From b276dee4f0888ff5eaff9f03244e2d49f6e7241b Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Sat, 8 Sep 2007 15:59:11 +0200 Subject: [PATCH] mfcc.{c,h}, filterbank.{c,h}: move filter initialisation into new_aubio_filterbank_mfcc --- src/filterbank.c | 136 +++++++++++++++++++++++++++++++++++++++++-- src/filterbank.h | 27 ++++----- src/mfcc.c | 146 +++-------------------------------------------- src/mfcc.h | 1 + 4 files changed, 152 insertions(+), 158 deletions(-) diff --git a/src/filterbank.c b/src/filterbank.c index bfe1a80f..32906151 100644 --- a/src/filterbank.c +++ b/src/filterbank.c @@ -23,13 +23,17 @@ */ #include "aubio_priv.h" +#include "sample.h" #include "filterbank.h" +#define USE_EQUAL_GAIN 1 +#define VERY_SMALL_NUMBER 2e-42 + /** \brief A structure to store a set of n_filters filters of lenghts win_s */ struct aubio_filterbank_t_ { uint_t win_s; uint_t n_filters; - fvec_t *filters; + fvec_t **filters; }; aubio_filterbank_t * new_aubio_filterbank(uint_t n_filters, uint_t win_s){ @@ -40,21 +44,141 @@ aubio_filterbank_t * new_aubio_filterbank(uint_t n_filters, uint_t win_s){ fb->n_filters=n_filters; /** allocating filter tables */ - fb->filters=AUBIO_ARRAY(n_filters,fvec_t); + fb->filters=AUBIO_ARRAY(fvec_t*,n_filters); for (filter_cnt=0; filter_cntfilters[filter_cnt]=new_fvec(win_s, 1); + + return fb; +} + +aubio_filterbank_t * new_aubio_filterbank_mfcc(uint_t n_filters, uint_t win_s, smpl_t samplerate, smpl_t freq_min, smpl_t freq_max){ + smpl_t nyquist = samplerate/2.; + uint_t style = 1; + aubio_filterbank_t * fb = new_aubio_filterbank(n_filters, win_s); + + uint_t n, i, k, *fft_peak, M, next_peak; + smpl_t norm, mel_freq_max, mel_freq_min, norm_fact, height, inc, val, + freq_bw_mel, *mel_peak, *height_norm, *lin_peak; + + mel_peak = height_norm = lin_peak = NULL; + fft_peak = NULL; + norm = 1; + + mel_freq_max = 1127 * log(1 + freq_max / 700); + mel_freq_min = 1127 * log(1 + freq_min / 700); + freq_bw_mel = (mel_freq_max - mel_freq_min) / fb->n_filters; + + mel_peak = (smpl_t *)malloc((fb->n_filters + 2) * sizeof(smpl_t)); + /* +2 for zeros at start and end */ + lin_peak = (smpl_t *)malloc((fb->n_filters + 2) * sizeof(smpl_t)); + fft_peak = (uint_t *)malloc((fb->n_filters + 2) * sizeof(uint_t)); + height_norm = (smpl_t *)malloc(fb->n_filters * sizeof(smpl_t)); + + if(mel_peak == NULL || height_norm == NULL || + lin_peak == NULL || fft_peak == NULL) + return NULL; + + M = fb->win_s >> 1; + + mel_peak[0] = mel_freq_min; + lin_peak[0] = 700 * (exp(mel_peak[0] / 1127) - 1); + fft_peak[0] = lin_peak[0] / nyquist * M; + + + for (n = 1; n <= fb->n_filters; n++){ + /*roll out peak locations - mel, linear and linear on fft window scale */ + mel_peak[n] = mel_peak[n - 1] + freq_bw_mel; + lin_peak[n] = 700 * (exp(mel_peak[n] / 1127) -1); + fft_peak[n] = lin_peak[n] / nyquist * M; + } + + for (n = 0; n < fb->n_filters; n++){ + /*roll out normalised gain of each peak*/ + if (style == USE_EQUAL_GAIN){ + height = 1; + norm_fact = norm; + } + else{ + height = 2 / (lin_peak[n + 2] - lin_peak[n]); + norm_fact = norm / (2 / (lin_peak[2] - lin_peak[0])); + } + height_norm[n] = height * norm_fact; + } + + i = 0; + + for(n = 0; n < fb->n_filters; n++){ + + /*calculate the rise increment*/ + if(n > 0) + inc = height_norm[n] / (fft_peak[n] - fft_peak[n - 1]); + else + inc = height_norm[n] / fft_peak[n]; + val = 0; + + /*zero the start of the array*/ + for(k = 0; k < i; k++) + //fft_tables[n][k] = 0.f; + fb->filters[n]->data[0][k]=0.f; + + /*fill in the rise */ + for(; i <= fft_peak[n]; i++){ + // fft_tables[n][i] = val; + fb->filters[n]->data[0][k]=val; + val += inc; + } + + /*calculate the fall increment */ + inc = height_norm[n] / (fft_peak[n + 1] - fft_peak[n]); + + val = 0; + next_peak = fft_peak[n + 1]; + + /*reverse fill the 'fall' */ + for(i = next_peak; i > fft_peak[n]; i--){ + //fft_tables[n][i] = val; + fb->filters[n]->data[0][k]=val; + val += inc; + } + + /*zero the rest of the array*/ + for(k = next_peak + 1; k < fb->win_s; k++) + //fft_tables[n][k] = 0.f; + fb->filters[n]->data[0][k]=0.f; + } + + free(mel_peak); + free(lin_peak); + free(height_norm); + free(fft_peak); + + return fb; } + void del_aubio_filterbank(aubio_filterbank_t * fb){ - - int filter_cnt; + uint_t filter_cnt; /** deleting filter tables first */ for (filter_cnt=0; filter_cntn_filters; filter_cnt++) del_fvec(fb->filters[filter_cnt]); AUBIO_FREE(fb->filters); AUBIO_FREE(fb); - } +void aubio_filterbank_do(aubio_filterbank_t * f, cvec_t * in, fvec_t *out) { + uint_t n, filter_cnt; + for(filter_cnt = 0; filter_cnt < f->n_filters; filter_cnt++){ + out->data[0][filter_cnt] = 0.f; + for(n = 0; n < f->win_s; n++){ + out->data[0][filter_cnt] += in->norm[0][n] + * f->filters[filter_cnt]->data[0][n]; + } + out->data[0][filter_cnt] = + LOG(out->data[0][filter_cnt] < VERY_SMALL_NUMBER ? + VERY_SMALL_NUMBER : out->data[0][filter_cnt]); + } + + return; +} diff --git a/src/filterbank.h b/src/filterbank.h index 6cefdfc3..bc9e441c 100644 --- a/src/filterbank.h +++ b/src/filterbank.h @@ -43,31 +43,28 @@ typedef struct aubio_filterbank_t_ aubio_filterbank_t; aubio_filterbank_t * new_aubio_filterbank(uint_t n_filters, uint_t win_s); -/** destroy filterbank object - - \param fb filterbank, as returned by new_aubio_filterbank method - -*/ -void del_aubio_filterbank(aubio_filterbank_t * fb); - /** filterbank initialization for mel filters - \param fb filterbank, as returned by new_aubio_filterbank method \param nyquist nyquist frequency, i.e. half of the sampling rate \param style libxtract style \param freqmin lowest filter frequency \param freqmax highest filter frequency */ -void aubio_filterbank_mfcc_init(aubio_filterbank_t * fb, smpl_t nyquist, int style, smpl_t freq_min, smpl_t freq_max); +aubio_filterbank_t * new_aubio_filterbank_mfcc(uint_t n_filters, uint_t win_s, smpl_t samplerate, smpl_t freq_min, smpl_t freq_max); -// Initialization -/** \brief A function to initialise a mel filter bank - * - * It is up to the caller to pass in a pointer to memory allocated for freq_bands arrays of length N. This function populates these arrays with magnitude coefficients representing the mel filterbank on a linear scale - */ -int aubio_mfcc_init(int N, smpl_t nyquist, int style, smpl_t freq_min, smpl_t freq_max, int freq_bands, smpl_t ** fft_tables); +/** destroy filterbank object + + \param fb filterbank, as returned by new_aubio_filterbank method + +*/ +void del_aubio_filterbank(aubio_filterbank_t * fb); + +/** compute filterbank + +*/ +void aubio_filterbank_do(aubio_filterbank_t * fb, cvec_t * in, fvec_t *out); #ifdef __cplusplus } diff --git a/src/mfcc.c b/src/mfcc.c index 37c3f943..fe5ea48a 100644 --- a/src/mfcc.c +++ b/src/mfcc.c @@ -27,10 +27,6 @@ #include "mfcc.h" #include "math.h" -#define VERY_SMALL_NUMBER 2e-42 -#define USE_EQUAL_GAIN 1 - - /** Internal structure for mfcc object **/ struct aubio_mfcc_t_{ @@ -47,17 +43,6 @@ struct aubio_mfcc_t_{ }; -/** filterbank initialization for mel filters - - \param fb filterbank, as returned by new_aubio_filterbank method - \param nyquist nyquist frequency, i.e. half of the sampling rate - \param style libxtract style - \param freqmin lowest filter frequency - \param freqmax highest filter frequency - -*/ -void aubio_filterbank_mfcc_init(aubio_filterbank_t * fb, smpl_t nyquist, int style, smpl_t freq_min, smpl_t freq_max); - aubio_mfcc_t * new_aubio_mfcc (uint_t win_s, uint_t samplerate ,uint_t n_coefs, smpl_t lowfreq, smpl_t highfreq, uint_t channels){ /** allocating space for mfcc object */ aubio_mfcc_t * mfcc = AUBIO_NEW(aubio_mfcc_t); @@ -73,19 +58,16 @@ aubio_mfcc_t * new_aubio_mfcc (uint_t win_s, uint_t samplerate ,uint_t n_coefs, mfcc->highfreq=highfreq; /** filterbank allocation */ - mfcc->fb = new_aubio_filterbank(n_filters, mfcc->win_s); + mfcc->fb = new_aubio_filterbank_mfcc(n_filters, mfcc->win_s, samplerate, lowfreq, highfreq); /** allocating space for fft object (used for dct) */ - mfcc->fft_dct=new_aubio_mfft(mfcc->win_s, 1); + mfcc->fft_dct=new_aubio_mfft(n_filters, 1); /** allocating buffers */ mfcc->in_dct=new_fvec(mfcc->win_s, 1); mfcc->fftgrain_dct=new_cvec(n_filters, 1); - /** populating the filterbank */ - aubio_filterbank_mfcc_init(mfcc->fb, (mfcc->samplerate)/2, mfcc->lowfreq, mfcc->highfreq); - return mfcc; }; @@ -103,18 +85,8 @@ void del_aubio_mfcc(aubio_mfcc_t *mf){ } void aubio_mfcc_do(aubio_mfcc_t * mf, cvec_t *in, fvec_t *out){ - - aubio_filterbank_t *f = mf->fb; - uint_t n, filter_cnt; - - for(filter_cnt = 0; filter_cnt < f->n_filters; filter_cnt++){ - mf->in_dct->data[0][filter_cnt] = 0.f; - for(n = 0; n < mf->win_s; n++){ - mf->in_dct->data[0][filter_cnt] += in->norm[0][n] * f->filters[filter_cnt]->data[0][n]; - } - mf->in_dct->data[0][filter_cnt] = LOG(mf->in_dct->data[0][filter_cnt] < VERY_SMALL_NUMBER ? VERY_SMALL_NUMBER : mf->in_dct->data[0][filter_cnt]); - } - + // compute filterbank + aubio_filterbank_do(mf->fb, in, mf->in_dct); //TODO: check that zero padding // the following line seems useless since the in_dct buffer has the correct size //for(n = filter + 1; n < N; n++) result[n] = 0; @@ -125,115 +97,15 @@ void aubio_mfcc_do(aubio_mfcc_t * mf, cvec_t *in, fvec_t *out){ } void aubio_dct_do(aubio_mfcc_t * mf, fvec_t *in, fvec_t *out){ + uint_t i; //compute mag spectrum aubio_mfft_do (mf->fft_dct, in, mf->fftgrain_dct); - - int i; //extract real part of fft grain - for(i=0; in_coefs ;i++){ - out->data[0][i]= mf->fftgrain_dct->norm[0][i]*COS(mf->fftgrain_dct->phas[0][i]); + //for(i=0; in_coefs ;i++){ + for(i=0; ilength;i++){ + out->data[0][i]= mf->fftgrain_dct->norm[0][i] + *COS(mf->fftgrain_dct->phas[0][i]); } - return; } -void aubio_filterbank_mfcc_init(aubio_filterbank_t * fb, smpl_t nyquist, int style, smpl_t freq_min, smpl_t freq_max){ - - int n, i, k, *fft_peak, M, next_peak; - smpl_t norm, mel_freq_max, mel_freq_min, norm_fact, height, inc, val, - freq_bw_mel, *mel_peak, *height_norm, *lin_peak; - - mel_peak = height_norm = lin_peak = NULL; - fft_peak = NULL; - norm = 1; - - mel_freq_max = 1127 * log(1 + freq_max / 700); - mel_freq_min = 1127 * log(1 + freq_min / 700); - freq_bw_mel = (mel_freq_max - mel_freq_min) / fb->n_filters; - - mel_peak = (smpl_t *)malloc((fb->n_filters + 2) * sizeof(smpl_t)); - /* +2 for zeros at start and end */ - lin_peak = (smpl_t *)malloc((fb->n_filters + 2) * sizeof(smpl_t)); - fft_peak = (int *)malloc((fb->n_filters + 2) * sizeof(int)); - height_norm = (smpl_t *)malloc(fb->n_filters * sizeof(smpl_t)); - - if(mel_peak == NULL || height_norm == NULL || - lin_peak == NULL || fft_peak == NULL) - return NULL; - - M = fb->win_s >> 1; - - mel_peak[0] = mel_freq_min; - lin_peak[0] = 700 * (exp(mel_peak[0] / 1127) - 1); - fft_peak[0] = lin_peak[0] / nyquist * M; - - - for (n = 1; n <= fb->n_filters; n++){ - /*roll out peak locations - mel, linear and linear on fft window scale */ - mel_peak[n] = mel_peak[n - 1] + freq_bw_mel; - lin_peak[n] = 700 * (exp(mel_peak[n] / 1127) -1); - fft_peak[n] = lin_peak[n] / nyquist * M; - } - - for (n = 0; n < fb->n_filters; n++){ - /*roll out normalised gain of each peak*/ - if (style == USE_EQUAL_GAIN){ - height = 1; - norm_fact = norm; - } - else{ - height = 2 / (lin_peak[n + 2] - lin_peak[n]); - norm_fact = norm / (2 / (lin_peak[2] - lin_peak[0])); - } - height_norm[n] = height * norm_fact; - } - - i = 0; - - for(n = 0; n < fb->n_filters; n++){ - - /*calculate the rise increment*/ - if(n > 0) - inc = height_norm[n] / (fft_peak[n] - fft_peak[n - 1]); - else - inc = height_norm[n] / fft_peak[n]; - val = 0; - - /*zero the start of the array*/ - for(k = 0; k < i; k++) - //fft_tables[n][k] = 0.f; - fb->filters[n]->data[0][k]=0.f; - - /*fill in the rise */ - for(; i <= fft_peak[n]; i++){ - // fft_tables[n][i] = val; - fb->filters[n]->data[0][k]=val; - val += inc; - } - - /*calculate the fall increment */ - inc = height_norm[n] / (fft_peak[n + 1] - fft_peak[n]); - - val = 0; - next_peak = fft_peak[n + 1]; - - /*reverse fill the 'fall' */ - for(i = next_peak; i > fft_peak[n]; i--){ - //fft_tables[n][i] = val; - fb->filters[n]->data[0][k]=val; - val += inc; - } - - /*zero the rest of the array*/ - for(k = next_peak + 1; k < fb->win_s; k++) - //fft_tables[n][k] = 0.f; - fb->filters[n]->data[0][k]=0.f; - } - - free(mel_peak); - free(lin_peak); - free(height_norm); - free(fft_peak); - -} - diff --git a/src/mfcc.h b/src/mfcc.h index c1cd5070..c86b089f 100644 --- a/src/mfcc.h +++ b/src/mfcc.h @@ -29,6 +29,7 @@ extern "C" { #endif +#include "sample.h" #include "filterbank.h" typedef struct aubio_mfcc_t_ aubio_mfcc_t; -- 2.26.2