ref: 3c15659c39ca266286a53e04fcbf09735e311d0d
parent: d60e0db0e24935903f5aae30414a28232c65c9b0
author: Jean-Marc Valin <[email protected]>
date: Tue Sep 14 12:02:47 EDT 2010
Fixes fixed-point overflow in stereo_merge()
--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -264,8 +264,10 @@
for (j=0;j<N;j++)
xp = MAC16_16(xp, X[j], Y[j]);
/* mid and side are in Q15, not Q14 like X and Y */
- El = MULT16_16(mid, mid) + MULT16_16(side, side) - 2*SHL32(xp,2);
- Er = MULT16_16(mid, mid) + MULT16_16(side, side) + 2*SHL32(xp,2);
+ mid = SHR32(mid, 1);
+ side = SHR32(side, 1);
+ El = MULT16_16(mid, mid) + MULT16_16(side, side) - 2*xp;
+ Er = MULT16_16(mid, mid) + MULT16_16(side, side) + 2*xp;
if (Er < EPSILON)
Er = EPSILON;
if (El < EPSILON)
@@ -280,13 +282,20 @@
t = VSHR32(Er, (kr-7)<<1);
rgain = celt_rsqrt_norm(t);
+#ifdef FIXED_POINT
+ if (kl < 7)
+ kl = 7;
+ if (kr < 7)
+ kr = 7;
+#endif
+
for (j=0;j<N;j++)
{
celt_norm r, l;
l = X[j];
r = Y[j];
- X[j] = EXTRACT16(PSHR32(MULT16_16(lgain, l-r), kl));
- Y[j] = EXTRACT16(PSHR32(MULT16_16(rgain, l+r), kr));
+ X[j] = EXTRACT16(PSHR32(MULT16_16(lgain, SUB16(l,r)), kl+1));
+ Y[j] = EXTRACT16(PSHR32(MULT16_16(rgain, ADD16(l,r)), kr+1));
}
}