将音频信号从存储器流分配到帧。字节数组[C#]

时间:2017-03-21 18:03:42

标签: c# audio stream memorystream

我正在尝试在c#中实现VAD(语音活动检测)算法,因为我没有为此目的找到任何合适的库。 我不使用波形文件,但只使用内存流,如下所示:

        NAudio.Wave.WaveFileWriter waveWriter;

        Stream s1 = new MemoryStream();
        WaveInEvent waveSource = new WaveInEvent();
        waveSource.WaveFormat = new NAudio.Wave.WaveFormat(16000, 16, 1);

        waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
        waveWriter = new NAudio.Wave.WaveFileWriter(s1, waveSource.WaveFormat);

        waveSource.StartRecording();
        Console.ReadLine();
        waveSource.StopRecording();
        s1.Position = 0;
        var bytes = streamToArray(s1);

我将遵循这个tutorial,其中第一步是将输入信号分割为10ms帧。我知道如何从文件输入中执行此操作,但如何使用字节数组执行类似的操作? 谢谢你的回答!

更新

我测试了这些方法:

1

short[] sdata = new short[(int)Math.Ceiling(bytes.Length / 2.0)]; 
Buffer.BlockCopy(bytes, 0, sdata, 0, bytes.Length);

2

 for (var i = 0; i < bytes.Length; i += 2)
            {
                var b1 = (short)bytes[i];
                var b2 = (short)bytes[i + 1];
                sListData.Add((short)(b1 | b2 << 8));
            }

当我将输出数组与使用Big Endian的方法进行比较时,它们都是相同的。 所以BlockCopy完成了这项工作,但只有当BE合适时才能完成。

1 个答案:

答案 0 :(得分:0)

不是100%肯定这是不是你的意思,但是: 假设音频流参数为16kbp,每个样本16bit,单通道,这是一个非常快速的计算,如果16000个样本是1秒,那么10ms是16000/100 = 160个样本。现在16位是2个字节,它给我们160 * 2 = 320字节。 所以每个320字节是10ms。 您可以使用Array.Copy - https://msdn.microsoft.com/en-us/library/z50k9bft(v=vs.110).aspx将chunk od数据复制到单独的数组中。

下面只是一些代码:

var int8Array = new byte [] {0x04,0x02,0x08,0xA1};

var int16ArrayLE = new List<short>();
var int16ArrayBE = new List<short>();

for(var i=0;i<int8Array.Length;i+=2) 
{
    var b1 = (short)int8Array[i];
    var b2 = (short)int8Array[i+1];
    int16ArrayLE.Add((short)((b1 << 8) + b2));
    int16ArrayBE.Add((short)(b1 + (b2 << 8)));
}

.net短类型是16位整数,字节是8位整数。代码对可读性有点明确。我展示了两种可能的转换 - Little Endian和Big Endian。在前者中,第一个字节在后一个第二个字节中更为重要。字节顺序取决于流格式,可以是。