使用NAudio获取RTP的Ulaw样本

时间:2012-02-29 11:29:23

标签: c# rtp naudio

我一直在寻找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.");
}

2 个答案:

答案 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中轻松收听,并检查您发送到您的软电话的内容是否符合您的预期。