fixes overflows in celt_iir() by doing proper saturation
authorJean-Marc Valin <jmvalin@jmvalin.ca>
Fri, 22 Jul 2016 13:13:00 +0000 (09:13 -0400)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Fri, 22 Jul 2016 19:57:01 +0000 (15:57 -0400)
celt/arch.h
celt/celt_lpc.c
celt/fixed_debug.h
celt/fixed_generic.h

index 1615af3..6a328ea 100644 (file)
@@ -206,6 +206,7 @@ static OPUS_INLINE int celt_isnan(float x)
 #define SATURATE16(x)   (x)
 
 #define ROUND16(a,shift)  (a)
+#define SROUND16(a,shift) (a)
 #define HALF16(x)       (.5f*(x))
 #define HALF32(x)       (.5f*(x))
 
index b410a21..bc9eb2c 100644 (file)
@@ -166,7 +166,7 @@ void celt_iir(const opus_val32 *_x,
       {
          mem[j]=mem[j-1];
       }
-      mem[0] = ROUND16(sum,SIG_SHIFT);
+      mem[0] = SROUND16(sum, SIG_SHIFT);
       _y[i] = sum;
    }
 #else
@@ -195,20 +195,20 @@ void celt_iir(const opus_val32 *_x,
       xcorr_kernel(rden, y+i, sum, ord, arch);
 
       /* Patch up the result to compensate for the fact that this is an IIR */
-      y[i+ord  ] = -ROUND16(sum[0],SIG_SHIFT);
+      y[i+ord  ] = -SROUND16(sum[0],SIG_SHIFT);
       _y[i  ] = sum[0];
       sum[1] = MAC16_16(sum[1], y[i+ord  ], den[0]);
-      y[i+ord+1] = -ROUND16(sum[1],SIG_SHIFT);
+      y[i+ord+1] = -SROUND16(sum[1],SIG_SHIFT);
       _y[i+1] = sum[1];
       sum[2] = MAC16_16(sum[2], y[i+ord+1], den[0]);
       sum[2] = MAC16_16(sum[2], y[i+ord  ], den[1]);
-      y[i+ord+2] = -ROUND16(sum[2],SIG_SHIFT);
+      y[i+ord+2] = -SROUND16(sum[2],SIG_SHIFT);
       _y[i+2] = sum[2];
 
       sum[3] = MAC16_16(sum[3], y[i+ord+2], den[0]);
       sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]);
       sum[3] = MAC16_16(sum[3], y[i+ord  ], den[2]);
-      y[i+ord+3] = -ROUND16(sum[3],SIG_SHIFT);
+      y[i+ord+3] = -SROUND16(sum[3],SIG_SHIFT);
       _y[i+3] = sum[3];
    }
    for (;i<N;i++)
@@ -216,7 +216,7 @@ void celt_iir(const opus_val32 *_x,
       opus_val32 sum = _x[i];
       for (j=0;j<ord;j++)
          sum -= MULT16_16(rden[j],y[i+j]);
-      y[i+ord] = ROUND16(sum,SIG_SHIFT);
+      y[i+ord] = SROUND16(sum,SIG_SHIFT);
       _y[i] = sum;
    }
    for(i=0;i<ord;i++)
index f55dbf9..c9546a7 100644 (file)
@@ -233,6 +233,8 @@ static OPUS_INLINE int SHL32_(opus_int64 a, int shift, char *file, int line)
 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
 
 #define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
+#define SROUND16(x,a) (celt_mips--,EXTRACT16(SATURATE(PSHR32(x,a), 32767)));
+
 #define HALF16(x)  (SHR16(x,1))
 #define HALF32(x)  (SHR32(x,1))
 
index 32e38ff..3561b93 100644 (file)
 
 /** Shift by a and round-to-neareast 32-bit value. Result is a 16-bit value */
 #define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a))))
+/** Shift by a and round-to-neareast 32-bit value. Result is a saturated 16-bit value */
+#define SROUND16(x,a) EXTRACT16(SATURATE(PSHR32(x,a), 32767));
+
 /** Divide by two */
 #define HALF16(x)  (SHR16(x,1))
 #define HALF32(x)  (SHR32(x,1))