diff options
author | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2016-07-22 18:05:19 +0300 |
---|---|---|
committer | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2016-07-22 22:30:19 +0300 |
commit | c952f90b4ffb63616a4b29d1ec6b671a2ed76147 (patch) | |
tree | a5faec920f0f3c2c767939573cdf873ad2c0ff6b | |
parent | 1fba9045b18f79af9200427766ff34c41936148f (diff) |
Prevent overflows in PLC celt_iir()
-rw-r--r-- | celt/celt_decoder.c | 18 |
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 |