From 563f16dc2a52de3217c90313ca6bddbbc20f20a0 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 22 Apr 2013 00:52:50 -0700 Subject: Fix overflow issues when converting float to int 32-bit floats can only reach between -16777215...+16777215 (25 bits) before it starts losing whole-number accuracy. Some compiler optimizations may break trying to multiply a float by 2147483647.0 when the result is given right to a float parameter, causing it instead to multiply by the nearest representable float value, 2147483648.0. --- Alc/ALu.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Alc/ALu.c b/Alc/ALu.c index 424b12ac..1288f7b2 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -912,24 +912,27 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) } -static __inline ALfloat aluF2F(ALfloat val) -{ return val; } -static __inline ALint aluF2I(ALfloat val) +static __inline ALint aluF2I25(ALfloat val) { /* Clamp the value between -1 and +1. This handles that with only a single branch. */ if(fabsf(val) > 1.0f) val = (ALfloat)((0.0f < val) - (val < 0.0f)); - /* Convert to a signed integer, between -2147483647 and +2147483647. */ - return fastf2i((ALfloat)(val*2147483647.0)); + /* Convert to a signed integer, between -16777215 and +16777215. */ + return fastf2i(val*16777215.0f); } + +static __inline ALfloat aluF2F(ALfloat val) +{ return val; } +static __inline ALint aluF2I(ALfloat val) +{ return aluF2I25(val)<<7; } static __inline ALuint aluF2UI(ALfloat val) { return aluF2I(val)+2147483648u; } static __inline ALshort aluF2S(ALfloat val) -{ return aluF2I(val)>>16; } +{ return aluF2I25(val)>>9; } static __inline ALushort aluF2US(ALfloat val) { return aluF2S(val)+32768; } static __inline ALbyte aluF2B(ALfloat val) -{ return aluF2I(val)>>24; } +{ return aluF2I25(val)>>17; } static __inline ALubyte aluF2UB(ALfloat val) { return aluF2B(val)+128; } -- cgit v1.2.3