audioconvert: introduce s25_32 type, f32<->s25 cast is lossless

The largest integer that 32-bit floating point can exactly represent
is actually `(2^24)-1`, not`(2^23)-1` like the code assumes.
This means, whenever we use s24 as an intermediate step
to go between f32 and s32, we lose a bit of precision.

s25_32 is really a i32 with highest byte always being a sign byte.

Printing was done by adding
```
for(int e = 0; e != 13; ++e)
fprintf(stderr, "%16.32e,", ((float*)m1)[e]);
```
to `compare_mem`. I don't like how these tests work.

https://godbolt.org/z/abe94sedT
This commit is contained in:
Roman Lebedev 2024-06-13 16:18:33 +03:00
parent 7b4c0dd5ec
commit 2a035ac49e
No known key found for this signature in database
GPG key ID: 083C3EBB4A1689E0
2 changed files with 131 additions and 9 deletions

View file

@ -88,6 +88,18 @@
#define U32_TO_U24_32(v) (((uint32_t)(v)) >> 8)
#define S25_MIN -16777216
#define S25_MAX 16777215
#define S25_SCALE 16777216.0f
#define S25_32_TO_F32(v) ITOF(int32_t, v, S25_SCALE, 0.0f)
#define S25_32S_TO_F32(v) S25_32_TO_F32(bswap_32(v))
#define F32_TO_S25_32_D(v,d) FTOI(int32_t, v, S25_SCALE, 0.0f, d, S25_MIN, S25_MAX)
#define F32_TO_S25_32(v) F32_TO_S25_32_D(v, 0.0f)
#define F32_TO_S25_32S(v) bswap_32(F32_TO_S25_32(v))
#define F32_TO_S25_32S_D(v,d) bswap_32(F32_TO_S25_32_D(v,d))
#define S25_32_TO_S32(v) ((int32_t)(((uint32_t)(v)) << 7))
#define S32_TO_S25_32(v) (((int32_t)(v)) >> 7)
#define U32_MIN 0u
#define U32_MAX 4294967295u
#define U32_SCALE 2147483648.f