我将如何使用 NAudio 压缩来自麦克风的传入 PCM 数据?

Posted

技术标签:

【中文标题】我将如何使用 NAudio 压缩来自麦克风的传入 PCM 数据?【英文标题】:How would I use NAudio to compress incoming PCM data from the microphone? 【发布时间】:2019-05-13 00:31:27 【问题描述】:

我正在开发一个 VOIP 应用程序,它将使用 NAudio 通过网络传输音频数据。由于带宽问题,我不想流式传输原始 PCM,所以我试图用 μ-law 对样本进行编码。到目前为止,我一直无法找到任何关于这是如何完成的解释。我假设我应该使用NAudio.Codecs.MuLawEncoder.LinearToMuLawSample(short s),但问题是我在 DataAvailable 事件中获得了一个字节数组。

我尝试遍历 DataAvailable 缓冲区,在每个字节上调用 LinearToMuLawSample。但是,数组的实际大小显然没有改变,因此我没有减少任何大小。

这是负责编码的代码:

byte[] sample = _rawSamples.Take(); //take from sample buffer

for (int i = 0; i < sample.Length; i++) //actual conversion code
    sample[i] = MuLawEncoder.LinearToMuLawSample(sample[i]);

_encodedSamples.Add(sample); //add to network buffer

这是我的 DataAvailable 处理程序的内容:

private void _input_DataAvailable(object sender, WaveInEventArgs e)

    byte[] buffer = e.Buffer;
    Array.Resize(ref buffer, e.BytesRecorded);

    _rawSamples.Add(audioData);

最后,这是我声明 WaveIn 的方式:

_input = new WaveIn();
_input.BufferMilliseconds = 100;
_input.DataAvailable += _input_DataAvailable;
_input.RecordingStopped += _input_InputRecordingStopped;

本质上,我正在寻找一种以字节数组形式获取 PCM 数据并将其转换为适合通过网络发送的格式的方法。我不太明白 MuLawEncoder 类如何以这种方式实际编码/压缩音频数据。

【问题讨论】:

即使输入是字节数组,单个样本的大小是多少?在this example 中,样本是 16 位的,因此它们将输入数组中的每对字节解释为 16 位整数,然后再将其传递给编码器... 我正在使用 16 位音频。那么这个示例代码将原始 PCM 的大小减半? 是的,你没看错。 一个很好的起点是查看 NAudioDemo 项目中网络聊天演示的代码。它显示了基本的麦克风捕获,而 Mulaw 是可用的编解码器之一 【参考方案1】:

更新

我能够使用https://github.com/naudio/NAudio/blob/master/NAudioDemo/NetworkChatDemo/ 中的示例使其正常工作。以下是我最终使用的关键功能:

private byte[] EncodeSamples(byte[] data)

    byte[] encoded = new byte[data.Length / 2];
    int outIndex = 0;

    for (int n = 0; n < data.Length; n += 2)
        encoded[outIndex++] = MuLawEncoder.LinearToMuLawSample(BitConverter.ToInt16(data, n));

    return encoded;


private byte[] DecodeSamples(byte[] data)

    byte[] decoded = new byte[data.Length * 2];
    int outIndex = 0;
    for (int n = 0; n < data.Length; n++)
    
        short decodedSample = MuLawDecoder.MuLawToLinearSample(data[n]);
        decoded[outIndex++] = (byte)(decodedSample & 0xFF);
        decoded[outIndex++] = (byte)(decodedSample >> 8);
    
    return decoded;

关键是一次遍历两个字节的数据,将每一对转换为 Int16,将其传递给 LinearToMuLawSample,并将返回值打包成一个大小为一半的新数组。

【讨论】:

以上是关于我将如何使用 NAudio 压缩来自麦克风的传入 PCM 数据?的主要内容,如果未能解决你的问题,请参考以下文章

abt naudio 输入和输出设备

如何拆分和管道多个 NAudio 流

记录来自 NAudio WaveIn 的输入,并输出到 NAudio WaveOut

如何使用 NAudio 将麦克风(mic-in)设置为默认值?

记录来自 NAudio WaveIn 的输入,并将输出保存到字节数组

使用 NAudio 发送正在播放的音频