added a shortcut (SHORTCUT) to skip the spreading function in the pitch search
[opus.git] / libcelt / pitch.c
index 2dab60f..67c9557 100644 (file)
@@ -47,6 +47,7 @@
 #include "psy.h"
 #include "os_support.h"
 #include "mathops.h"
+#include "modes.h"
 #include "stack_alloc.h"
 
 kiss_fftr_cfg pitch_state_alloc(int max_lag)
@@ -75,8 +76,10 @@ static void normalise16(celt_word16_t *x, int len, celt_word16_t val)
       }
       if (shift==0)
          return;
-      for (i=0;i<len;i++)
+      i=0;
+      do{
          x[i] = SHR16(x[i], shift);
+      } while (++i<len);
    } else {
       int shift=0;
       if (maxabs == 0)
@@ -89,8 +92,10 @@ static void normalise16(celt_word16_t *x, int len, celt_word16_t val)
       }
       if (shift==0)
          return;
-      for (i=0;i<len;i++)
+      i=0;
+      do{
          x[i] = SHL16(x[i], shift);
+      } while (++i<len);
    }
 }
 #else
@@ -99,24 +104,29 @@ static void normalise16(celt_word16_t *x, int len, celt_word16_t val)
 
 #define INPUT_SHIFT 15
 
-void find_spectral_pitch(kiss_fftr_cfg fft, const struct PsyDecay *decay, const celt_sig_t * restrict x, const celt_sig_t * restrict y, const celt_word16_t * restrict window, int overlap, int lag, int len, int C, int *pitch)
+void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyDecay *decay, const celt_sig_t * restrict x, const celt_sig_t * restrict y, const celt_word16_t * restrict window, int len, int *pitch)
 {
    int c, i;
    VARDECL(celt_word16_t, _X);
    VARDECL(celt_word16_t, _Y);
+#ifndef SHORTCUTS
    VARDECL(celt_mask_t, curve);
+#endif
    celt_word16_t * restrict X, * restrict Y;
    int n2;
    int L2;
+   const int C = CHANNELS(m);
+   const int overlap = OVERLAP(m);
+   const int lag = MAX_PERIOD;
    SAVE_STACK;
    n2 = lag>>1;
    L2 = len>>1;
    ALLOC(_X, lag, celt_word16_t);
    X = _X;
+#ifndef SHORTCUTS
    ALLOC(curve, n2, celt_mask_t);
-
-   for (i=0;i<lag;i++)
-      X[i] = 0;
+#endif
+   CELT_MEMSET(X,0,lag);
    /* Sum all channels of the current frame and copy into X in bit-reverse order */
    for (c=0;c<C;c++)
    {
@@ -140,13 +150,14 @@ void find_spectral_pitch(kiss_fftr_cfg fft, const struct PsyDecay *decay, const
    /* Forward real FFT (in-place) */
    real16_fft_inplace(fft, X, lag);
 
+#ifndef SHORTCUTS
    compute_masking(decay, X, curve, lag);
-
+#endif
+   
    /* Deferred allocation to reduce peak stack usage */
    ALLOC(_Y, lag, celt_word16_t);
    Y = _Y;
-   for (i=0;i<lag;i++)
-      Y[i] = 0;
+   CELT_MEMSET(Y,0,lag);
    /* Sum all channels of the past audio and copy into Y in bit-reverse order */
    for (c=0;c<C;c++)
    {
@@ -163,16 +174,22 @@ void find_spectral_pitch(kiss_fftr_cfg fft, const struct PsyDecay *decay, const
    /* Compute cross-spectrum using the inverse masking curve as weighting */
    for (i=1;i<n2;i++)
    {
-      celt_word16_t n;
-      celt_word32_t tmp;
-      /*printf ("%d %d ", X[2*i]*X[2*i]+X[2*i+1]*X[2*i+1], Y[2*i]*Y[2*i]+Y[2*i+1]*Y[2*i+1]);*/
-      /*n = DIV32_16(Q15ONE,celt_sqrt(EPSILON+curve[i]));*/
-      /*n = ROUND16(celt_rcp(celt_sqrt(EPSILON+curve[i])),16);*/
+      celt_word16_t Xr, Xi, n;
+      /* weight = 1/sqrt(curve) */
+      Xr = X[2*i];
+      Xi = X[2*i+1];
+#ifdef SHORTCUTS
+      /*n = SHR32(32767,(celt_ilog2(EPSILON+curve[i])>>1));*/
+      n = SHR32(32767,(celt_ilog2(EPSILON+MULT16_16(Xr,Xr)+MULT16_16(Xi,Xi))>>1));
+#else
       n = celt_rsqrt(EPSILON+curve[i]);
-      /*printf ("%f ", n);*/
-      tmp = X[2*i];
-      X[2*i] = MULT16_32_Q15(n, ADD32(MULT16_16(X[2*i  ],Y[2*i  ]), MULT16_16(X[2*i+1],Y[2*i+1])));
-      X[2*i+1] = MULT16_32_Q15(n, SUB32(MULT16_16(tmp,Y[2*i+1]), MULT16_16(X[2*i+1],Y[2*i  ])));
+#endif
+      /* Pre-multiply X by n, so we can keep everything in 16 bits */
+      Xr = EXTRACT16(SHR32(MULT16_16(n, Xr),3));
+      Xi = EXTRACT16(SHR32(MULT16_16(n, Xi),3));
+      /* Cross-spectrum between X and conj(Y) */
+      X[2*i]   = ADD16(MULT16_16_Q15(Xr, Y[2*i  ]), MULT16_16_Q15(Xi,Y[2*i+1]));
+      X[2*i+1] = SUB16(MULT16_16_Q15(Xr, Y[2*i+1]), MULT16_16_Q15(Xi,Y[2*i  ]));
    }
    /*printf ("\n");*/
    X[0] = X[1] = 0;