aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
Diffstat (limited to 'Alc')
-rw-r--r--Alc/effects/pshifter.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/Alc/effects/pshifter.c b/Alc/effects/pshifter.c
index bf36f5eb..7411f705 100644
--- a/Alc/effects/pshifter.c
+++ b/Alc/effects/pshifter.c
@@ -108,8 +108,32 @@ static alonce_flag HannInitOnce = AL_ONCE_FLAG_INIT;
static inline ALint double2int(ALdouble d)
{
- /* TODO: Make a more efficient version for x87. */
+#if ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) && \
+ !defined(__SSE2_MATH__)) || (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP < 2)
+ ALint sign, shift;
+ ALint64 mant;
+ union {
+ ALdouble d;
+ ALint64 i64;
+ } conv;
+
+ conv.d = d;
+ sign = (conv.i64>>63) | 1;
+ shift = ((conv.i64>>52)&0x7ff) - (1023+52);
+
+ /* Over/underflow */
+ if(UNLIKELY(shift >= 63 || shift < -52))
+ return 0;
+
+ mant = (conv.i64&U64(0xfffffffffffff)) | U64(0x10000000000000);
+ if(LIKELY(shift < 0))
+ return (ALint)(mant >> -shift) * sign;
+ return (ALint)(mant << shift) * sign;
+
+#else
+
return (ALint)d;
+#endif
}