将 NAudio 的 float[] 转换为 byte[]

Posted

技术标签:

【中文标题】将 NAudio 的 float[] 转换为 byte[]【英文标题】:Convert float[] to byte[] for NAudio 【发布时间】:2016-01-27 17:58:20 【问题描述】:

我从通过 getUserMedia 捕获的浏览器接收到表示音频样本数组的字符串。 getUserMedia 在 48000 录制,我在将字符串值发送到服务器之前交错了 2 个通道。我把这个字符串变成一个 float[] 像这样:

string[] raw = buffer.ToString().Split(new char[] ',' );
float[] fArray = new float[raw.Length];
for (int x = 0; x < raw.Length; x++)

     float sampleVal = float.Parse(raw[x]);
     fArray[x] = sampleVal;

我想做的是将 float[] 数组转换为 byte[] 数组,以便我可以将它传递给 BufferedWaveProvider (48000, 16, 1) 进行播放。以下是我目前尝试进行转换的方式:

byte[] bSamples = new byte[fArray.Length * 2];
for (int x = 0; x < fArray.Length; x += 2)

    short sSample = (short)Math.Floor(fArray[x] * 32767);

    byte[] tmp = BitConverter.GetBytes(sSample);
    bSamples[x] = tmp[0];
    bSamples[x + 1] = tmp[1];

使用上面的代码,只会产生垃圾。谁能指出我进行此类转换的正确方向?

我见过this,但它没有把我带到我需要去的地方。

【问题讨论】:

我在这方面取得了一些进展。转换循环应该更像这样: int destOffset = 0; byte[] destArray = new byte[fArray.Length * 2]; for (int x = 0; x 但这仍然没有产生任何接近被记录的东西。 更新 2:如果我将输入源 (getUserMedia) 更改为仅使用 1 个通道,而不是交错 2 个通道,我可以重现声音。 考虑编辑更新问题,而不是将它们作为 cmets 发布。它为未来的读者提供了一个更加连贯和有用的问题。 【参考方案1】:

为时已晚,但仍然有用 - 我已经发布了从 float[] samples 数组到 byte[] 数组的转换代码 https://***.com/a/42151979/4778700

【讨论】:

【参考方案2】:

看起来您的索引在第二个循环中不太正确。您正在循环遍历 float 样本,并在 short 输出中使用相同的索引:

for (int x = 0; x < fArray.Length; x += 2)

另一件事(假设浮点输入是真正的 IEEE 32 位浮点样本,范围为 [-1.0,1.0],因此我们不必担心转换)。是立体声输入吗?如果是这样,那么您需要在转换为“短”之前合并样本。这很容易做到。只需平均连续的float 值对(左通道/右通道)。

输出数组的大小应该是正确的。从技术上讲,它会是这样的:

int inchannels = 2;  // doesn't have to be a variable, but shows 'stereo' input.
int numsamples = fArray.Length / inchannels;
byte [] bSamples = new byte [numsamples * sizeof(Int16)];

那么您应该可以进行如下转换。请注意,这是假设立体声输入,因此它会平均浮点样本。

int outindex = 0;
for( int inindex = 0; inindex < fArray.Length; inindex += 2 )

    // 'insample' is the average of left and right channels.  This isn't
    // entirely accurate - if one channel is 0.0, then we should just use
    // the other channel verbatim.  But this is close enough.
    float insample = (fArray[inindex] + fArray[inindex+1]) / 2.0f;

    // The output sample.  It's probably better to use Int16.MaxValue
    // than the hard-coded value.
    Int16 outsample = (Int16)(insample * (float)Int16.MaxValue);

    // I'm old-school, so I'm a fan of 'unsafe'.  But you can use the
    // BitConverter that you were already using.  Actually, I would've
    // probably done this entire conversion in 'unsafe' mode.
    unsafe
    
        fixed( byte * pbyte = &bSamples[outindex] )
        
            Int16 * p = (Int16 *)pbyte;
            *p = outsample;
            outindex += sizeof(Int16);
        
    

【讨论】:

以上是关于将 NAudio 的 float[] 转换为 byte[]的主要内容,如果未能解决你的问题,请参考以下文章

将 32 位浮点音频转换为 16 位字节数组?

使用 NAudio 将 g722 音频转换为 WAV

即时将原始音频字节从 NAudio 转换为 wav 字节

使用 NAudio 将 WAV 流转换为 Opus

如何使用 NAudio 将任何音频格式转换为 mp3

Naudio mvc 将 mp3 转换为 wav