Fixes several fixed-point overflows in the PLC code

This commit is contained in:
Jean-Marc Valin 2010-11-06 22:02:32 -04:00
parent e53c4bc59b
commit 1ad93cf485
3 changed files with 12 additions and 8 deletions

View file

@ -1458,13 +1458,15 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p
/* Copy excitation, taking decay into account */ /* Copy excitation, taking decay into account */
for (i=0;i<len+st->mode->overlap;i++) for (i=0;i<len+st->mode->overlap;i++)
{ {
celt_word16 tmp;
if (offset+i >= MAX_PERIOD) if (offset+i >= MAX_PERIOD)
{ {
offset -= pitch_index; offset -= pitch_index;
decay = MULT16_16_Q15(decay, decay); decay = MULT16_16_Q15(decay, decay);
} }
e[i] = SHL32(EXTEND32(MULT16_16_Q15(decay, exc[offset+i])), SIG_SHIFT); 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++) for (i=0;i<LPC_ORDER;i++)
mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT); 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; celt_word32 S2=0;
for (i=0;i<len+overlap;i++) 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 */ /* This checks for an "explosion" in the synthesis */
#ifdef FIXED_POINT #ifdef FIXED_POINT
if (!(S1 > SHR32(S2,2))) 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)); celt_word16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1));
for (i=0;i<len+overlap;i++) for (i=0;i<len+overlap;i++)
e[i] = MULT16_16_Q15(ratio, e[i]); e[i] = MULT16_32_Q15(ratio, e[i]);
} }
} }

View file

@ -74,10 +74,9 @@ celt_word32 frac_div32(celt_word32 a, celt_word32 b)
{ {
celt_word16 rcp; celt_word16 rcp;
celt_word32 result, rem; celt_word32 result, rem;
int shift = 29-celt_ilog2(b); int shift = celt_ilog2(b)-29;
a = SHL32(a,shift); a = VSHR32(a,shift);
b = SHL32(b,shift); b = VSHR32(b,shift);
/* 16-bit reciprocal */ /* 16-bit reciprocal */
rcp = ROUND16(celt_rcp(ROUND16(b,16)),3); rcp = ROUND16(celt_rcp(ROUND16(b,16)),3);
result = SHL32(MULT16_32_Q15(rcp, a),2); result = SHL32(MULT16_32_Q15(rcp, a),2);

View file

@ -172,7 +172,7 @@ void _celt_autocorr(
ac0 += SHR32(MULT16_16(xx[i],xx[i]),8); ac0 += SHR32(MULT16_16(xx[i],xx[i]),8);
ac0 += 1+n; ac0 += 1+n;
shift = celt_ilog2(ac0)-30+8; shift = celt_ilog2(ac0)-30+9;
shift = (shift+1)/2; shift = (shift+1)/2;
for(i=0;i<n;i++) for(i=0;i<n;i++)
xx[i] = VSHR32(xx[i], shift); xx[i] = VSHR32(xx[i], shift);