source: src/filterbank.c @ e5f6a0b

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

added mfcc binding

  • Property mode set to 100644
File size: 10.7 KB
Line 
1/*
2   Copyright (C) 2007 Amaury Hazan <ahazan@iua.upf.edu>
3                  and Paul Brossier <piem@piem.org>
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
21
22#include "aubio_priv.h"
23#include "sample.h"
24#include "filterbank.h"
25
26#include "stdio.h"
27
28#define USE_EQUAL_GAIN 1
29#define VERY_SMALL_NUMBER 2e-42
30
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;
35    fvec_t **filters;
36};
37
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);
41  uint_t filter_cnt;
42  fb->win_s=win_s;
43  fb->n_filters=n_filters;
44
45  /** allocating filter tables */
46  fb->filters=AUBIO_ARRAY(fvec_t*,n_filters);
47  for (filter_cnt=0; filter_cnt<n_filters; filter_cnt++)
48    /* considering one-channel filters */
49    fb->filters[filter_cnt]=new_fvec(win_s, 1);
50
51  return fb;
52}
53
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){
55 
56  smpl_t nyquist = samplerate/2.;
57  uint_t style = 1;
58  aubio_filterbank_t * fb = new_aubio_filterbank(n_filters, win_s);
59
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;
63
64  mel_peak = height_norm = lin_peak = NULL;
65  fft_peak = NULL;
66  norm = 1; 
67
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;
71
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));
77
78  if(mel_peak == NULL || height_norm == NULL || 
79      lin_peak == NULL || fft_peak == NULL)
80    return NULL;
81
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++){ 
89    /*roll out peak locations - mel, linear and linear on fft window scale */
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;
100    }
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;
109
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;
127    }
128
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;
144
145
146  }
147
148  free(mel_peak);
149  free(lin_peak);
150  free(height_norm);
151  free(fft_peak);
152
153
154  return fb;
155
156}
157
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*/
167
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 
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;
181 
182  //buffers for computing filter frequencies
183  fvec_t * freqs=new_fvec(allFilters+2 , 1);
184 
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);
188
189 
190  fvec_t * triangle_heights=new_fvec( allFilters, 1);
191  //lookup table of each bin frequency in hz
192  fvec_t * fft_freqs=new_fvec(win_s, 1);
193
194  uint_t filter_cnt, bin_cnt;
195 
196  //first step: filling all the linear filter frequencies
197  for(filter_cnt=0; filter_cnt<linearFilters; filter_cnt++){
198    freqs->data[0][filter_cnt]=lowestFrequency+ filter_cnt*linearSpacing;
199  }
200  smpl_t lastlinearCF=freqs->data[0][filter_cnt-1];
201 
202  //second step: filling all the log filter frequencies
203  for(filter_cnt=0; filter_cnt<logFilters+2; filter_cnt++){
204    freqs->data[0][filter_cnt+linearFilters]=lastlinearCF*(pow(logSpacing,filter_cnt+1));
205  }
206
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
217  //computing triangle heights so that each triangle has unit area
218  for(filter_cnt=0; filter_cnt<allFilters; filter_cnt++){
219    triangle_heights->data[0][filter_cnt]=2./(upper_freqs->data[0][filter_cnt]-lower_freqs->data[0][filter_cnt]);
220  }
221 
222 
223  //AUBIO_DBG
224  AUBIO_DBG("filter tables frequencies\n");
225  for(filter_cnt=0; filter_cnt<allFilters; filter_cnt++)
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]);
227
228  //filling the fft_freqs lookup table, which assigns the frequency in hz to each bin
229  for(bin_cnt=0; bin_cnt<win_s; bin_cnt++){
230    //TODO: check the formula!
231    fft_freqs->data[0][bin_cnt]= (smpl_t)samplerate* (smpl_t)bin_cnt/ (smpl_t)win_s;
232  }
233
234  //building each filter table
235  for(filter_cnt=0; filter_cnt<allFilters; filter_cnt++){
236
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
242    AUBIO_DBG("\nfilter %d",filter_cnt);
243    //zeroing begining of filter
244    AUBIO_DBG("\nzero begin\n");
245    for(bin_cnt=0; bin_cnt<win_s-1; bin_cnt++){
246      //zeroing beigining of array
247      fb->filters[filter_cnt]->data[0][bin_cnt]=0.f;
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]);
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      }
253    }
254    bin_cnt++;
255   
256    AUBIO_DBG("\npos slope\n");
257    //positive slope
258    for(; bin_cnt<win_s-1; bin_cnt++){
259      AUBIO_DBG(".");
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;
264    }
265    //bin_cnt++;
266   
267   
268    //negative slope
269    AUBIO_DBG("\nneg slope\n");   
270    for(; bin_cnt<win_s-1; bin_cnt++){
271      //AUBIO_DBG(".");
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;
283    }
284    //bin_cnt++;
285   
286    AUBIO_DBG("\nzero end\n");
287    //zeroing tail
288    for(; bin_cnt<win_s; bin_cnt++)
289      //AUBIO_DBG(".");
290      fb->filters[filter_cnt]->data[0][bin_cnt]=0.f;
291
292  }
293 
294 
295
296  del_fvec(freqs);
297  del_fvec(lower_freqs);
298  del_fvec(upper_freqs);
299  del_fvec(center_freqs);
300
301  del_fvec(triangle_heights);
302  del_fvec(fft_freqs);
303
304  return fb;
305
306}
307
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}
325
326void del_aubio_filterbank(aubio_filterbank_t * fb){
327  uint_t filter_cnt;
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}
334
335void aubio_filterbank_do(aubio_filterbank_t * f, cvec_t * in, fvec_t *out) {
336  uint_t n, filter_cnt;
337  for(filter_cnt = 0; (filter_cnt < f->n_filters)
338    && (filter_cnt < out->length); filter_cnt++){
339      out->data[0][filter_cnt] = 0.f;
340      for(n = 0; n < in->length; n++){
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;
350}
Note: See TracBrowser for help on using the repository browser.