重新采样环回捕获

时间:2015-08-03 13:33:04

标签: c# naudio wasapi

我使用以下代码成功捕获了Wasapi的声音:

IWaveIn waveIn = new WasapiLoopbackCapture();
waveIn.DataAvailable += OnDataReceivedFromWaveOut;

我现在需要做的是将内存数据重新采样到pcm,采样率为8000,每个采样单声道16位。

我无法使用ACMStream重新取样示例,因为录制的音频是每秒32位。

我已经尝试过这段代码将字节从32位转换为16位,但我每次都得到的只是空白音频。

byte[] newArray16Bit = new byte[e.BytesRecorded / 2];
short two;
float value;
for (int i = 0, j = 0; i < e.BytesRecorded; i += 4, j += 2)
{
    value = (BitConverter.ToSingle(e.Buffer, i));
    two = (short)(value * short.MaxValue);

    newArray16Bit[j] = (byte)(two & 0xFF);
    newArray16Bit[j + 1] = (byte)((two >> 8) & 0xFF);
}

source = newArray16Bit;

1 个答案:

答案 0 :(得分:0)

我使用此例程从WASAPI IeeeFloat快速重新采样为我的应用程序所需的格式,该格式为16kHz,16位,1通道。我的格式是固定的,因此我在对所需的转换进行硬编码,但可以根据需要进行调整。

private void ResampleWasapi(object sender, WaveInEventArgs e)
{
    //the result of downsampling
    var resampled = new byte[e.BytesRecorded / 12];
    var indexResampled = 0;

    //a variable to flag the mod 3-ness of the current sample
    var arity = -1;

    var runningSamples = new short[3];
    for(var offset = 0; offset < e.BytesRecorded; offset += 8)
    {
        var float1 = BitConverter.ToSingle(e.Buffer, offset);
        var float2 = BitConverter.ToSingle(e.Buffer, offset + 4);

        //simple average to collapse 2 channels into 1
        float mono = (float)((double)float1 + (double)float2) / 2;

        //convert (-1, 1) range int to short
        short sixteenbit = (short)(mono * 32767);

        //the input is 48000Hz and the output is 16000Hz, so we need 1/3rd of the data points
        //so save up 3 running samples and then mix and write to the file
        arity = (arity + 1) % 3;

        //record the value
        runningSamples[arity] = sixteenbit;

        //if we've hit the third one
        if (arity == 2)
        {
            //simple average of the 3 and put in the 0th position
            runningSamples[0] = (short)(((int)runningSamples[0] + (int)runningSamples[1] + (int)runningSamples[2]) / 3);

            //copy that short (2 bytes) into the result array at the current location
            Buffer.BlockCopy(runningSamples, 0, resampled, indexResampled, 2);

            //for next pass
            indexResampled += 2;
        }
    }

    //and tell listeners that we've got data
    RaiseDataEvent(resampled, resampled.Length);
}