mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-02-16 22:05:31 -05:00
audioconvert: avoid even more precision loss in F32 to S32 conversion
This is somewhat similar to the S32->F32 conversion improvements, but here things a bit more tricky... The main consideration is that the limits to which we clamp must be valid 32-bit signed integers, but not all such integers are exactly losslessly representable in `float32_t`. For example it we'd clamp to `2147483647`, that is actually a `2147483648.0f`, and `2147483648` is not a valid 32-bit signed integer, so the post-clamp conversion would basically be UB. We don't have this problem for negative bound, though. But as we know, any 25-bit signed integer is losslessly round-trippable through float32_t, and since multiplying by 2 only changes the float's exponent, we can clamp to `2147483520`! The algorithm of selection of the pre-clamping scale is unaffected. This additionally avoids right-shift, and thus is even faster. As `test_lossless_s32_lossless_subset` shows, if the integer is in the form of s25+shift, the maximal absolute error is finally zero. Without going through `float`->`double`->`int`, i'm not sure if the `float`->`int` conversion can be improved further.
This commit is contained in:
parent
f4c89b1b40
commit
7c40cafa7c
4 changed files with 50 additions and 70 deletions
|
|
@ -121,10 +121,14 @@
|
|||
|
||||
#define S32_MIN -2147483648
|
||||
#define S32_MAX 2147483647
|
||||
#define S32_SCALE 2147483648.0f
|
||||
#define S32_TO_F32(v) ITOF(int32_t, v, S32_SCALE, 0.0f)
|
||||
#define S32_SCALE_I2F 2147483648.0f
|
||||
#define S32_TO_F32(v) ITOF(int32_t, v, S32_SCALE_I2F, 0.0f)
|
||||
#define S32S_TO_F32(v) S32_TO_F32(bswap_32(v))
|
||||
#define F32_TO_S32_D(v,d) S25_32_TO_S32(F32_TO_S25_32_D(v,d))
|
||||
|
||||
#define S32_MIN_F2I ((int32_t)(((uint32_t)(S25_MIN)) << 7))
|
||||
#define S32_MAX_F2I ((S25_MAX) << 7)
|
||||
#define S32_SCALE_F2I (-((float)(S32_MIN_F2I)))
|
||||
#define F32_TO_S32_D(v,d) FTOI(int32_t, v, S32_SCALE_F2I, 0.0f, d, S32_MIN_F2I, S32_MAX_F2I)
|
||||
#define F32_TO_S32(v) F32_TO_S32_D(v, 0.0f)
|
||||
#define F32_TO_S32S(v) bswap_32(F32_TO_S32(v))
|
||||
#define F32_TO_S32S_D(v,d) bswap_32(F32_TO_S32_D(v,d))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue