ref: 5b50f4bf81d532de20bc07be795a7787348bcadd
parent: b7ed44ba0a3df8a95c6e0fe9fc86245a5a6485d5
author: Jean-Marc Valin <[email protected]>
date: Mon Feb 11 06:50:20 EST 2008
Decays corresponding to the psychoacoustic spreading function are now pre-computed (instead of computing tons of pow() uselessly all the time)
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -64,6 +64,7 @@
mdct_lookup mdct_lookup;
kiss_fftr_cfg fft;
+ struct PsyDecay psy;
float *window;
float *in_mem;
@@ -98,6 +99,7 @@
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 @@
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 @@
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 */
--- a/libcelt/pitch.c
+++ b/libcelt/pitch.c
@@ -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 @@
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++)
{
--- a/libcelt/pitch.h
+++ b/libcelt/pitch.h
@@ -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
--- a/libcelt/psy.c
+++ b/libcelt/psy.c
@@ -31,22 +31,22 @@
#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,16 +58,29 @@
/* 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) */
@@ -74,7 +87,7 @@
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 @@
}
/* 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 @@
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 @@
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);
}
--- a/libcelt/psy.h
+++ b/libcelt/psy.h
@@ -31,8 +31,17 @@
#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 */