我一直在寻找NAudio的例子,试图找出如何获得适合作为RTP有效载荷打包的ulaw样本。我正在尝试使用下面的代码从mp3文件生成样本。毫不奇怪,因为我并不知道我正在使用NAudio做什么,当我通过网络将样本传输到软电话时,我得到的都是静态的。
任何人都可以提供任何关于如何使用NAudio从MP3文件获取160字节(8Khz @ 20ms)ULAW样本的方向吗?
private void GetAudioSamples()
{
var pcmStream = WaveFormatConversionStream.CreatePcmStream(new Mp3FileReader("whitelight.mp3"));
byte[] buffer = new byte[2];
byte[] sampleBuffer = new byte[160];
int sampleIndex = 0;
int bytesRead = pcmStream.Read(buffer, 0, 2);
while (bytesRead > 0)
{
var ulawByte = MuLawEncoder.LinearToMuLawSample(BitConverter.ToInt16(buffer, 0));
sampleBuffer[sampleIndex++] = ulawByte;
if (sampleIndex == 160)
{
m_rtpChannel.AddSample(sampleBuffer);
sampleBuffer = new byte[160];
sampleIndex = 0;
}
bytesRead = pcmStream.Read(buffer, 0, 2);
}
logger.Debug("Finished adding audio samples.");
}
答案 0 :(得分:3)
以下是我最终实现它的方式。我确实失去了mp3中的一个频道,我想有一些方法可以将频道组合作为转换的一部分,但这对我的情况无关紧要。
160字节的缓冲区大小为我提供了20ms的ulaw样本,与我正在测试的SIP软电话完美配合。
var pcmFormat = new WaveFormat(8000, 16, 1);
var ulawFormat = WaveFormat.CreateMuLawFormat(8000, 1);
using (WaveFormatConversionStream pcmStm = new WaveFormatConversionStream(pcmFormat, new Mp3FileReader("whitelight.mp3")))
{
using (WaveFormatConversionStream ulawStm = new WaveFormatConversionStream(ulawFormat, pcmStm))
{
byte[] buffer = new byte[160];
int bytesRead = ulawStm.Read(buffer, 0, 160);
while (bytesRead > 0)
{
byte[] sample = new byte[bytesRead];
Array.Copy(buffer, sample, bytesRead);
m_rtpChannel.AddSample(sample);
bytesRead = ulawStm.Read(buffer, 0, 160);
}
}
}
答案 1 :(得分:2)
这里有一些指示。首先,只要您使用NAudio 1.5,就不需要额外的WaveFormatConversionStream - Mp3FileReader的Read方法返回PCM。
但是,你不会得到8kHz,所以你需要先重新取样。 WaveFormatConversionStream可以做到这一点,虽然它使用内置的Windows ACM采样率转换,它似乎不能很好地过滤传入的音频,因此可能存在别名伪像。
此外,由于MP3解码器需要一次解码一个帧(重采样器也希望处理更大的块大小),因此通常一次读取的块数大于两个字节。我会尝试一次读取至少20ms的字节数。
您使用BitConverter.ToInt16对于获取16位样本值是正确的,但请记住,MP3可能是立体声,左右样本。你确定你的手机需要立体声。
最后,我建议使用WaveFileWriter制作mu-law WAV文件作为第一步。然后,您可以在Windows Media Player中轻松收听,并检查您发送到您的软电话的内容是否符合您的预期。