[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 | /* part of this mfcc implementation were inspired from LibXtract |
---|
| 22 | http://libxtract.sourceforge.net/ |
---|
| 23 | */ |
---|
| 24 | |
---|
[7c6c806d] | 25 | #include "aubio_priv.h" |
---|
[b276dee] | 26 | #include "sample.h" |
---|
[71d3bf0] | 27 | #include "filterbank.h" |
---|
[88199ce] | 28 | |
---|
[b276dee] | 29 | #define USE_EQUAL_GAIN 1 |
---|
| 30 | #define VERY_SMALL_NUMBER 2e-42 |
---|
| 31 | |
---|
[8708556] | 32 | /** \brief A structure to store a set of n_filters filters of lenghts win_s */ |
---|
| 33 | struct aubio_filterbank_t_ { |
---|
| 34 | uint_t win_s; |
---|
| 35 | uint_t n_filters; |
---|
[b276dee] | 36 | fvec_t **filters; |
---|
[7c6c806d] | 37 | }; |
---|
| 38 | |
---|
[8708556] | 39 | aubio_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); |
---|
[f918cb9] | 42 | uint_t filter_cnt; |
---|
[8708556] | 43 | fb->win_s=win_s; |
---|
| 44 | fb->n_filters=n_filters; |
---|
| 45 | |
---|
| 46 | /** allocating filter tables */ |
---|
[b276dee] | 47 | fb->filters=AUBIO_ARRAY(fvec_t*,n_filters); |
---|
[8708556] | 48 | for (filter_cnt=0; filter_cnt<n_filters; filter_cnt++) |
---|
| 49 | /* considering one-channel filters */ |
---|
[b276dee] | 50 | fb->filters[filter_cnt]=new_fvec(win_s, 1); |
---|
| 51 | |
---|
| 52 | return fb; |
---|
| 53 | } |
---|
| 54 | |
---|
| 55 | 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){ |
---|
| 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; |
---|
[8708556] | 157 | |
---|
| 158 | } |
---|
| 159 | |
---|
[b276dee] | 160 | |
---|
[8708556] | 161 | void del_aubio_filterbank(aubio_filterbank_t * fb){ |
---|
[b276dee] | 162 | uint_t filter_cnt; |
---|
[8708556] | 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 | |
---|
[b276dee] | 170 | void aubio_filterbank_do(aubio_filterbank_t * f, cvec_t * in, fvec_t *out) { |
---|
| 171 | uint_t n, filter_cnt; |
---|
[f14a78d] | 172 | for(filter_cnt = 0; (filter_cnt < f->n_filters) |
---|
| 173 | && (filter_cnt < out->length); filter_cnt++){ |
---|
[b276dee] | 174 | out->data[0][filter_cnt] = 0.f; |
---|
[f14a78d] | 175 | for(n = 0; n < in->length; n++){ |
---|
[b276dee] | 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 | } |
---|