Search code examples
numberslazarusfloating24-bit

how to convert 3 bytes in little endian order to a floating number from -1 to +1


I have 3 bytes in little-endian. these are: Top, Middle and Bottom (from bit 23 to bit 0) How can I convert them to a float number from -1 to +1?

3 bytes are in little-endian because there is the string RIFF In the wav so min value is (0x7FFFFF) and the max value is (0x800000)

http://www.labbookpages.co.uk/audio/javaWavFiles.html

for a 16 bit wav: the wave frames are in 2s complementary binary between -32768; 0x8000 and 32767; 0x7FFF)


Solution

  • The link you provide looks wrong to me. Surely the 24 bit format uses standard two's complement arithmetic. In which case 0x7FFFFF represents -8388608 and 0x800000 represents 8388607.

    On that basis you use this function to convert your three bytes into a signed integer value:

    function TwosComplement24(const Bytes): Integer;
    begin
      Result := 0;
      Move(Bytes, Result, 3);
      Result := (Result and $7fffff) - (Result and $800000);
    end;
    

    Once you have that in place, you can convert to a floating point value like this:

    function Sample24toReal(const Bytes): Double;
    begin
      Result := TwosComplement24(Bytes) / 8388608;
    end;
    

    I've used an untyped parameter for the 3 bytes, but you may want to do it differently depending on how you read the data.

    Also, this code is written assuming that it runs on a little endian machine. If the data is little endian, and the machine is big endian, then you would need to reverse each group of three bytes.