From 6a7ee7fb55b4a41fca2dea19624600fe42d3b7f7 Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin <jmvalin@jmvalin.ca> Date: Wed, 28 Aug 2013 17:55:34 -0400 Subject: [PATCH] Share auto-correlation code between SILK and CELT --- celt/celt_lpc.c | 78 +++++++++++++++++++++++++++------------ celt/celt_lpc.h | 2 +- silk/fixed/autocorr_FIX.c | 35 ++---------------- 3 files changed, 58 insertions(+), 57 deletions(-) diff --git a/celt/celt_lpc.c b/celt/celt_lpc.c index 1861b8903..523c36aae 100644 --- a/celt/celt_lpc.c +++ b/celt/celt_lpc.c @@ -221,7 +221,7 @@ void celt_iir(const opus_val32 *_x, #endif } -void _celt_autocorr( +int _celt_autocorr( const opus_val16 *x, /* in: [0...n-1] samples x */ opus_val32 *ac, /* out: [0...lag-1] ac values */ const opus_val16 *window, @@ -231,49 +231,79 @@ void _celt_autocorr( ) { opus_val32 d; - int i; + int i, k; int fastN=n-lag; + int shift; + const opus_val16 *xptr; VARDECL(opus_val16, xx); SAVE_STACK; ALLOC(xx, n, opus_val16); celt_assert(n>0); celt_assert(overlap>=0); - for (i=0;i<n;i++) - xx[i] = x[i]; - for (i=0;i<overlap;i++) + if (overlap == 0) { - xx[i] = MULT16_16_Q15(x[i],window[i]); - xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]); + xptr = x; + } else { + for (i=0;i<n;i++) + xx[i] = x[i]; + for (i=0;i<overlap;i++) + { + xx[i] = MULT16_16_Q15(x[i],window[i]); + xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]); + } + xptr = xx; } + shift=0; #ifdef FIXED_POINT { opus_val32 ac0; - int shift; - ac0 = 1+n; - if (n&1) ac0 += SHR32(MULT16_16(xx[0],xx[0]),9); + ac0 = 1+(n<<7); + if (n&1) ac0 += SHR32(MULT16_16(xptr[0],xptr[0]),9); for(i=(n&1);i<n;i+=2) { - ac0 += SHR32(MULT16_16(xx[i],xx[i]),9); - ac0 += SHR32(MULT16_16(xx[i+1],xx[i+1]),9); + ac0 += SHR32(MULT16_16(xptr[i],xptr[i]),9); + ac0 += SHR32(MULT16_16(xptr[i+1],xptr[i+1]),9); } shift = celt_ilog2(ac0)-30+10; - shift = (shift+1)/2; - for(i=0;i<n;i++) - xx[i] = VSHR32(xx[i], shift); + shift = (shift)/2; + if (shift>0) + { + for(i=0;i<n;i++) + xx[i] = PSHR32(xptr[i], shift); + xptr = xx; + } else + shift = 0; } #endif - celt_pitch_xcorr(xx, xx, ac, fastN, lag+1); - while (lag>=0) + celt_pitch_xcorr(xptr, xptr, ac, fastN, lag+1); + for (k=0;k<=lag;k++) + { + for (i = k+fastN, d = 0; i < n; i++) + d = MAC16_16(d, xptr[i], xptr[i-k]); + ac[k] += d; + } +#ifdef FIXED_POINT + shift = 2*shift; + if (shift<=0) + ac[0] += SHL32((opus_int32)1, -shift); + if (ac[0] < 268435456) { - for (i = lag+fastN, d = 0; i < n; i++) - d = MAC16_16(d, xx[i], xx[i-lag]); - ac[lag] += d; - /*printf ("%f ", ac[lag]);*/ - lag--; + int shift2 = 29 - EC_ILOG(ac[0]); + for (i=0;i<=lag;i++) + ac[i] = SHL32(ac[i], shift2); + shift -= shift2; + } else if (ac[0] >= 536870912) + { + int shift2=1; + if (ac[0] >= 1073741824) + shift2++; + for (i=0;i<=lag;i++) + ac[i] = SHR32(ac[i], shift2); + shift += shift2; } - /*printf ("\n");*/ - ac[0] += 10; +#endif RESTORE_STACK; + return shift; } diff --git a/celt/celt_lpc.h b/celt/celt_lpc.h index 2baa77edf..19279a0ed 100644 --- a/celt/celt_lpc.h +++ b/celt/celt_lpc.h @@ -48,6 +48,6 @@ void celt_iir(const opus_val32 *x, int ord, opus_val16 *mem); -void _celt_autocorr(const opus_val16 *x, opus_val32 *ac, const opus_val16 *window, int overlap, int lag, int n); +int _celt_autocorr(const opus_val16 *x, opus_val32 *ac, const opus_val16 *window, int overlap, int lag, int n); #endif /* PLC_H */ diff --git a/silk/fixed/autocorr_FIX.c b/silk/fixed/autocorr_FIX.c index 3ac6650be..4cd8f6fc0 100644 --- a/silk/fixed/autocorr_FIX.c +++ b/silk/fixed/autocorr_FIX.c @@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE. #endif #include "SigProc_FIX.h" +#include "celt_lpc.h" /* Compute autocorrelation */ void silk_autocorr( @@ -40,37 +41,7 @@ void silk_autocorr( const opus_int correlationCount /* I Number of correlation taps to compute */ ) { - opus_int i, lz, nRightShifts, corrCount; - opus_int64 corr64; - + opus_int corrCount; corrCount = silk_min_int( inputDataSize, correlationCount ); - - /* compute energy (zero-lag correlation) */ - corr64 = silk_inner_prod16_aligned_64( inputData, inputData, inputDataSize ); - - /* deal with all-zero input data */ - corr64 += 1; - - /* number of leading zeros */ - lz = silk_CLZ64( corr64 ); - - /* scaling: number of right shifts applied to correlations */ - nRightShifts = 35 - lz; - *scale = nRightShifts; - - if( nRightShifts <= 0 ) { - results[ 0 ] = silk_LSHIFT( (opus_int32)silk_CHECK_FIT32( corr64 ), -nRightShifts ); - - /* compute remaining correlations based on int32 inner product */ - for( i = 1; i < corrCount; i++ ) { - results[ i ] = silk_LSHIFT( silk_inner_prod_aligned( inputData, inputData + i, inputDataSize - i ), -nRightShifts ); - } - } else { - results[ 0 ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr64, nRightShifts ) ); - - /* compute remaining correlations based on int64 inner product */ - for( i = 1; i < corrCount; i++ ) { - results[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( silk_inner_prod16_aligned_64( inputData, inputData + i, inputDataSize - i ), nRightShifts ) ); - } - } + *scale = _celt_autocorr(inputData, results, NULL, 0, corrCount-1, inputDataSize); } -- GitLab