source: src/filterbank.c @ 38837b1

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since 38837b1 was f14a78d, checked in by Paul Brossier <piem@piem.org>, 17 years ago

filterbank.c: make sure we never write out of input/output vectors in aubio_filterbank_do

  • Property mode set to 100644
File size: 5.4 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/* part of this mfcc implementation were inspired from LibXtract
22   http://libxtract.sourceforge.net/
23*/
24
25#include "aubio_priv.h"
26#include "sample.h"
27#include "filterbank.h"
28
29#define USE_EQUAL_GAIN 1
30#define VERY_SMALL_NUMBER 2e-42
31
32/** \brief A structure to store a set of n_filters filters of lenghts win_s */
33struct aubio_filterbank_t_ {
34    uint_t win_s;
35    uint_t n_filters;
36    fvec_t **filters;
37};
38
39aubio_filterbank_t * new_aubio_filterbank(uint_t n_filters, uint_t win_s){
40  /** allocating space for filterbank object */
41  aubio_filterbank_t * fb = AUBIO_NEW(aubio_filterbank_t);
42  uint_t filter_cnt;
43  fb->win_s=win_s;
44  fb->n_filters=n_filters;
45
46  /** allocating filter tables */
47  fb->filters=AUBIO_ARRAY(fvec_t*,n_filters);
48  for (filter_cnt=0; filter_cnt<n_filters; filter_cnt++)
49    /* considering one-channel filters */
50    fb->filters[filter_cnt]=new_fvec(win_s, 1);
51
52  return fb;
53}
54
55aubio_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){
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
89  for (n = 1; n <= fb->n_filters; n++){ 
90    /*roll out peak locations - mel, linear and linear on fft window scale */
91    mel_peak[n] = mel_peak[n - 1] + freq_bw_mel;
92    lin_peak[n] = 700 * (exp(mel_peak[n] / 1127) -1);
93    fft_peak[n] = lin_peak[n] / nyquist * M;
94  }
95
96  for (n = 0; n < fb->n_filters; n++){
97    /*roll out normalised gain of each peak*/
98    if (style == USE_EQUAL_GAIN){
99      height = 1; 
100      norm_fact = norm;
101    }
102    else{
103      height = 2 / (lin_peak[n + 2] - lin_peak[n]);
104      norm_fact = norm / (2 / (lin_peak[2] - lin_peak[0]));
105    }
106    height_norm[n] = height * norm_fact;
107  }
108
109  i = 0;
110
111  for(n = 0; n < fb->n_filters; n++){
112
113    /*calculate the rise increment*/
114    if(n > 0)
115      inc = height_norm[n] / (fft_peak[n] - fft_peak[n - 1]);
116    else
117      inc = height_norm[n] / fft_peak[n];
118    val = 0; 
119
120    /*zero the start of the array*/
121    for(k = 0; k < i; k++)
122      //fft_tables[n][k] = 0.f;
123      fb->filters[n]->data[0][k]=0.f;
124
125    /*fill in the rise */
126    for(; i <= fft_peak[n]; i++){ 
127      // fft_tables[n][i] = val;
128      fb->filters[n]->data[0][k]=val;
129      val += inc;
130    }
131
132    /*calculate the fall increment */
133    inc = height_norm[n] / (fft_peak[n + 1] - fft_peak[n]);
134
135    val = 0;
136    next_peak = fft_peak[n + 1];
137
138    /*reverse fill the 'fall' */
139    for(i = next_peak; i > fft_peak[n]; i--){ 
140      //fft_tables[n][i] = val;
141      fb->filters[n]->data[0][k]=val;
142      val += inc;
143    }
144
145    /*zero the rest of the array*/
146    for(k = next_peak + 1; k < fb->win_s; k++)
147      //fft_tables[n][k] = 0.f;
148      fb->filters[n]->data[0][k]=0.f;
149  }
150
151  free(mel_peak);
152  free(lin_peak);
153  free(height_norm);
154  free(fft_peak);
155
156  return fb;
157
158}
159
160
161void del_aubio_filterbank(aubio_filterbank_t * fb){
162  uint_t filter_cnt;
163  /** deleting filter tables first */
164  for (filter_cnt=0; filter_cnt<fb->n_filters; filter_cnt++)
165    del_fvec(fb->filters[filter_cnt]);
166  AUBIO_FREE(fb->filters);
167  AUBIO_FREE(fb);
168}
169
170void aubio_filterbank_do(aubio_filterbank_t * f, cvec_t * in, fvec_t *out) {
171  uint_t n, filter_cnt;
172  for(filter_cnt = 0; (filter_cnt < f->n_filters)
173    && (filter_cnt < out->length); filter_cnt++){
174      out->data[0][filter_cnt] = 0.f;
175      for(n = 0; n < in->length; n++){
176          out->data[0][filter_cnt] += in->norm[0][n] 
177            * f->filters[filter_cnt]->data[0][n];
178      }
179      out->data[0][filter_cnt] =
180        LOG(out->data[0][filter_cnt] < VERY_SMALL_NUMBER ? 
181            VERY_SMALL_NUMBER : out->data[0][filter_cnt]);
182  }
183
184  return;
185}
Note: See TracBrowser for help on using the repository browser.