将原始字节数据转换为float []

时间:2011-02-20 11:10:33

标签: c# byte bitconverter

我有此代码用于将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,
}

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

5 个答案:

答案 0 :(得分:4)

如果endianness是问题,您应该检查BitConverter.IsLittleEndian的值以确定是否必须颠倒字节:

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

答案 1 :(得分:2)

指数中的255表示NaN不是问题(请参阅指数部分中的Wikipedia),因此您应该得到NaN。尝试将最后255个更改为其他内容......

答案 2 :(得分:1)

如果这是错误的字节顺序(你正在读大端数字)尝试这些(请注意它们是“不安全的”所以你必须检查项目属性中的unsafe标志)

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

答案 3 :(得分:1)

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

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

样本也是无符号的,但也不常见。在这种情况下,您需要从转换函数中删除偏移量。

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

如果格式为little endian,则可以使用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;
}

答案 4 :(得分:0)

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

如果每个字节都应转换为0到255之间的浮点数:

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

如果bytes数组包含浮点数的二进制表示,则有几种表示形式,如果存储在文件中的表示形式与c# language标准浮点表示形式(IEEE 754)不匹配,这样的奇怪事情将会发生。