16 to 32 bit floating point conversions
-
- KVRist
- 334 posts since 18 Apr, 2005 from Sweden
I'm in the process of writing a class to read in AIFF files into memory. While AIFF supports up to 32 bit floating point values, it's more common to see 16 and 24 bit values instead. My question is, how exactly do I go about reading the raw 16-bit values from disk and converting them internally to 32 bit floats? I've read the documentation on the IEEE 754 specs, but am still not clear as to how to actually make this conversion happen.... any ideas?
:: Teragon Audio ::
-
- KVRist
- 76 posts since 27 Jan, 2005
Eh.. I probably don't get what you mean, but what's wrong with simply typecasting and scaling?
-
- KVRist
- Topic Starter
- 334 posts since 18 Apr, 2005 from Sweden
-
- KVRAF
- 4738 posts since 20 Feb, 2004 from Gothenburg, Sweden
- KVRian
- 513 posts since 6 Jul, 2005 from Berlin
[ Ghetto answer removed cause stefancr's reply is much more elegant
]
Last edited by dblue on Wed Jun 07, 2006 4:34 pm, edited 2 times in total.
I'm Kieran, aka dblue, aka illformed | illformed.com | Glitch 2 now available for Windows, Mac and Linux!
-
- KVRist
- Topic Starter
- 334 posts since 18 Apr, 2005 from Sweden
Thanks for the suggestions, guys. Let me try these out and see if I can't get things working. 
:: Teragon Audio ::
-
- KVRist
- 76 posts since 27 Jan, 2005
Ok, so nothing wrong with simply typecasting and scaling 
-
- KVRist
- Topic Starter
- 334 posts since 18 Apr, 2005 from Sweden
Yeah, I guess not.... I think all the mantissa/exponent stuff freaked me out a bit.BarendB wrote:Ok, so nothing wrong with simply typecasting and scaling
:: Teragon Audio ::
-
- KVRAF
- 4222 posts since 23 Feb, 2004 from Tucson Arizona USA
It is really not that bad. The only weird things about it are the bias in the exponent, and the fact that the mantissa is normalized. But if you practice with the formats just for a little while, it will be clear why these are good ideas.sqook wrote:Yeah, I guess not.... I think all the mantissa/exponent stuff freaked me out a bit.BarendB wrote:Ok, so nothing wrong with simply typecasting and scaling
As for converting from 32 bit to 16 bit, you must be willing to give up both precision and scale (of course). But you also have to decide whether you want your conversion to be direct and only consider those 32-bit floats that fit in the same scale as 16 bit floats (and overflow the rest), OR whether you want to map the 32-bit float range as a proportional scale, and approximate that scale in 16-bit.
-
- KVRist
- 76 posts since 27 Jan, 2005
That's imaginablesqook wrote:Yeah, I guess not.... I think all the mantissa/exponent stuff freaked me out a bit.
Code: Select all
int iVal = (int&)fVal & 0x7FFFFFFF;
fVal = (float&)iVal;Code: Select all
fVal += 1.f;
unsigned int iVal = (((unsigned int&)fVal) & 0x7FFFFF) << 9; // use 23bits mantissa
Last edited by BarendB on Wed Jun 07, 2006 6:06 pm, edited 3 times in total.
-
- KVRAF
- 4222 posts since 23 Feb, 2004 from Tucson Arizona USA
Oops, my apologies, you want to up-scale 16 to 32 bit. I'm sure I'd still do it by padding the mantissa and re-scaling the exponent. It can be done with only logic and an add operation.
I'd try to avoid any floating point divide if at all possible.
I'd try to avoid any floating point divide if at all possible.
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
Exactly what stefancrs said works, and with no divide, because, as the value that's divided by is a constant, it should optimize to...james0tucson wrote:Oops, my apologies, you want to up-scale 16 to 32 bit. I'm sure I'd still do it by padding the mantissa and re-scaling the exponent. It can be done with only logic and an add operation.
I'd try to avoid any floating point divide if at all possible.
float val = (float)(int16_value) * 0.000030517578125f;
...automatically, by the compiler. No?
(I don't actually know, cuz I always code them this way just to be sure. But I'd hope any complier would optimize divides by constants.)
-
- KVRAF
- 4222 posts since 23 Feb, 2004 from Tucson Arizona USA
A floating point multiply is the same problem as a floating point divide.AdmiralQuality wrote:Exactly what stefancrs said works, and with no divide, because, as the value that's divided by is a constant, it should optimize to...james0tucson wrote:Oops, my apologies, you want to up-scale 16 to 32 bit. I'm sure I'd still do it by padding the mantissa and re-scaling the exponent. It can be done with only logic and an add operation.
I'd try to avoid any floating point divide if at all possible.
float val = (float)(int16_value) * 0.000030517578125f;
...automatically, by the compiler. No?
(I don't actually know, cuz I always code them this way just to be sure. But I'd hope any complier would optimize divides by constants.)
I'm quite sure I would convert a 16-bit float to a 32-bit float as follows, that is if performance was an issue at all. (If it's not an optimization opportunity in the first place, then who cares??)
1. Set the sign bit of the new value
2. Set the mantissa by padding the 10 bit mantissa to the 23 bits of the target.
3. subtract the bias from the 5 bit exponent
4. AND the target with the normalized 8 bit value of the exponent
No multiply or divide involved.
If you want to scale the 32-bit values proportional to the 16-bit values, that's different. (I still think that can be done with only shifts, though.)
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
Could you write all that out in code though so I can actually see what you mean, and then tell me again it's more efficient than a cast and a mult? (And, if it was, wouldn't the cast do it your way too?)james0tucson wrote: A floating point multiply is the same problem as a floating point divide.
I'm quite sure I would convert a 16-bit float to a 32-bit float as follows, that is if performance was an issue at all. (If it's not an optimization opportunity in the first place, then who cares??)
1. Set the sign bit of the new value
2. Set the mantissa by padding the 10 bit mantissa to the 23 bits of the target.
3. subtract the bias from the 5 bit exponent
4. AND the target with the normalized 8 bit value of the exponent
No multiply or divide involved.
If you want to scale the 32-bit values proportional to the 16-bit values, that's different. (I still think that can be done with only shifts, though.)
And I assume you mean by proportional scale that we want the int range -32768..32767 to map to -1.0..1.0 in floats? What OTHER way would anyone EVER want to do this? How can you do this without a multiply somewhere?
If you did mash it up into an out of scale float, you're just going to have to scale it again (probably, depending on your application). But assuming you're reading wave data, you'd want 0 dB to come out as 0dB 99% of the time.
Sorry if I'm not getting something. Please show us in code to clarify? Maybe we can do a little test.
-
- KVRist
- 76 posts since 27 Jan, 2005
Actually, that IS possible. This code will convert and scale an unsigned int sample value (iVal) in the range [0..32767] to a float in the range [0..1], without any multiplication:AdmiralQuality wrote:And I assume you mean by proportional scale that we want the int range -32768..32767 to map to -1.0..1.0 in floats? What OTHER way would anyone EVER want to do this? How can you do this without a multiply somewhere?
Code: Select all
iVal = (iVal << 8) | 0x3F800000;
float fVal = (float&)iVal - 1.f;
Last edited by BarendB on Thu Jun 08, 2006 1:02 pm, edited 1 time in total.

