ref: 367c39486618fe6a6f9ffe85e834d59cae241253
parent: 7aecadda2f72cbf1f55209293dc63e01bb743035
author: Jean-Marc Valin <[email protected]>
date: Thu Apr 12 07:07:21 EDT 2012
Fixes several overflows in the CELT fixed-point These were all mostly benign and would at worst result in (rare) suboptimal encoder decisions rather than signal corruption.
--- a/celt/bands.c
+++ b/celt/bands.c
@@ -249,7 +249,7 @@
prev2 = MAX16(prev2,prev2logE[m->nbEBands+i]);
}
Ediff = EXTEND32(logE[c*m->nbEBands+i])-EXTEND32(MIN16(prev1,prev2));
- Ediff = MAX16(0, Ediff);
+ Ediff = MAX32(0, Ediff);
#ifdef FIXED_POINT
if (Ediff < 16384)
--- a/celt/celt.c
+++ b/celt/celt.c
@@ -607,7 +607,7 @@
/* Just add the right channel if we're in stereo */
if (C==2)
for (j=0;j<N;j++)
- tmp[j] = ADD16(tmp[j],X[N0+j+(m->eBands[i]<<LM)]);
+ tmp[j] = ADD16(SHR16(tmp[j], 1),SHR16(X[N0+j+(m->eBands[i]<<LM)], 1));
L1 = l1_metric(tmp, N, isTransient ? LM : 0, N>>LM);
best_L1 = L1;
/*printf ("%f ", L1);*/
--- a/celt/fixed_debug.h
+++ b/celt/fixed_debug.h
@@ -154,17 +154,18 @@
celt_mips+=2;
return res;
}
-static inline int SHL32(long long a, int shift)
+#define SHL32(a, shift) SHL32_(a, shift, __FILE__, __LINE__)
+static inline int SHL32_(long long a, int shift, char *file, int line)
{
long long res;
if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
{
- fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift);
+ fprintf (stderr, "SHL32: inputs are not int: %lld %d in %s: line %d\n", a, shift, file, line);
}
res = a<<shift;
if (!VERIFY_INT(res))
{
- fprintf (stderr, "SHL32: output is not int: %d\n", (int)res);
+ fprintf (stderr, "SHL32: output is not int: %lld<<%d = %lld in %s: line %d\n", a, shift, res, file, line);
}
celt_mips+=2;
return res;
--- a/celt/mathops.c
+++ b/celt/mathops.c
@@ -75,9 +75,15 @@
b = VSHR32(b,shift);
/* 16-bit reciprocal */
rcp = ROUND16(celt_rcp(ROUND16(b,16)),3);
- result = SHL32(MULT16_32_Q15(rcp, a),2);
- rem = a-MULT32_32_Q31(result, b);
- result += SHL32(MULT16_32_Q15(rcp, rem),2);
+ result = MULT16_32_Q15(rcp, a);
+ rem = PSHR32(a,2)-MULT32_32_Q31(result, b);
+ result = ADD32(result, SHL32(MULT16_32_Q15(rcp, rem),2));
+ if (result >= 536870912) /* 2^29 */
+ return 2147483647; /* 2^31 - 1 */
+ else if (result <= -536870912) /* -2^29 */
+ return -2147483647; /* -2^31 */
+ else
+ return SHL32(result, 2);
return result;
}
--- a/celt/quant_bands.c
+++ b/celt/quant_bands.c
@@ -146,11 +146,11 @@
c=0; do {
for (i=start;i<end;i++)
{
- opus_val16 d = SHR16(SUB16(eBands[i+c*len], oldEBands[i+c*len]),2);
+ opus_val16 d = SUB16(SHR16(eBands[i+c*len], 3), SHR16(oldEBands[i+c*len], 3));
dist = MAC16_16(dist, d,d);
}
} while (++c<C);
- return MIN32(200,SHR32(dist,2*DB_SHIFT-4));
+ return MIN32(200,SHR32(dist,2*DB_SHIFT-6));
}
static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,