Converting raw byte data to float[]
Solution 1
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;
}
Solution 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...
Solution 3
I assume that your byte[] doesn't contain the binary representation of floats, but either a sequence of Int8
s or Int16
s. 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;
}
Solution 4
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;
}
user488792
Updated on June 04, 2022Comments
-
user488792 almost 2 years
I have this code for converting a
byte[]
tofloat[]
.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 thebyte[]
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 convertingbyte[]
tofloat[]
? 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). -
Guffa about 13 yearsThat will convert each single byte into a float, not each group of four bytes into a float.
-
xanatos about 13 yearsIf you need the funcs for doubles and Int64, just ask. I had to make them some months ago for a project of mine.
-
Jeff Mercado about 13 yearsI suspect this ultimately is the problem. Though it should be noted that this modifies the array so might not be the best approach.
-
Jeff Mercado about 13 yearsHow is this relevant? Those numbers most likely came from a real float in that order. If converted as big-endian, it is a valid number (
-2.417114E+24
). You just can't change the data to get a real number. -
user488792 about 13 yearsHi and thanks! I tried with the IsLittleEndian approach and it does work! However, there are still values in the resulting float[] that have NaN values. What other problem could it be?
-
CodesInChaos about 13 years-2.41E+24 is a valid float, but typically not used in audio data, since audio data is typically restricted to -1 to 1. So I still think the byte array doesn't contain floats, but integer samples.
-
user488792 about 13 yearsHi and thanks for this! It works although there are still some NaN values so I think that endianness is only 1 part of the problem
-
xanatos about 13 years@user488792 How can you know it works then? Do you have some "reference" numbers?
-
vidstige about 13 years@Guffa ye, exactly. Clearified my answer a bit.
-
user488792 about 13 yearsI tried the other suggestion of one of the answers here, and I compared them to each other and they were (seemed to) be the same.
-
user488792 about 13 yearsHi! Thanks. Ill try to see if this works. Im only working with mono audio currently so I think thats one less problem. Im currently using BitConverter for my previous code so Ill try that first.
-
Jeff Mercado about 13 yearsC# uses the older IEEE 754-1985 standard, not IEEE 754-2008 as you have linked.