summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Marc Valin <jmvalin@jmvalin.ca>2016-07-22 11:05:19 -0400
committerJean-Marc Valin <jmvalin@jmvalin.ca>2016-07-22 15:57:01 -0400
commit3c60bae2d74b4b9898b5f4925d4a1fb464a3fa43 (patch)
tree99d0b5bea2c2364abccdb6042ed11cca390ba99f
parenta0bd7d3b8420be9c96f4e65e6113e11a05a23717 (diff)
downloadopus-3c60bae2d74b4b9898b5f4925d4a1fb464a3fa43.tar.gz
Prevent overflows in PLC celt_iir()
-rw-r--r--celt/celt_decoder.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/celt/celt_decoder.c b/celt/celt_decoder.c
index 5e0c2c88..28239cd8 100644
--- a/celt/celt_decoder.c
+++ b/celt/celt_decoder.c
@@ -632,7 +632,23 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
SIG_SHIFT);
S1 += SHR32(MULT16_16(tmp, tmp), 9);
}
-
+#ifdef FIXED_POINT
+ /* For fixed-point, apply bandwidth expansion until we can guarantee that
+ no overflow can happen in the IIR filter. This means:
+ attenuation*32768*sum(abs(filter)) < 2^31 */
+ while (1) {
+ opus_val16 tmp=Q15ONE;
+ opus_val32 sum=QCONST16(1., SIG_SHIFT);
+ for (i=0;i<LPC_ORDER;i++)
+ sum += ABS16(lpc[c*LPC_ORDER+i]);
+ if (MULT16_32_Q15(attenuation, sum) < 65535) break;
+ for (i=0;i<LPC_ORDER;i++)
+ {
+ tmp = MULT16_16_Q15(QCONST16(.99f,15), tmp);
+ lpc[c*LPC_ORDER+i] = MULT16_16_Q15(lpc[c*LPC_ORDER+i], tmp);
+ }
+ }
+#endif
{
opus_val16 lpc_mem[LPC_ORDER];
/* Copy the last decoded samples (prior to the overlap region) to