Question

I have this code for converting a byte[] to 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;
}

Problem is, I usually get a NaN result! Why should this be? I checked if there is data in the byte[] and the data seems to be fine. If it helps, an example of the values are:

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

But this returns NaN (Not a Number) after conversion to float. What could be the problem? Are there other better ways of converting byte[] to float[]? I am sure that the values read into the buffer are correct since I compared it with my other program (which performs amplification for a .wav file).

Was it helpful?

Solution

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

OTHER TIPS

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...

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

I assume that your byte[] doesn't contain the binary representation of floats, but either a sequence of Int8s or Int16s. The examples you posted don't look like audio samples based on float (neither NaN nor -2.41E+24 are in the range -1 to 1. While some new audio formats might support floats outside that range, traditionally audio data consists of signed 8 or 16 bit integer samples.

Another thing you need to be aware of is that often the different channels are interleaved. For example it could contain the first sample for the left, then for the right channel, and then the second sample for both... So you need to separate the channels while parsing.

It's also possible, but uncommon that the samples are unsigned. In which case you need to remove the offset from the conversion functions.

So you first need to parse current position in the byte array into an Int8/16. And then convert that integer to a float in the range -1 to 1.

If the format is little endian you can use BitConverter. Another possibility that works with both endiannesses is getting two bytes manually and combining them with a bit-shift. I don't remember if little or big endian is common. So you need to try that yourself.

This can be done with functions like the following(I didn't test them):

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

float Int16ToFloat(Int16 i)
{
  return ((i-Int16.MinValue)*(1f/0xFFFF))-0.5f;
}

Depends on how you want to convert the bytes to float. Start out by trying to pin-point what is actually stored in the byte array. Perhaps there is a file format specification? Other transformations in your code?

In the case each byte should be converted to a float between 0 and 255:

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

If the bytes array contains binary representation of floats, there are several representation and if the representation stored in your file does not match the c# language standard floating point representation (IEEE 754) weird things like this will happen.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top