shithub: opus

Download patch

ref: 6a7ee7fb55b4a41fca2dea19624600fe42d3b7f7
parent: a156c5ece7133383468d4cba33f067595d9da391
author: Jean-Marc Valin <[email protected]>
date: Wed Aug 28 13:55:34 EDT 2013

Share auto-correlation code between SILK and CELT

--- a/celt/celt_lpc.c
+++ b/celt/celt_lpc.c
@@ -221,7 +221,7 @@
 #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 @@
                   )
 {
    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 = lag+fastN, d = 0; i < n; i++)
-         d = MAC16_16(d, xx[i], xx[i-lag]);
-      ac[lag] += d;
-      /*printf ("%f ", ac[lag]);*/
-      lag--;
+      for (i = k+fastN, d = 0; i < n; i++)
+         d = MAC16_16(d, xptr[i], xptr[i-k]);
+      ac[k] += d;
    }
-   /*printf ("\n");*/
-   ac[0] += 10;
+#ifdef FIXED_POINT
+   shift = 2*shift;
+   if (shift<=0)
+      ac[0] += SHL32((opus_int32)1, -shift);
+   if (ac[0] < 268435456)
+   {
+      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;
+   }
+#endif
 
    RESTORE_STACK;
+   return shift;
 }
--- a/celt/celt_lpc.h
+++ b/celt/celt_lpc.h
@@ -48,6 +48,6 @@
          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 */
--- a/silk/fixed/autocorr_FIX.c
+++ b/silk/fixed/autocorr_FIX.c
@@ -30,6 +30,7 @@
 #endif
 
 #include "SigProc_FIX.h"
+#include "celt_lpc.h"
 
 /* Compute autocorrelation */
 void silk_autocorr(
@@ -40,37 +41,7 @@
     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);
 }