diff options
author | Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> | 2010-11-07 05:02:32 +0300 |
---|---|---|
committer | Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> | 2010-11-07 05:02:32 +0300 |
commit | 1ad93cf485b344abc9f8c67e4120fdb29536ea03 (patch) | |
tree | 11bf7230e9e5e2db0fa36ebc5d4cd5964d9254b9 | |
parent | e53c4bc59bdfb69299371c75ccd743d05dd147ae (diff) |
Fixes several fixed-point overflows in the PLC code
-rw-r--r-- | libcelt/celt.c | 11 | ||||
-rw-r--r-- | libcelt/mathops.c | 7 | ||||
-rw-r--r-- | libcelt/plc.c | 2 |
3 files changed, 12 insertions, 8 deletions
diff --git a/libcelt/celt.c b/libcelt/celt.c index fe92075..450bde5 100644 --- a/libcelt/celt.c +++ b/libcelt/celt.c @@ -1458,13 +1458,15 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p /* Copy excitation, taking decay into account */ for (i=0;i<len+st->mode->overlap;i++) { + celt_word16 tmp; if (offset+i >= MAX_PERIOD) { offset -= pitch_index; decay = MULT16_16_Q15(decay, decay); } e[i] = SHL32(EXTEND32(MULT16_16_Q15(decay, exc[offset+i])), SIG_SHIFT); - S1 += SHR32(MULT16_16(out_mem[c][offset+i],out_mem[c][offset+i]),8); + tmp = ROUND16(out_mem[c][offset+i],SIG_SHIFT); + S1 += SHR32(MULT16_16(tmp,tmp),8); } for (i=0;i<LPC_ORDER;i++) mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT); @@ -1475,7 +1477,10 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p { celt_word32 S2=0; for (i=0;i<len+overlap;i++) - S2 += SHR32(MULT16_16(e[i],e[i]),8); + { + celt_word16 tmp = ROUND16(e[i],SIG_SHIFT); + S2 += SHR32(MULT16_16(tmp,tmp),8); + } /* This checks for an "explosion" in the synthesis */ #ifdef FIXED_POINT if (!(S1 > SHR32(S2,2))) @@ -1490,7 +1495,7 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p { celt_word16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1)); for (i=0;i<len+overlap;i++) - e[i] = MULT16_16_Q15(ratio, e[i]); + e[i] = MULT16_32_Q15(ratio, e[i]); } } diff --git a/libcelt/mathops.c b/libcelt/mathops.c index 1dca101..494649e 100644 --- a/libcelt/mathops.c +++ b/libcelt/mathops.c @@ -74,10 +74,9 @@ celt_word32 frac_div32(celt_word32 a, celt_word32 b) { celt_word16 rcp; celt_word32 result, rem; - int shift = 29-celt_ilog2(b); - a = SHL32(a,shift); - b = SHL32(b,shift); - + int shift = celt_ilog2(b)-29; + a = VSHR32(a,shift); + b = VSHR32(b,shift); /* 16-bit reciprocal */ rcp = ROUND16(celt_rcp(ROUND16(b,16)),3); result = SHL32(MULT16_32_Q15(rcp, a),2); diff --git a/libcelt/plc.c b/libcelt/plc.c index cadad2b..b93fd6a 100644 --- a/libcelt/plc.c +++ b/libcelt/plc.c @@ -172,7 +172,7 @@ void _celt_autocorr( ac0 += SHR32(MULT16_16(xx[i],xx[i]),8); ac0 += 1+n; - shift = celt_ilog2(ac0)-30+8; + shift = celt_ilog2(ac0)-30+9; shift = (shift+1)/2; for(i=0;i<n;i++) xx[i] = VSHR32(xx[i], shift); |