shithub: opus

Download patch

ref: dffd9449b5cdf2833af293c8d18aedebb6eb8728
parent: 01e177377cb359da31b73406080545e0ac521af6
author: Jean-Marc Valin <[email protected]>
date: Wed Oct 15 03:29:58 EDT 2008

Tonality estimation code

--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -471,8 +471,16 @@
    }
    /* Pitch analysis: we do it early to save on the peak stack space */
    if (st->pitch_enabled && !shortBlocks)
-      find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, in, st->out_mem, st->mode->window, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index);
-
+   {
+#ifdef EXP_PSY
+      VARDECL(celt_word16_t, X);
+      ALLOC(X, MAX_PERIOD/2, celt_word16_t);
+      find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, in, st->out_mem, st->mode->window, X, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index);
+      compute_tonality(st->mode, X, st->psy_mem, MAX_PERIOD);
+#else
+      find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, in, st->out_mem, st->mode->window, NULL, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index);
+#endif
+   }
    ALLOC(freq, C*N, celt_sig_t); /**< Interleaved signal MDCTs */
    
    /*for (i=0;i<(B+1)*C*N;i++) printf ("%f(%d) ", in[i], i); printf ("\n");*/
@@ -480,13 +488,13 @@
    compute_mdcts(st->mode, shortBlocks, in, freq);
 
 #ifdef EXP_PSY
-   CELT_MOVE(st->psy_mem, st->out_mem+N, MAX_PERIOD+st->overlap-N);
+   /*CELT_MOVE(st->psy_mem, st->out_mem+N, MAX_PERIOD+st->overlap-N);
    for (i=0;i<N;i++)
       st->psy_mem[MAX_PERIOD+st->overlap-N+i] = in[C*(st->overlap+i)];
    for (c=1;c<C;c++)
       for (i=0;i<N;i++)
          st->psy_mem[MAX_PERIOD+st->overlap-N+i] += in[C*(st->overlap+i)+c];
-
+   */
    ALLOC(mask, N, celt_sig_t);
    compute_mdct_masking(&st->psy, freq, st->psy_mem, mask, C*N);
 
@@ -846,7 +854,7 @@
    compute_mdcts(st->mode, st->mode->window, st->out_mem+pitch_index*C, freq);
 
 #else
-   find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, st->out_mem+MAX_PERIOD-len, st->out_mem, st->mode->window, len, MAX_PERIOD-len-100, &pitch_index);
+   find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, st->out_mem+MAX_PERIOD-len, st->out_mem, st->mode->window, NULL, len, MAX_PERIOD-len-100, &pitch_index);
    pitch_index = MAX_PERIOD-len-pitch_index;
    offset = MAX_PERIOD-pitch_index;
    while (offset+len >= MAX_PERIOD)
--- a/libcelt/pitch.c
+++ b/libcelt/pitch.c
@@ -104,7 +104,7 @@
 
 #define INPUT_SHIFT 15
 
-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 max_pitch, 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, celt_word16_t * restrict spectrum, int len, int max_pitch, int *pitch)
 {
    int c, i;
    VARDECL(celt_word16_t, _X);
@@ -158,6 +158,14 @@
    /* Forward real FFT (in-place) */
    real16_fft_inplace(fft, X, lag);
 
+   if (spectrum)
+   {
+      for (i=0;i<lag/4;i++)
+      {
+         spectrum[2*i] = X[4*i];
+         spectrum[2*i+1] = X[4*i+1];
+      }
+   }
 #ifndef SHORTCUTS
    compute_masking(decay, X, curve, lag);
 #endif
--- a/libcelt/pitch.h
+++ b/libcelt/pitch.h
@@ -48,6 +48,6 @@
 /** Find the optimal delay for the pitch prediction. Computation is
     done in the frequency domain, both to save time and to make it
     easier to apply psychoacoustic weighting */
-void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyDecay *decay, const celt_sig_t *x, const celt_sig_t *y, const celt_word16_t *window, int len, int max_pitch, int *pitch);
+void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyDecay *decay, const celt_sig_t *x, const celt_sig_t *y, const celt_word16_t *window, celt_word16_t * restrict X, int len, int max_pitch, int *pitch);
 
 #endif
--- a/libcelt/psy.c
+++ b/libcelt/psy.c
@@ -38,6 +38,7 @@
 #include "os_support.h"
 #include "arch.h"
 #include "stack_alloc.h"
+#include "mathops.h"
 
 /* The Vorbis freq<->Bark mapping */
 #define toBARK(n)   (13.1f*atan(.00074f*(n))+2.24f*atan((n)*(n)*1.85e-8f)+1e-4f*(n))
@@ -161,5 +162,41 @@
    /* Noise masking */
    spreading_func(decay, mask, len);
    RESTORE_STACK;  
+}
+
+void compute_tonality(const CELTMode *m, celt_word16_t * restrict X, celt_word16_t * mem, int len)
+{
+   int i;
+   celt_word16_t norm_1;
+   celt_word16_t *mem2;
+   int N = len>>2;
+
+   mem2 = mem+2*N;
+   X[0] = 0;
+   X[1] = 0;
+   for (i=1;i<N;i++)
+   {
+      celt_word16_t re, im, re2, im2;
+      re = X[2*i];
+      im = X[2*i+1];
+      /* Normalise spectrum */
+      norm_1 = celt_rsqrt(MAC16_16(MULT16_16(re,re), im,im));
+      re = MULT16_16(re, norm_1);
+      im = MULT16_16(im, norm_1);
+      /* Phase derivative */
+      re2 = re*mem[2*i] + im*mem[2*i+1];
+      im2 = im*mem[2*i] - re*mem[2*i+1];
+      mem[2*i] = re;
+      mem[2*i+1] = im;
+      /* Phase second derivative */
+      re = re2*mem2[2*i] + im2*mem2[2*i+1];
+      im = im2*mem2[2*i] - re2*mem2[2*i+1];
+      mem2[2*i] = re2;
+      mem2[2*i+1] = im2;
+      /*printf ("%f ", re);*/
+      X[2*i] = re;
+      X[2*i+1] = im;
+   }
+   /*printf ("\n");*/
 }
 #endif
--- a/libcelt/psy.h
+++ b/libcelt/psy.h
@@ -32,6 +32,7 @@
 #define PSY_H
 
 #include "arch.h"
+#include "celt.h"
 
 struct PsyDecay {
    /*celt_word16_t *decayL;*/
@@ -49,5 +50,7 @@
 
 /** Compute the masking curve for an input (MDCT) spectrum X */
 void compute_mdct_masking(const struct PsyDecay *decay, celt_word32_t *X, celt_word16_t *long_window, celt_mask_t *mask, int len);
+
+void compute_tonality(const CELTMode *m, celt_word16_t * restrict X, celt_word16_t * mem, int len);
 
 #endif /* PSY_H */