You do not sign 24 bits in an integer; high bits will always be zero. This code will work regardless of your int size:
if (i & 0x800000) i |= ~0xffffff;
Edit: Problem 2 is your scaling constant. Simply put, you want to multiply by a new maximum and divide by the old maximum, assuming that 0 remains at 0.0 after the conversion.
const float Q = 1.0 / 0x7fffff;
Finally, why are you adding 0.5 to the final conversion? I could understand if you are trying to round to an integer value, but you are going in a different direction.
Edit 2: The source you are pointing to has a very detailed rationale for your choices. Not as I would have chosen, but perfectly justified, nonetheless. My advice for the multiplier is still there, but the maximum is different due to the 0.5 factor added:
const float Q = 1.0 / (0x7fffff + 0.5);
Since after adding the positive and negative values โโcoincide, this should correctly scale both directions.
Mark ransom
source share