Decays corresponding to the psychoacoustic spreading function are now
authorJean-Marc Valin <Jean-Marc.Valin@csiro.au>
Mon, 11 Feb 2008 00:50:20 +0000 (11:50 +1100)
committerJean-Marc Valin <Jean-Marc.Valin@csiro.au>
Mon, 11 Feb 2008 00:50:20 +0000 (11:50 +1100)
pre-computed (instead of computing tons of pow() uselessly all the time)

libcelt/celt.c
libcelt/pitch.c
libcelt/pitch.h
libcelt/psy.c
libcelt/psy.h

index 653d6a3..766997e 100644 (file)
@@ -64,6 +64,7 @@ struct CELTEncoder {
    
    mdct_lookup mdct_lookup;
    kiss_fftr_cfg fft;
+   struct PsyDecay psy;
    
    float *window;
    float *in_mem;
@@ -98,6 +99,7 @@ CELTEncoder *celt_encoder_new(const CELTMode *mode)
 
    mdct_init(&st->mdct_lookup, 2*N);
    st->fft = kiss_fftr_alloc(MAX_PERIOD*C, 0, 0);
+   psydecay_init(&st->psy, MAX_PERIOD/2, st->Fs);
    
    st->window = celt_alloc(2*N*sizeof(float));
    st->in_mem = celt_alloc(N*C*sizeof(float));
@@ -131,6 +133,7 @@ void celt_encoder_destroy(CELTEncoder *st)
 
    mdct_clear(&st->mdct_lookup);
    kiss_fft_free(st->fft);
+   psydecay_clear(&st->psy);
 
    celt_free(st->window);
    celt_free(st->in_mem);
@@ -254,7 +257,7 @@ int celt_encode(CELTEncoder *st, celt_int16_t *pcm, unsigned char *compressed, i
          in[C*(B*N+i)+c] *= st->window[N+i];
       }
    }
-   find_spectral_pitch(st->fft, in, st->out_mem, MAX_PERIOD, (B+1)*N, C, &pitch_index);
+   find_spectral_pitch(st->fft, &st->psy, in, st->out_mem, MAX_PERIOD, (B+1)*N, C, &pitch_index);
    ec_enc_uint(&st->enc, pitch_index, MAX_PERIOD-(B+1)*N);
    
    /* Compute MDCTs of the pitch part */
index 67c8319..206f158 100644 (file)
@@ -26,7 +26,7 @@
 #include "pitch.h"
 #include "psy.h"
 
-void find_spectral_pitch(kiss_fftr_cfg fft, float *x, float *y, int lag, int len, int C, int *pitch)
+void find_spectral_pitch(kiss_fftr_cfg fft, struct PsyDecay *decay, float *x, float *y, int lag, int len, int C, int *pitch)
 {
    int c;
    int n2 = lag/2;
@@ -51,7 +51,7 @@ void find_spectral_pitch(kiss_fftr_cfg fft, float *x, float *y, int lag, int len
    kiss_fftr(fft, xx, X);
    kiss_fftr(fft, yy, Y);
    
-   compute_masking(X, curve, lag*C, 44100);
+   compute_masking(decay, X, curve, lag*C, 44100);
    
    for (i=1;i<C*n2;i++)
    {
index 4de2f36..8ebc129 100644 (file)
@@ -24,7 +24,8 @@
 #define _PITCH_H
 
 #include "kiss_fftr.h"
+#include "psy.h"
 
-void find_spectral_pitch(kiss_fftr_cfg fft, float *x, float *y, int lag, int len, int C, int *pitch);
+void find_spectral_pitch(kiss_fftr_cfg fft, struct PsyDecay *decay, float *x, float *y, int lag, int len, int C, int *pitch);
 
 #endif
index 6ba252a..0f7ffaf 100644 (file)
 
 #include "psy.h"
 #include <math.h>
+#include "os_support.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))
 #define fromBARK(z) (102.f*(z)-2.f*pow(z,2.f)+.4f*pow(z,3.f)+pow(1.46f,z)-1.f)
 
+
 /* Psychoacoustic spreading function. The idea here is compute a first order 
    recursive filter. The filter coefficient is frequency dependent and 
    chosen such that we have a -10dB/Bark slope on the right side and a -25dB/Bark
    slope on the left side. */
-static void spreading_func(float *psd, float *mask, int len, int Fs)
+void psydecay_init(struct PsyDecay *decay, int len, int Fs)
 {
    int i;
-   float decayL[len], decayR[len];
-   float mem;
-   //for (i=0;i<len;i++) printf ("%f ", psd[i]);
-   /* This can easily be tabulated, which makes the function very fast. */
+   decay->decayR = celt_alloc(sizeof(float)*len);
+   decay->decayL = celt_alloc(sizeof(float)*len);
    for (i=0;i<len;i++)
    {
       float f;
@@ -58,23 +58,36 @@ static void spreading_func(float *psd, float *mask, int len, int Fs)
       /* Back to FFT bin units */
       deriv *= Fs*(1/(2.f*len));
       /* decay corresponding to -10dB/Bark */
-      decayR[i] = pow(.1f, deriv);
+      decay->decayR[i] = pow(.1f, deriv);
       /* decay corresponding to -25dB/Bark */
-      decayL[i] = pow(0.0031623f, deriv);
+      decay->decayL[i] = pow(0.0031623f, deriv);
       //printf ("%f %f\n", decayL[i], decayR[i]);
    }
+}
+
+void psydecay_clear(struct PsyDecay *decay)
+{
+   celt_free(decay->decayR);
+   celt_free(decay->decayL);
+}
+
+static void spreading_func(struct PsyDecay *d, float *psd, float *mask, int len, int Fs)
+{
+   int i;
+   float mem;
+   //for (i=0;i<len;i++) printf ("%f ", psd[i]);
    /* Compute right slope (-10 dB/Bark) */
    mem=psd[0];
    for (i=0;i<len;i++)
    {
-      mask[i] = (1-decayR[i])*psd[i] + decayR[i]*mem;
+      mask[i] = (1-d->decayR[i])*psd[i] + d->decayR[i]*mem;
       mem = mask[i];
    }
    /* Compute left slope (-25 dB/Bark) */
    mem=mask[len-1];
    for (i=len-1;i>=0;i--)
    {
-      mask[i] = (1-decayR[i])*mask[i] + decayL[i]*mem;
+      mask[i] = (1-d->decayR[i])*mask[i] + d->decayL[i]*mem;
       mem = mask[i];
    }
    //for (i=0;i<len;i++) printf ("%f ", mask[i]); printf ("\n");
@@ -104,7 +117,7 @@ static void spreading_func(float *psd, float *mask, int len, int Fs)
 }
 
 /* Compute a marking threshold from the spectrum X. */
-void compute_masking(float *X, float *mask, int len, int Fs)
+void compute_masking(struct PsyDecay *decay, float *X, float *mask, int len, int Fs)
 {
    int i;
    int N=len/2;
@@ -114,11 +127,11 @@ void compute_masking(float *X, float *mask, int len, int Fs)
       psd[i] = X[i*2]*X[i*2] + X[i*2+1]*X[i*2+1];
    /* TODO: Do tone masking */
    /* Noise masking */
-   spreading_func(psd, mask, N, Fs);
+   spreading_func(decay, psd, mask, N, Fs);
    
 }
 
-void compute_mdct_masking(float *X, float *mask, int len, int Fs)
+void compute_mdct_masking(struct PsyDecay *decay, float *X, float *mask, int len, int Fs)
 {
    int i;
    float psd[len];
@@ -132,6 +145,6 @@ void compute_mdct_masking(float *X, float *mask, int len, int Fs)
    psd[len-1] = .5*(mask[len-1]+mask[len-2]);
    /* TODO: Do tone masking */
    /* Noise masking */
-   spreading_func(psd, mask, len, Fs);
+   spreading_func(decay, psd, mask, len, Fs);
    
 }
index 06e9183..6b92a37 100644 (file)
 #ifndef PSY_H
 #define PSY_H
 
-void compute_masking(float *X, float *mask, int len, int Fs);
+struct PsyDecay {
+   float *decayL;
+   float *decayR;
+};
 
-void compute_mdct_masking(float *X, float *mask, int len, int Fs);
+void psydecay_init(struct PsyDecay *decay, int len, int Fs);
+
+void psydecay_clear(struct PsyDecay *decay);
+
+void compute_masking(struct PsyDecay *decay, float *X, float *mask, int len, int Fs);
+
+void compute_mdct_masking(struct PsyDecay *decay, float *X, float *mask, int len, int Fs);
 
 #endif /* PSY_H */