Blame libcelt/pitch.c

Packit 664db3
/* (C) 2007-2008 Jean-Marc Valin, CSIRO
Packit 664db3
*/
Packit 664db3
/**
Packit 664db3
   @file pitch.c
Packit 664db3
   @brief Pitch analysis
Packit 664db3
 */
Packit 664db3
Packit 664db3
/*
Packit 664db3
   Redistribution and use in source and binary forms, with or without
Packit 664db3
   modification, are permitted provided that the following conditions
Packit 664db3
   are met:
Packit 664db3
   
Packit 664db3
   - Redistributions of source code must retain the above copyright
Packit 664db3
   notice, this list of conditions and the following disclaimer.
Packit 664db3
   
Packit 664db3
   - Redistributions in binary form must reproduce the above copyright
Packit 664db3
   notice, this list of conditions and the following disclaimer in the
Packit 664db3
   documentation and/or other materials provided with the distribution.
Packit 664db3
   
Packit 664db3
   - Neither the name of the Xiph.org Foundation nor the names of its
Packit 664db3
   contributors may be used to endorse or promote products derived from
Packit 664db3
   this software without specific prior written permission.
Packit 664db3
   
Packit 664db3
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 664db3
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 664db3
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 664db3
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
Packit 664db3
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Packit 664db3
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Packit 664db3
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
Packit 664db3
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
Packit 664db3
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Packit 664db3
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit 664db3
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 664db3
*/
Packit 664db3
Packit 664db3
Packit 664db3
#ifdef HAVE_CONFIG_H
Packit 664db3
#include "config.h"
Packit 664db3
#endif
Packit 664db3
Packit 664db3
/*#include "_kiss_fft_guts.h"
Packit 664db3
#include "kiss_fftr.h"*/
Packit 664db3
#include "kfft_single.h"
Packit 664db3
Packit 664db3
#include "pitch.h"
Packit 664db3
#include "psy.h"
Packit 664db3
#include "os_support.h"
Packit 664db3
#include "mathops.h"
Packit 664db3
#include "modes.h"
Packit 664db3
#include "stack_alloc.h"
Packit 664db3
Packit 664db3
kiss_fftr_cfg pitch_state_alloc(int max_lag)
Packit 664db3
{
Packit 664db3
   return real16_fft_alloc(max_lag);
Packit 664db3
}
Packit 664db3
Packit 664db3
void pitch_state_free(kiss_fftr_cfg st)
Packit 664db3
{
Packit 664db3
   real16_fft_free(st);
Packit 664db3
}
Packit 664db3
Packit 664db3
#ifdef FIXED_POINT
Packit 664db3
static void normalise16(celt_word16_t *x, int len, celt_word16_t val)
Packit 664db3
{
Packit 664db3
   int i;
Packit 664db3
   celt_word16_t maxabs;
Packit 664db3
   maxabs = celt_maxabs16(x,len);
Packit 664db3
   if (maxabs > val)
Packit 664db3
   {
Packit 664db3
      int shift = 0;
Packit 664db3
      while (maxabs > val)
Packit 664db3
      {
Packit 664db3
         maxabs >>= 1;
Packit 664db3
         shift++;
Packit 664db3
      }
Packit 664db3
      if (shift==0)
Packit 664db3
         return;
Packit 664db3
      i=0;
Packit 664db3
      do{
Packit 664db3
         x[i] = SHR16(x[i], shift);
Packit 664db3
      } while (++i
Packit 664db3
   } else {
Packit 664db3
      int shift=0;
Packit 664db3
      if (maxabs == 0)
Packit 664db3
         return;
Packit 664db3
      val >>= 1;
Packit 664db3
      while (maxabs < val)
Packit 664db3
      {
Packit 664db3
         val >>= 1;
Packit 664db3
         shift++;
Packit 664db3
      }
Packit 664db3
      if (shift==0)
Packit 664db3
         return;
Packit 664db3
      i=0;
Packit 664db3
      do{
Packit 664db3
         x[i] = SHL16(x[i], shift);
Packit 664db3
      } while (++i
Packit 664db3
   }
Packit 664db3
}
Packit 664db3
#else
Packit 664db3
#define normalise16(x,len,val)
Packit 664db3
#endif
Packit 664db3
Packit 664db3
#define INPUT_SHIFT 15
Packit 664db3
Packit 664db3
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, celt_word16_t * restrict spectrum, int len, int max_pitch, int *pitch)
Packit 664db3
{
Packit 664db3
   int c, i;
Packit 664db3
   VARDECL(celt_word16_t, _X);
Packit 664db3
   VARDECL(celt_word16_t, _Y);
Packit 664db3
   const celt_word16_t * restrict wptr;
Packit 664db3
#ifndef SHORTCUTS
Packit 664db3
   VARDECL(celt_mask_t, curve);
Packit 664db3
#endif
Packit 664db3
   celt_word16_t * restrict X, * restrict Y;
Packit 664db3
   celt_word16_t * restrict Xptr, * restrict Yptr;
Packit 664db3
   const celt_sig_t * restrict yptr;
Packit 664db3
   int n2;
Packit 664db3
   int L2;
Packit 664db3
   const int C = CHANNELS(m);
Packit 664db3
   const int overlap = OVERLAP(m);
Packit 664db3
   const int lag = MAX_PERIOD;
Packit 664db3
   SAVE_STACK;
Packit 664db3
   n2 = lag>>1;
Packit 664db3
   L2 = len>>1;
Packit 664db3
   ALLOC(_X, lag, celt_word16_t);
Packit 664db3
   X = _X;
Packit 664db3
#ifndef SHORTCUTS
Packit 664db3
   ALLOC(curve, n2, celt_mask_t);
Packit 664db3
#endif
Packit 664db3
   CELT_MEMSET(X,0,lag);
Packit 664db3
   /* Sum all channels of the current frame and copy into X in bit-reverse order */
Packit 664db3
   for (c=0;c
Packit 664db3
   {
Packit 664db3
      const celt_sig_t * restrict xptr = &x[c];
Packit 664db3
      for (i=0;i
Packit 664db3
      {
Packit 664db3
         X[2*BITREV(fft,i)] += SHR32(*xptr,INPUT_SHIFT);
Packit 664db3
         xptr += C;
Packit 664db3
         X[2*BITREV(fft,i)+1] += SHR32(*xptr,INPUT_SHIFT);
Packit 664db3
         xptr += C;
Packit 664db3
      }
Packit 664db3
   }
Packit 664db3
   /* Applying the window in the bit-reverse domain. It's a bit weird, but it
Packit 664db3
      can help save memory */
Packit 664db3
   wptr = window;
Packit 664db3
   for (i=0;i<overlap>>1;i++)
Packit 664db3
   {
Packit 664db3
      X[2*BITREV(fft,i)]        = MULT16_16_Q15(wptr[0], X[2*BITREV(fft,i)]);
Packit 664db3
      X[2*BITREV(fft,i)+1]      = MULT16_16_Q15(wptr[1], X[2*BITREV(fft,i)+1]);
Packit 664db3
      X[2*BITREV(fft,L2-i-1)]   = MULT16_16_Q15(wptr[1], X[2*BITREV(fft,L2-i-1)]);
Packit 664db3
      X[2*BITREV(fft,L2-i-1)+1] = MULT16_16_Q15(wptr[0], X[2*BITREV(fft,L2-i-1)+1]);
Packit 664db3
      wptr += 2;
Packit 664db3
   }
Packit 664db3
   normalise16(X, lag, 8192);
Packit 664db3
   /*for (i=0;i
Packit 664db3
   /* Forward real FFT (in-place) */
Packit 664db3
   real16_fft_inplace(fft, X, lag);
Packit 664db3
Packit 664db3
   if (spectrum)
Packit 664db3
   {
Packit 664db3
      for (i=0;i
Packit 664db3
      {
Packit 664db3
         spectrum[2*i] = X[4*i];
Packit 664db3
         spectrum[2*i+1] = X[4*i+1];
Packit 664db3
      }
Packit 664db3
   }
Packit 664db3
#ifndef SHORTCUTS
Packit 664db3
   compute_masking(decay, X, curve, lag);
Packit 664db3
#endif
Packit 664db3
   
Packit 664db3
   /* Deferred allocation to reduce peak stack usage */
Packit 664db3
   ALLOC(_Y, lag, celt_word16_t);
Packit 664db3
   Y = _Y;
Packit 664db3
   yptr = &y[0];
Packit 664db3
   /* Copy first channel of the past audio into Y in bit-reverse order */
Packit 664db3
   for (i=0;i
Packit 664db3
   {
Packit 664db3
      Y[2*BITREV(fft,i)] = SHR32(*yptr,INPUT_SHIFT);
Packit 664db3
      yptr += C;
Packit 664db3
      Y[2*BITREV(fft,i)+1] = SHR32(*yptr,INPUT_SHIFT);
Packit 664db3
      yptr += C;
Packit 664db3
   }
Packit 664db3
   /* Add remaining channels into Y in bit-reverse order */
Packit 664db3
   for (c=1;c
Packit 664db3
   {
Packit 664db3
      yptr = &y[c];
Packit 664db3
      for (i=0;i
Packit 664db3
      {
Packit 664db3
         Y[2*BITREV(fft,i)] += SHR32(*yptr,INPUT_SHIFT);
Packit 664db3
         yptr += C;
Packit 664db3
         Y[2*BITREV(fft,i)+1] += SHR32(*yptr,INPUT_SHIFT);
Packit 664db3
         yptr += C;
Packit 664db3
      }
Packit 664db3
   }
Packit 664db3
   normalise16(Y, lag, 8192);
Packit 664db3
   /* Forward real FFT (in-place) */
Packit 664db3
   real16_fft_inplace(fft, Y, lag);
Packit 664db3
Packit 664db3
   /* Compute cross-spectrum using the inverse masking curve as weighting */
Packit 664db3
   Xptr = &X[2];
Packit 664db3
   Yptr = &Y[2];
Packit 664db3
   for (i=1;i
Packit 664db3
   {
Packit 664db3
      celt_word16_t Xr, Xi, n;
Packit 664db3
      /* weight = 1/sqrt(curve) */
Packit 664db3
      Xr = Xptr[0];
Packit 664db3
      Xi = Xptr[1];
Packit 664db3
#ifdef SHORTCUTS
Packit 664db3
      /*n = SHR32(32767,(celt_ilog2(EPSILON+curve[i])>>1));*/
Packit 664db3
      n = 1+(8192>>(celt_ilog2(1+MULT16_16(Xr,Xr)+MULT16_16(Xi,Xi))>>1));
Packit 664db3
      /* Pre-multiply X by n, so we can keep everything in 16 bits */
Packit 664db3
      Xr = MULT16_16_16(n, Xr);
Packit 664db3
      Xi = MULT16_16_16(n, Xi);
Packit 664db3
#else
Packit 664db3
      n = celt_rsqrt(EPSILON+curve[i]);
Packit 664db3
      /* Pre-multiply X by n, so we can keep everything in 16 bits */
Packit 664db3
      Xr = EXTRACT16(SHR32(MULT16_16(n, Xr),3));
Packit 664db3
      Xi = EXTRACT16(SHR32(MULT16_16(n, Xi),3));
Packit 664db3
#endif
Packit 664db3
      /* Cross-spectrum between X and conj(Y) */
Packit 664db3
      *Xptr++ = ADD16(MULT16_16_Q15(Xr, Yptr[0]), MULT16_16_Q15(Xi,Yptr[1]));
Packit 664db3
      *Xptr++ = SUB16(MULT16_16_Q15(Xr, Yptr[1]), MULT16_16_Q15(Xi,Yptr[0]));
Packit 664db3
      Yptr += 2;
Packit 664db3
   }
Packit 664db3
   /*printf ("\n");*/
Packit 664db3
   X[0] = X[1] = 0;
Packit 664db3
   /*for (i=0;i
Packit 664db3
   normalise16(X, lag, 50);
Packit 664db3
   /* Inverse half-complex to real FFT gives us the correlation */
Packit 664db3
   real16_ifft(fft, X, Y, lag);
Packit 664db3
   
Packit 664db3
   /* The peak in the correlation gives us the pitch */
Packit 664db3
   *pitch = find_max16(Y, max_pitch);
Packit 664db3
   RESTORE_STACK;
Packit 664db3
}