issue with conversions from 24 bit signed int to 32 bit float and back

Hello.
24_bit_int.wav is signed 24 bit PCM, no clipping.

I perform the following:
24_bit_int.wav → 24_bit_int.raw (format is signed 24 bit PCM)
24_bit_int.wav → 32_bit_float.wav
32_bit_float.wav → 24_bit_int_back.raw (no manipulation with 32_bit_float.wav was done in-between.)
Then I compare
vbindiff 24_bit_int.raw 24_bit_int_back.raw
and see a lot off differences.

Although they must be identical.
I assume the conversion of each wav-value must be like this:
0 → 0.0 → 0
-1 → -1.0 → -1
1 → 1.0 → 1
etc. up to max/min 24 bit int values.
(I don’t go here in details of float representation format).
In C/C++, simple cast from int to float and back will do the job when int is 24 bit signed integer and float is 32 bit signed float.

I can add I tried the same conversions with SOX. vbindiff shows no differences as expected.
Although I noticed sox works incorrectly with 32 bit float wav-files if they exceed [-144db…0db] range. But this is different issue with sox.

Please advise.

P.S. I use Audacity 3.0.2 on macOS 10.9.5 (since the latest version doesn’t work, although announced as compliant with macOS 10.7 - macOS 12)

If you are doing that with Audacity, the conversion actually goes like this:

24_bit_int.wav → 32-bit float → 24_bit_int.raw

because Audacity always uses 32-bit float when processing audio.

This part:
24_bit_int.wav → 32-bit float
is not a problem because 32-bit float can represent all 24-bit int values exactly.

This part:
32-bit float → 24_bit_int.raw
needs some care, because Audacity doesn’t know if the 32-bit float values can convert to 24-bit int exactly, or require rounding.
By default, Audacity assumes that rounding will be required (even though in this special case “we” know that all the samples can be represented exactly). So Audacity applies dither for better quality rounding.
Since “we” know that rounding is not required, we can temporarily turn it of in
“Edit menu > Preferences > Quality > High quality conversion - Dither: None”

With dither turned off, the round trip from 24_bit_int.wav → → 24_bit_int.raw should be perfect.

Clear. Thank you!

Would like to note that before the conversion 32bit float → 24bit int, audacity can check if the data contain values which cannot be converted to 24bit ints and base on that decide whether the dithering is needed or not.
If the dithering is needed, some warning message would be nice.

That would require Audacity to check every sample, which would pretty well double the time to export - that would not be popular with people that work on big projects.