将 float[] 转换为 NAudio 的字节 []

本文关键字:字节 NAudio 转换 float | 更新日期: 2023-09-27 18:32:19

>我收到一个字符串,表示通过getUserMedia捕获的浏览器的音频样本数组。 getUserMedia 正在以 48000 的速度录制,在将字符串值发送到服务器之前,我交错了 2 个通道。 我把这个字符串变成一个浮点[],如下所示:

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];
}

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

我已经看到了这个,但它并没有让我到达我需要去的地方。

将 float[] 转换为 NAudio 的字节 []

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

看起来您的索引在第二个循环中不太正确。 您正在循环访问float示例,并在short输出中使用相同的索引:

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

另一件事(假设浮点输入是 [-1.0,1.0] 范围内的 IEEE 32 位浮点样本,因此我们不必担心转换)。 是立体声输入吗? 如果是这样,那么您需要在转换为"short"之前合并样本。 这很容易做到。 只是平均连续的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);
        }
    }
}