merge with aubio-mfcc branch, adding filterbank and mfcc first draft. thank you Amaury
authorPaul Brossier <piem@piem.org>
Sat, 24 Nov 2007 17:46:30 +0000 (18:46 +0100)
committerPaul Brossier <piem@piem.org>
Sat, 24 Nov 2007 17:46:30 +0000 (18:46 +0100)
1  2 
examples/Makefile.am
src/Makefile.am
src/aubio.h
src/filterbank.c
src/mfcc.c
swig/aubio.i
tests/python/demo/plot_mfcc_filterbank.py
tests/python/filterbank.py
tests/python/filterbank_mfcc.txt

Simple merge
diff --cc src/Makefile.am
Simple merge
diff --cc src/aubio.h
Simple merge
index 0000000000000000000000000000000000000000,30c2942c1f004264ccd720e992175015c58b8658..d60890a000568c37e4595dba4b74b5f699a4198b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,221 +1,220 @@@
 -#define USE_EQUAL_GAIN 1
+ /*
+    Copyright (C) 2007 Amaury Hazan <ahazan@iua.upf.edu>
+                   and Paul Brossier <piem@piem.org>
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+ #include "aubio_priv.h"
+ #include "sample.h"
+ #include "filterbank.h"
+ #include "mathutils.h"
+ #include "stdio.h"
+ #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;
+ };
+ aubio_filterbank_t * new_aubio_filterbank(uint_t n_filters, uint_t win_s){
+   /** allocating space for filterbank object */
+   aubio_filterbank_t * fb = AUBIO_NEW(aubio_filterbank_t);
+   uint_t filter_cnt;
+   fb->win_s=win_s;
+   fb->n_filters=n_filters;
+   /** allocating filter tables */
+   fb->filters=AUBIO_ARRAY(fvec_t*,n_filters);
+   for (filter_cnt=0; filter_cnt<n_filters; filter_cnt++)
+     /* considering one-channel filters */
+     fb->filters[filter_cnt]=new_fvec(win_s, 1);
+   return fb;
+ }
+ /*
+ FB initialization based on Slaney's auditory toolbox
+ TODO:
+   *solve memory leak problems while
+   *solve quantization issues when constructing signal:
+     *bug for win_s=512
+     *corrections for win_s=1024 -> why even filters with smaller amplitude
+ */
+ aubio_filterbank_t * new_aubio_filterbank_mfcc(uint_t n_filters, uint_t win_s, uint_t samplerate, smpl_t freq_min, smpl_t freq_max){
+   
+   aubio_filterbank_t * fb = new_aubio_filterbank(n_filters, win_s);
+   
+   
+   //slaney params
+   smpl_t lowestFrequency = 133.3333;
+   smpl_t linearSpacing = 66.66666666;
+   smpl_t logSpacing = 1.0711703;
+   uint_t linearFilters = 13;
+   uint_t logFilters = 27;
+   uint_t allFilters = linearFilters + logFilters;
+   
+   //buffers for computing filter frequencies
+   fvec_t * freqs=new_fvec(allFilters+2 , 1);
+   
+   fvec_t * lower_freqs=new_fvec( allFilters, 1);
+   fvec_t * upper_freqs=new_fvec( allFilters, 1);
+   fvec_t * center_freqs=new_fvec( allFilters, 1);
+   fvec_t * triangle_heights=new_fvec( allFilters, 1);
+   //lookup table of each bin frequency in hz
+   fvec_t * fft_freqs=new_fvec(win_s, 1);
+   uint_t filter_cnt, bin_cnt;
+   
+   //first step: filling all the linear filter frequencies
+   for(filter_cnt=0; filter_cnt<linearFilters; filter_cnt++){
+     freqs->data[0][filter_cnt]=lowestFrequency+ filter_cnt*linearSpacing;
+   }
+   smpl_t lastlinearCF=freqs->data[0][filter_cnt-1];
+   
+   //second step: filling all the log filter frequencies
+   for(filter_cnt=0; filter_cnt<logFilters+2; filter_cnt++){
+     freqs->data[0][filter_cnt+linearFilters] = 
+       lastlinearCF*(pow(logSpacing,filter_cnt+1));
+   }
+   //Option 1. copying interesting values to lower_freqs, center_freqs and upper freqs arrays
+   //TODO: would be nicer to have a reference to freqs->data, anyway we do not care in this init step
+     
+   for(filter_cnt=0; filter_cnt<allFilters; filter_cnt++){
+     lower_freqs->data[0][filter_cnt]=freqs->data[0][filter_cnt];
+     center_freqs->data[0][filter_cnt]=freqs->data[0][filter_cnt+1];
+     upper_freqs->data[0][filter_cnt]=freqs->data[0][filter_cnt+2];
+   }
+   //computing triangle heights so that each triangle has unit area
+   for(filter_cnt=0; filter_cnt<allFilters; filter_cnt++){
+     triangle_heights->data[0][filter_cnt] = 2./(upper_freqs->data[0][filter_cnt] 
+       - lower_freqs->data[0][filter_cnt]);
+   }
+   
+   //AUBIO_DBG("filter tables frequencies\n");
+   //for(filter_cnt=0; filter_cnt<allFilters; filter_cnt++)
+   //  AUBIO_DBG("filter n. %d %f %f %f %f\n",
+   //    filter_cnt, lower_freqs->data[0][filter_cnt], 
+   //    center_freqs->data[0][filter_cnt], upper_freqs->data[0][filter_cnt], 
+   //    triangle_heights->data[0][filter_cnt]);
+   //filling the fft_freqs lookup table, which assigns the frequency in hz to each bin
+   for(bin_cnt=0; bin_cnt<win_s; bin_cnt++){
+     fft_freqs->data[0][bin_cnt]= aubio_bintofreq(bin_cnt, samplerate, win_s);
+   }
+   //building each filter table
+   for(filter_cnt=0; filter_cnt<allFilters; filter_cnt++){
+     //TODO:check special case : lower freq =0
+     //calculating rise increment in mag/Hz
+     smpl_t riseInc= triangle_heights->data[0][filter_cnt]/(center_freqs->data[0][filter_cnt]-lower_freqs->data[0][filter_cnt]);
+     
+     //zeroing begining of filter
+     for(bin_cnt=0; bin_cnt<win_s-1; bin_cnt++){
+       fb->filters[filter_cnt]->data[0][bin_cnt]=0.f;
+       if( fft_freqs->data[0][bin_cnt]  <= lower_freqs->data[0][filter_cnt] &&
+           fft_freqs->data[0][bin_cnt+1] > lower_freqs->data[0][filter_cnt]) {
+         break;
+       }
+     }
+     bin_cnt++;
+     
+     //positive slope
+     for(; bin_cnt<win_s-1; bin_cnt++){
+       fb->filters[filter_cnt]->data[0][bin_cnt]=(fft_freqs->data[0][bin_cnt]-lower_freqs->data[0][filter_cnt])*riseInc;
+       //if(fft_freqs->data[0][bin_cnt]<= center_freqs->data[0][filter_cnt] && fft_freqs->data[0][bin_cnt+1]> center_freqs->data[0][filter_cnt])
+       if(fft_freqs->data[0][bin_cnt+1]> center_freqs->data[0][filter_cnt])
+         break;
+     }
+     //bin_cnt++;
+     
+     //negative slope
+     for(; bin_cnt<win_s-1; bin_cnt++){
+       
+       //checking whether last value is less than 0...
+       smpl_t val=triangle_heights->data[0][filter_cnt]-(fft_freqs->data[0][bin_cnt]-center_freqs->data[0][filter_cnt])*riseInc;
+       if(val>=0)
+         fb->filters[filter_cnt]->data[0][bin_cnt]=val;
+       else fb->filters[filter_cnt]->data[0][bin_cnt]=0.f;
+       
+       //if(fft_freqs->data[0][bin_cnt]<= upper_freqs->data[0][bin_cnt] && fft_freqs->data[0][bin_cnt+1]> upper_freqs->data[0][filter_cnt])
+       //TODO: CHECK whether bugfix correct
+       if(fft_freqs->data[0][bin_cnt+1]> upper_freqs->data[0][filter_cnt])
+         break;
+     }
+     //bin_cnt++;
+     
+     //zeroing tail
+     for(; bin_cnt<win_s; bin_cnt++)
+       fb->filters[filter_cnt]->data[0][bin_cnt]=0.f;
+   }
+   
+   
+   del_fvec(freqs);
+   del_fvec(lower_freqs);
+   del_fvec(upper_freqs);
+   del_fvec(center_freqs);
+   del_fvec(triangle_heights);
+   del_fvec(fft_freqs);
+   return fb;
+ }
+ void del_aubio_filterbank(aubio_filterbank_t * fb){
+   uint_t filter_cnt;
+   /** deleting filter tables first */
+   for (filter_cnt=0; filter_cnt<fb->n_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->length); filter_cnt++){
+       out->data[0][filter_cnt] = 0.f;
+       for(n = 0; n < in->length; 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;
+ }
+ fvec_t * aubio_filterbank_getchannel(aubio_filterbank_t * f, uint_t channel) {
+   if ( (channel >= 0) && (channel < f->n_filters) ) { return f->filters[channel]; }
+   else { return NULL; }
+ }
diff --cc src/mfcc.c
index 0000000000000000000000000000000000000000,a77aae4a5f424b3ee40ae9c8ee7aff769f8e5273..2420d8037e4a12e6a48f88623e8f249a3771ec73
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,124 +1,124 @@@
 -  aubio_mfft_t * fft_dct;   /** fft object for dct */
+ /*
+    Copyright (C) 2006 Amaury Hazan
+    Ported to aubio from LibXtract
+    http://libxtract.sourceforge.net/
+    
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+ #include "aubio_priv.h"
+ #include "sample.h"
+ #include "fft.h"
+ #include "filterbank.h"
+ #include "mfcc.h"
+ #include "math.h"
+ /** Internal structure for mfcc object **/
+ struct aubio_mfcc_t_{
+   uint_t win_s;             /** grain length */
+   uint_t samplerate;        /** sample rate (needed?) */
+   uint_t channels;          /** number of channels */
+   uint_t n_filters;         /** number of  *filters */
+   uint_t n_coefs;           /** number of coefficients (<= n_filters/2 +1) */
+   smpl_t lowfreq;           /** lowest frequency for filters */ 
+   smpl_t highfreq;          /** highest frequency for filters */
+   aubio_filterbank_t * fb;  /** filter bank */
+   fvec_t * in_dct;          /** input buffer for dct * [fb->n_filters] */
 -  mfcc->fft_dct=new_aubio_mfft(n_filters, 1);
++  aubio_fft_t * fft_dct;   /** fft object for dct */
+   cvec_t * fftgrain_dct;    /** output buffer for dct */
+ };
+ aubio_mfcc_t * new_aubio_mfcc (uint_t win_s, uint_t samplerate, uint_t n_filters, 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);
+   //we need (n_coefs-1)*2 filters to obtain n_coefs coefficients after dct
+   //uint_t n_filters = (n_coefs-1)*2;
+   
+   mfcc->win_s=win_s;
+   mfcc->samplerate=samplerate;
+   mfcc->channels=channels;
+   mfcc->n_filters=n_filters;
+   mfcc->n_coefs=n_coefs;
+   mfcc->lowfreq=lowfreq;
+   mfcc->highfreq=highfreq;
+   
+   /** filterbank allocation */
+   mfcc->fb = new_aubio_filterbank_mfcc(n_filters, mfcc->win_s, samplerate, lowfreq, highfreq);
+   /** allocating space for fft object (used for dct) */
 -  /** deleting mfft object */
 -  del_aubio_mfft(mf->fft_dct);
++  mfcc->fft_dct=new_aubio_fft(n_filters, 1);
+   /** allocating buffers */
+   mfcc->in_dct=new_fvec(mfcc->win_s, 1);
+   
+   mfcc->fftgrain_dct=new_cvec(n_filters, 1);
+   return mfcc;
+ };
+ void del_aubio_mfcc(aubio_mfcc_t *mf){
+   /** deleting filterbank */
+   del_aubio_filterbank(mf->fb);
 -    aubio_mfft_do (mf->fft_dct, in, mf->fftgrain_dct);
++  /** deleting fft object */
++  del_aubio_fft(mf->fft_dct);
+   /** deleting buffers */
+   del_fvec(mf->in_dct);
+   del_cvec(mf->fftgrain_dct);
+   
+   /** deleting mfcc object */
+   AUBIO_FREE(mf);
+ }
+ /** intermediate dct involved in aubio_mfcc_do
+   \param mf mfcc object as returned by new_aubio_mfcc
+   \param in input spectrum (n_filters long)
+   \param out output mel coefficients buffer (n_filters/2 +1 long)
+ */
+ void aubio_dct_do(aubio_mfcc_t * mf, fvec_t *in, fvec_t *out);
+ void aubio_mfcc_do(aubio_mfcc_t * mf, cvec_t *in, fvec_t *out){
+     // 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; 
+     
+     aubio_dct_do(mf, mf->in_dct, out);
+     return;
+ }
+ void aubio_dct_do(aubio_mfcc_t * mf, fvec_t *in, fvec_t *out){
+     uint_t i;
+     //compute mag spectrum
++    aubio_fft_do (mf->fft_dct, in, mf->fftgrain_dct);
+     //extract real part of fft grain
+     for(i=0; i<mf->n_coefs ;i++){
+     //for(i=0; i<out->length;i++){
+       out->data[0][i]= mf->fftgrain_dct->norm[0][i]
+         *COS(mf->fftgrain_dct->phas[0][i]);
+     }
+     return;
+ }
diff --cc swig/aubio.i
index 90af8663596c9236350ad98b5a5a37efef68a12c,8984c9812a37d46b24b19a286d88290f2ff8a9fd..0ad423a9775c2cb1622f8fff99b791d30a572b46
@@@ -154,6 -148,19 +154,18 @@@ void aubio_autocorr(fvec_t * in, fvec_
  smpl_t aubio_zero_crossing_rate(fvec_t * input);
  smpl_t aubio_spectral_centroid(cvec_t * spectrum, smpl_t samplerate);
  
 -
+ /* filterbank */
+ aubio_filterbank_t * new_aubio_filterbank(uint_t win_s, uint_t channels);
+ aubio_filterbank_t * new_aubio_filterbank_mfcc(uint_t n_filters, uint_t win_s, uint_t samplerate, smpl_t freq_min, smpl_t freq_max);
+ void del_aubio_filterbank(aubio_filterbank_t * fb);
+ void aubio_filterbank_do(aubio_filterbank_t * fb, cvec_t * in, fvec_t *out);
+ fvec_t * aubio_filterbank_getchannel(aubio_filterbank_t * fb, uint_t channel);
+ /* mfcc */
+ aubio_mfcc_t * new_aubio_mfcc (uint_t win_s, uint_t samplerate, uint_t n_filters, uint_t n_coefs, smpl_t lowfreq, smpl_t highfreq, uint_t channels);
+ void del_aubio_mfcc(aubio_mfcc_t *mf);
+ void aubio_mfcc_do(aubio_mfcc_t *mf, cvec_t *in, fvec_t *out);
  /* scale */
  extern aubio_scale_t * new_aubio_scale(smpl_t flow, smpl_t fhig, smpl_t ilow, smpl_t ihig     );
  extern void aubio_scale_set (aubio_scale_t *s, smpl_t ilow, smpl_t ihig, smpl_t olow, smpl_t ohig);
index 0000000000000000000000000000000000000000,fb527f02addcb0491d829fe1326b2372b4962d26..fb527f02addcb0491d829fe1326b2372b4962d26
mode 000000,100755..100755
--- /dev/null
index 0000000000000000000000000000000000000000,3b04d290285af78752af2f22fda4667abd7586b6..3b04d290285af78752af2f22fda4667abd7586b6
mode 000000,100644..100644
--- /dev/null
index 0000000000000000000000000000000000000000,1a5443f3022228fedaef26eb3cc00a57f678fcb8..1a5443f3022228fedaef26eb3cc00a57f678fcb8
mode 000000,100644..100644
--- /dev/null