diff options
author | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2016-07-22 16:13:00 +0300 |
---|---|---|
committer | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2016-07-22 19:10:20 +0300 |
commit | b230d3df36d34909ca1f0e4f1fab0ccb55fedfb4 (patch) | |
tree | 4a20ef7f8f287111aabf37febfab083451ddddcc | |
parent | 940da2f78a7da1197e4bfed627869a382f45e8a4 (diff) |
fixes overflows in celt_iir() by doing proper saturation
-rw-r--r-- | celt/arch.h | 1 | ||||
-rw-r--r-- | celt/celt_lpc.c | 12 | ||||
-rw-r--r-- | celt/fixed_debug.h | 2 | ||||
-rw-r--r-- | celt/fixed_generic.h | 3 |
4 files changed, 12 insertions, 6 deletions
diff --git a/celt/arch.h b/celt/arch.h index d72bc9f2..8f3905a9 100644 --- a/celt/arch.h +++ b/celt/arch.h @@ -205,6 +205,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)) diff --git a/celt/celt_lpc.c b/celt/celt_lpc.c index b410a21c..bc9eb2c8 100644 --- a/celt/celt_lpc.c +++ b/celt/celt_lpc.c @@ -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++) diff --git a/celt/fixed_debug.h b/celt/fixed_debug.h index f55dbf92..c9546a7d 100644 --- a/celt/fixed_debug.h +++ b/celt/fixed_debug.h @@ -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)) diff --git a/celt/fixed_generic.h b/celt/fixed_generic.h index 32e38ff0..3561b93c 100644 --- a/celt/fixed_generic.h +++ b/celt/fixed_generic.h @@ -104,6 +104,9 @@ /** 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)) |