4

我有此代码用于将 a 转换byte[]float[].

public float[] ConvertByteToFloat(byte[] array)
{
    float[] floatArr = new float[array.Length / sizeof(float)];
    int index = 0;
    for (int i = 0; i < floatArr.Length; i++)
    {
        floatArr[i] = BitConverter.ToSingle(array, index);
        index += sizeof(float);
    }
    return floatArr;
}

问题是,我通常会得到一个NaN结果!为什么会这样?我检查了是否有数据,byte[]数据似乎很好。如果有帮助,这些值的示例是:

new byte[] {
    231,
    255,
    235,
    255,
}

但这NaN在转换为浮点数后返回 (Not a Number)。可能是什么问题呢?还有其他更好的转换byte[]方式float[]吗?我确信读入缓冲区的值是正确的,因为我将它与我的其他程序(对 .wav 文件执行放大)进行了比较。

4

5 回答 5

4

If endianness is the problem, you should check the value of BitConverter.IsLittleEndian to determine if the bytes have to be reversed:

public static float[] ConvertByteToFloat(byte[] array) {
  float[] floatArr = new float[array.Length / 4];
  for (int i = 0; i < floatArr.Length; i++) {
    if (BitConverter.IsLittleEndian) {
      Array.Reverse(array, i * 4, 4);
    }
    floatArr[i] = BitConverter.ToSingle(array, i * 4);
  }
  return floatArr;
}
于 2011-02-20T11:30:48.723 回答
2

Isn't the problem that the 255 in the exponent represents NaN (see Wikipedia in the exponent section), so you should get a NaN. Try changing the last 255 to something else...

于 2011-02-20T11:26:42.300 回答
1

If it's the endianness that is wrong (you are reading big endian numbers) try these (be aware that they are "unsafe" so you have to check the unsafe flag in your project properties)

public static unsafe int ToInt32(byte[] value, int startIndex)
{
    fixed (byte* numRef = &value[startIndex])
    {
        var num = (uint)((numRef[0] << 0x18) | (numRef[1] << 0x10) | (numRef[2] << 0x8) | numRef[3]);
        return (int)num;
    }
}

public static unsafe float ToSingle(byte[] value, int startIndex)
{
    int val = ToInt32(value, startIndex);
    return *(float*)&val;
}
于 2011-02-20T11:28:15.107 回答
1

我假设您的 byte[] 不包含浮点数的二进制表示,而是包含Int8s 或Int16s 的序列。您发布的示例看起来不像基于浮点数的音频样本(NaN 和 -2.41E+24 都不在 -1 到 1 的范围内。虽然一些新的音频格式可能支持超出该范围的浮点数,但传统上音频数据由带符号的8 或 16 位整数样本。

您需要注意的另一件事是,不同的通道通常是交错的。例如,它可能包含左声道的第一个样本,然后是右声道,然后是两者的第二个样本......所以你需要在解析时分离声道。

样本未签名也是可能的,但不常见。在这种情况下,您需要从转换函数中删除偏移量。

因此,您首先需要将字节数组中的当前位置解析为 Int8/16。然后将该整数转换为 -1 到 1 范围内的浮点数。

如果格式是小端,您可以使用 BitConverter。另一种适用于两种字节序的可能性是手动获取两个字节并将它们与位移相结合。我不记得小端或大端是否常见。所以你需要自己尝试一下。

这可以通过以下功能来完成(我没有测试它们):

float Int8ToFloat(Int8 i)
{
  return ((i-Int8.MinValue)*(1f/0xFF))-0.5f;
}

float Int16ToFloat(Int16 i)
{
  return ((i-Int16.MinValue)*(1f/0xFFFF))-0.5f;
}
于 2011-02-20T12:34:59.220 回答
0

取决于您希望如何将字节转换为浮点数。首先尝试确定字节数组中实际存储的内容。也许有文件格式规范?代码中的其他转换?

在这种情况下,每个字节都应转换为 0 到 255 之间的浮点数:

public float[] ConvertByteToFloat(byte[] array)
{
    return array.Select(b => (float)b).ToArray();
}

如果字节数组包含浮点数的二进制表示,则有多种表示,并且如果存储在文件中的表示与c# 语言标准浮点表示 ( IEEE 754 )不匹配,则会发生类似这样的奇怪事情。

于 2011-02-20T11:19:47.243 回答