diff --git a/celt/celt_lpc.c b/celt/celt_lpc.c
index 1861b890310b34b560219cb71213fd1a22b71c41..523c36aae12c671f1fbc0b03ae1f97d2f68a5a1b 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 2baa77edf8b8226634d726365988a32315f1b55c..19279a0ed66f2787b5968ef96373636b5e8f3120 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 3ac6650be7e4b6e4652977bc18ec8b0b5d899e13..4cd8f6fc05916810a9cc5f345a5c80f9e588a21b 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);
 }