source: src/filterbank.c @ aeb38cf

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since aeb38cf was bc4ba75, checked in by Amaury Hazan <mahmoudax@gmail.org>, 18 years ago

added mfcc binding

  • Property mode set to 100644
File size: 10.7 KB
RevLine 
[88199ce]1/*
[f918cb9]2   Copyright (C) 2007 Amaury Hazan <ahazan@iua.upf.edu>
3                  and Paul Brossier <piem@piem.org>
[88199ce]4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19*/
20
[f918cb9]21
[7c6c806d]22#include "aubio_priv.h"
[b276dee]23#include "sample.h"
[71d3bf0]24#include "filterbank.h"
[88199ce]25
[7a46bf6]26#include "stdio.h"
[7c6c806d]27
[b276dee]28#define USE_EQUAL_GAIN 1
29#define VERY_SMALL_NUMBER 2e-42
[7c6c806d]30
[8708556]31/** \brief A structure to store a set of n_filters filters of lenghts win_s */
32struct aubio_filterbank_t_ {
33    uint_t win_s;
34    uint_t n_filters;
[b276dee]35    fvec_t **filters;
[7c6c806d]36};
37
[8708556]38aubio_filterbank_t * new_aubio_filterbank(uint_t n_filters, uint_t win_s){
39  /** allocating space for filterbank object */
40  aubio_filterbank_t * fb = AUBIO_NEW(aubio_filterbank_t);
[f918cb9]41  uint_t filter_cnt;
[8708556]42  fb->win_s=win_s;
43  fb->n_filters=n_filters;
[88199ce]44
[8708556]45  /** allocating filter tables */
[b276dee]46  fb->filters=AUBIO_ARRAY(fvec_t*,n_filters);
[8708556]47  for (filter_cnt=0; filter_cnt<n_filters; filter_cnt++)
48    /* considering one-channel filters */
[b276dee]49    fb->filters[filter_cnt]=new_fvec(win_s, 1);
[88199ce]50
[b276dee]51  return fb;
52}
53
[f72ceeb]54aubio_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){
[7a46bf6]55 
[b276dee]56  smpl_t nyquist = samplerate/2.;
57  uint_t style = 1;
58  aubio_filterbank_t * fb = new_aubio_filterbank(n_filters, win_s);
[88199ce]59
[b276dee]60  uint_t n, i, k, *fft_peak, M, next_peak; 
61  smpl_t norm, mel_freq_max, mel_freq_min, norm_fact, height, inc, val, 
62         freq_bw_mel, *mel_peak, *height_norm, *lin_peak;
[88199ce]63
[b276dee]64  mel_peak = height_norm = lin_peak = NULL;
65  fft_peak = NULL;
66  norm = 1; 
[88199ce]67
[b276dee]68  mel_freq_max = 1127 * log(1 + freq_max / 700);
69  mel_freq_min = 1127 * log(1 + freq_min / 700);
70  freq_bw_mel = (mel_freq_max - mel_freq_min) / fb->n_filters;
[88199ce]71
[b276dee]72  mel_peak = (smpl_t *)malloc((fb->n_filters + 2) * sizeof(smpl_t)); 
73  /* +2 for zeros at start and end */
74  lin_peak = (smpl_t *)malloc((fb->n_filters + 2) * sizeof(smpl_t));
75  fft_peak = (uint_t *)malloc((fb->n_filters + 2) * sizeof(uint_t));
76  height_norm = (smpl_t *)malloc(fb->n_filters * sizeof(smpl_t));
[88199ce]77
[b276dee]78  if(mel_peak == NULL || height_norm == NULL || 
79      lin_peak == NULL || fft_peak == NULL)
80    return NULL;
[88199ce]81
[b276dee]82  M = fb->win_s >> 1;
83
84  mel_peak[0] = mel_freq_min;
85  lin_peak[0] = 700 * (exp(mel_peak[0] / 1127) - 1);
86  fft_peak[0] = lin_peak[0] / nyquist * M;
87
88  for (n = 1; n <= fb->n_filters; n++){ 
[88199ce]89    /*roll out peak locations - mel, linear and linear on fft window scale */
[b276dee]90    mel_peak[n] = mel_peak[n - 1] + freq_bw_mel;
91    lin_peak[n] = 700 * (exp(mel_peak[n] / 1127) -1);
92    fft_peak[n] = lin_peak[n] / nyquist * M;
93  }
94
95  for (n = 0; n < fb->n_filters; n++){
96    /*roll out normalised gain of each peak*/
97    if (style == USE_EQUAL_GAIN){
98      height = 1; 
99      norm_fact = norm;
[88199ce]100    }
[b276dee]101    else{
102      height = 2 / (lin_peak[n + 2] - lin_peak[n]);
103      norm_fact = norm / (2 / (lin_peak[2] - lin_peak[0]));
104    }
105    height_norm[n] = height * norm_fact;
106  }
107
108  i = 0;
[88199ce]109
[b276dee]110  for(n = 0; n < fb->n_filters; n++){
111
112    /*calculate the rise increment*/
113    if(n > 0)
114      inc = height_norm[n] / (fft_peak[n] - fft_peak[n - 1]);
115    else
116      inc = height_norm[n] / fft_peak[n];
117    val = 0; 
118
119    /*zero the start of the array*/
120    for(k = 0; k < i; k++)
121      fb->filters[n]->data[0][k]=0.f;
122
123    /*fill in the rise */
124    for(; i <= fft_peak[n]; i++){ 
125      fb->filters[n]->data[0][k]=val;
126      val += inc;
[88199ce]127    }
128
[b276dee]129    /*calculate the fall increment */
130    inc = height_norm[n] / (fft_peak[n + 1] - fft_peak[n]);
131
132    val = 0;
133    next_peak = fft_peak[n + 1];
134
135    /*reverse fill the 'fall' */
136    for(i = next_peak; i > fft_peak[n]; i--){ 
137      fb->filters[n]->data[0][k]=val;
138      val += inc;
139    }
140
141    /*zero the rest of the array*/
142    for(k = next_peak + 1; k < fb->win_s; k++)
143      fb->filters[n]->data[0][k]=0.f;
[7a46bf6]144
[88199ce]145
[b276dee]146  }
147
148  free(mel_peak);
149  free(lin_peak);
150  free(height_norm);
151  free(fft_peak);
152
[7a46bf6]153
[b276dee]154  return fb;
[88199ce]155
[8708556]156}
157
[83d5abf]158/*
159FB initialization based on Slaney's auditory toolbox
160TODO:
161  *solve memory leak problems while
162  *solve quantization issues when constructing signal:
163    *bug for win_s=512
164    *corrections for win_s=1024 -> why even filters with smaller amplitude
165
166*/
[ef1c3b7]167
[f72ceeb]168aubio_filterbank_t * new_aubio_filterbank_mfcc2(uint_t n_filters, uint_t win_s, uint_t samplerate, smpl_t freq_min, smpl_t freq_max){
169 
170  aubio_filterbank_t * fb = new_aubio_filterbank(n_filters, win_s);
171 
[ef1c3b7]172 
173  //slaney params
174  smpl_t lowestFrequency = 133.3333;
175  smpl_t linearSpacing = 66.66666666;
176  smpl_t logSpacing = 1.0711703;
177
178  uint_t linearFilters = 13;
179  uint_t logFilters = 27;
180  uint_t allFilters = linearFilters + logFilters;
[7a46bf6]181 
[ef1c3b7]182  //buffers for computing filter frequencies
[95a64c7]183  fvec_t * freqs=new_fvec(allFilters+2 , 1);
[787f1f3]184 
[ef1c3b7]185  fvec_t * lower_freqs=new_fvec( allFilters, 1);
186  fvec_t * upper_freqs=new_fvec( allFilters, 1);
187  fvec_t * center_freqs=new_fvec( allFilters, 1);
[95a64c7]188
[787f1f3]189 
[ef1c3b7]190  fvec_t * triangle_heights=new_fvec( allFilters, 1);
191  //lookup table of each bin frequency in hz
[f72ceeb]192  fvec_t * fft_freqs=new_fvec(win_s, 1);
[ef1c3b7]193
194  uint_t filter_cnt, bin_cnt;
195 
[95a64c7]196  //first step: filling all the linear filter frequencies
[ef1c3b7]197  for(filter_cnt=0; filter_cnt<linearFilters; filter_cnt++){
[f72ceeb]198    freqs->data[0][filter_cnt]=lowestFrequency+ filter_cnt*linearSpacing;
[ef1c3b7]199  }
[f72ceeb]200  smpl_t lastlinearCF=freqs->data[0][filter_cnt-1];
[ef1c3b7]201 
[95a64c7]202  //second step: filling all the log filter frequencies
[ef1c3b7]203  for(filter_cnt=0; filter_cnt<logFilters+2; filter_cnt++){
[f72ceeb]204    freqs->data[0][filter_cnt+linearFilters]=lastlinearCF*(pow(logSpacing,filter_cnt+1));
[ef1c3b7]205  }
[f72ceeb]206
[95a64c7]207  //Option 1. copying interesting values to lower_freqs, center_freqs and upper freqs arrays
208  //TODO: would be nicer to have a reference to freqs->data, anyway we do not care in this init step
209   
210  for(filter_cnt=0; filter_cnt<allFilters; filter_cnt++){
211    lower_freqs->data[0][filter_cnt]=freqs->data[0][filter_cnt];
212    center_freqs->data[0][filter_cnt]=freqs->data[0][filter_cnt+1];
213    upper_freqs->data[0][filter_cnt]=freqs->data[0][filter_cnt+2];
214  }
215
216
[ef1c3b7]217  //computing triangle heights so that each triangle has unit area
218  for(filter_cnt=0; filter_cnt<allFilters; filter_cnt++){
[f72ceeb]219    triangle_heights->data[0][filter_cnt]=2./(upper_freqs->data[0][filter_cnt]-lower_freqs->data[0][filter_cnt]);
[ef1c3b7]220  }
[95a64c7]221 
222 
[787f1f3]223  //AUBIO_DBG
224  AUBIO_DBG("filter tables frequencies\n");
[f72ceeb]225  for(filter_cnt=0; filter_cnt<allFilters; filter_cnt++)
[787f1f3]226    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]);
[bc4ba75]227
[f72ceeb]228  //filling the fft_freqs lookup table, which assigns the frequency in hz to each bin
[ef1c3b7]229  for(bin_cnt=0; bin_cnt<win_s; bin_cnt++){
230    //TODO: check the formula!
[f72ceeb]231    fft_freqs->data[0][bin_cnt]= (smpl_t)samplerate* (smpl_t)bin_cnt/ (smpl_t)win_s;
[ef1c3b7]232  }
[bc4ba75]233
[f72ceeb]234  //building each filter table
[ef1c3b7]235  for(filter_cnt=0; filter_cnt<allFilters; filter_cnt++){
236
[f72ceeb]237    //TODO:check special case : lower freq =0
238    //calculating rise increment in mag/Hz
239    smpl_t riseInc= triangle_heights->data[0][filter_cnt]/(center_freqs->data[0][filter_cnt]-lower_freqs->data[0][filter_cnt]);
240   
241
[bc4ba75]242    AUBIO_DBG("\nfilter %d",filter_cnt);
243    //zeroing begining of filter
[787f1f3]244    AUBIO_DBG("\nzero begin\n");
[f72ceeb]245    for(bin_cnt=0; bin_cnt<win_s-1; bin_cnt++){
246      //zeroing beigining of array
[ef1c3b7]247      fb->filters[filter_cnt]->data[0][bin_cnt]=0.f;
[787f1f3]248      AUBIO_DBG(".");
249      //AUBIO_DBG("%f %f %f\n", fft_freqs->data[0][bin_cnt], fft_freqs->data[0][bin_cnt+1], lower_freqs->data[0][filter_cnt]);
[f72ceeb]250      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]){
251        break;
252      }
[88199ce]253    }
[f72ceeb]254    bin_cnt++;
255   
[787f1f3]256    AUBIO_DBG("\npos slope\n");
[f72ceeb]257    //positive slope
258    for(; bin_cnt<win_s-1; bin_cnt++){
[787f1f3]259      AUBIO_DBG(".");
[f72ceeb]260      fb->filters[filter_cnt]->data[0][bin_cnt]=(fft_freqs->data[0][bin_cnt]-lower_freqs->data[0][filter_cnt])*riseInc;
261      //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])
262      if(fft_freqs->data[0][bin_cnt+1]> center_freqs->data[0][filter_cnt])
263        break;
[b276dee]264    }
[f72ceeb]265    //bin_cnt++;
266   
[83d5abf]267   
[f72ceeb]268    //negative slope
[787f1f3]269    AUBIO_DBG("\nneg slope\n");   
[f72ceeb]270    for(; bin_cnt<win_s-1; bin_cnt++){
[787f1f3]271      //AUBIO_DBG(".");
[f72ceeb]272     
273      //checking whether last value is less than 0...
274      smpl_t val=triangle_heights->data[0][filter_cnt]-(fft_freqs->data[0][bin_cnt]-center_freqs->data[0][filter_cnt])*riseInc;
275      if(val>=0)
276        fb->filters[filter_cnt]->data[0][bin_cnt]=val;
277      else fb->filters[filter_cnt]->data[0][bin_cnt]=0.f;
278     
279      //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])
280      //TODO: CHECK whether bugfix correct
281      if(fft_freqs->data[0][bin_cnt+1]> upper_freqs->data[0][filter_cnt])
282        break;
[b276dee]283    }
[f72ceeb]284    //bin_cnt++;
285   
[787f1f3]286    AUBIO_DBG("\nzero end\n");
[f72ceeb]287    //zeroing tail
288    for(; bin_cnt<win_s; bin_cnt++)
[787f1f3]289      //AUBIO_DBG(".");
[f72ceeb]290      fb->filters[filter_cnt]->data[0][bin_cnt]=0.f;
[88199ce]291
[b276dee]292  }
[f72ceeb]293 
294 
[95a64c7]295
[f72ceeb]296  del_fvec(freqs);
[95a64c7]297  del_fvec(lower_freqs);
298  del_fvec(upper_freqs);
299  del_fvec(center_freqs);
[b276dee]300
[f72ceeb]301  del_fvec(triangle_heights);
302  del_fvec(fft_freqs);
[b276dee]303
304  return fb;
[88199ce]305
[8708556]306}
307
[ef1c3b7]308void aubio_dump_filterbank(aubio_filterbank_t * fb){
309
310  FILE * mlog;
311  mlog=fopen("filterbank.txt","w");
312 
313  int k,n;
314  //dumping filter values
315  //smpl_t area_tmp=0.f;
316  for(n = 0; n < fb->n_filters; n++){
317    for(k = 0; k < fb->win_s; k++){
318      fprintf(mlog,"%f ",fb->filters[n]->data[0][k]);
319    }
320    fprintf(mlog,"\n");
321  }
322 
323  if(mlog) fclose(mlog);
324}
[b276dee]325
[8708556]326void del_aubio_filterbank(aubio_filterbank_t * fb){
[b276dee]327  uint_t filter_cnt;
[8708556]328  /** deleting filter tables first */
329  for (filter_cnt=0; filter_cnt<fb->n_filters; filter_cnt++)
330    del_fvec(fb->filters[filter_cnt]);
331  AUBIO_FREE(fb->filters);
332  AUBIO_FREE(fb);
333}
[88199ce]334
[b276dee]335void aubio_filterbank_do(aubio_filterbank_t * f, cvec_t * in, fvec_t *out) {
336  uint_t n, filter_cnt;
[f14a78d]337  for(filter_cnt = 0; (filter_cnt < f->n_filters)
338    && (filter_cnt < out->length); filter_cnt++){
[b276dee]339      out->data[0][filter_cnt] = 0.f;
[f14a78d]340      for(n = 0; n < in->length; n++){
[b276dee]341          out->data[0][filter_cnt] += in->norm[0][n] 
342            * f->filters[filter_cnt]->data[0][n];
343      }
344      out->data[0][filter_cnt] =
345        LOG(out->data[0][filter_cnt] < VERY_SMALL_NUMBER ? 
346            VERY_SMALL_NUMBER : out->data[0][filter_cnt]);
347  }
348
349  return;
[fe28ff3]350}
Note: See TracBrowser for help on using the repository browser.