Fixes several fixed-point overflows in the PLC code
authorJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Sun, 7 Nov 2010 02:02:32 +0000 (22:02 -0400)
committerJean-Marc Valin <jean-marc.valin@usherbrooke.ca>
Sun, 7 Nov 2010 02:02:32 +0000 (22:02 -0400)
libcelt/celt.c
libcelt/mathops.c
libcelt/plc.c

index fe92075..450bde5 100644 (file)
@@ -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]);
          }
       }
 
index 1dca101..494649e 100644 (file)
@@ -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);
index cadad2b..b93fd6a 100644 (file)
@@ -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);