2 Copyright (C) 2007-2009 Paul Brossier <piem@aubio.org>
3 and Amaury Hazan <ahazan@iua.upf.edu>
5 This file is part of Aubio.
7 Aubio is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Aubio is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Aubio. If not, see <http://www.gnu.org/licenses/>.
22 #include "aubio_priv.h"
25 #include "spectral/filterbank.h"
26 #include "mathutils.h"
29 aubio_filterbank_set_mel_coeffs (aubio_filterbank_t * fb, smpl_t samplerate,
30 smpl_t freq_min, smpl_t freq_max)
33 fvec_t *filters = aubio_filterbank_get_coeffs (fb);
34 uint_t n_filters = filters->channels, win_s = filters->length;
37 smpl_t lowestFrequency = 133.3333;
38 smpl_t linearSpacing = 66.66666666;
39 smpl_t logSpacing = 1.0711703;
41 uint_t linearFilters = 13;
42 uint_t logFilters = 27;
43 uint_t allFilters = linearFilters + logFilters;
45 if (allFilters > n_filters) {
46 AUBIO_WRN("not enough Mel filters, got %d but %d needed\n",
47 n_filters, allFilters);
50 //buffers for computing filter frequencies
51 fvec_t *freqs = new_fvec (allFilters + 2, 1);
53 fvec_t *lower_freqs = new_fvec (allFilters, 1);
54 fvec_t *upper_freqs = new_fvec (allFilters, 1);
55 fvec_t *center_freqs = new_fvec (allFilters, 1);
57 fvec_t *triangle_heights = new_fvec (allFilters, 1);
58 //lookup table of each bin frequency in hz
59 fvec_t *fft_freqs = new_fvec (win_s, 1);
61 uint_t filter_cnt, bin_cnt;
63 //first step: filling all the linear filter frequencies
64 for (filter_cnt = 0; filter_cnt < linearFilters; filter_cnt++) {
65 freqs->data[0][filter_cnt] = lowestFrequency + filter_cnt * linearSpacing;
67 smpl_t lastlinearCF = freqs->data[0][filter_cnt - 1];
69 //second step: filling all the log filter frequencies
70 for (filter_cnt = 0; filter_cnt < logFilters + 2; filter_cnt++) {
71 freqs->data[0][filter_cnt + linearFilters] =
72 lastlinearCF * (POW(logSpacing, filter_cnt + 1));
75 //Option 1. copying interesting values to lower_freqs, center_freqs and upper freqs arrays
76 //TODO: would be nicer to have a reference to freqs->data, anyway we do not care in this init step
78 for (filter_cnt = 0; filter_cnt < allFilters; filter_cnt++) {
79 lower_freqs->data[0][filter_cnt] = freqs->data[0][filter_cnt];
80 center_freqs->data[0][filter_cnt] = freqs->data[0][filter_cnt + 1];
81 upper_freqs->data[0][filter_cnt] = freqs->data[0][filter_cnt + 2];
84 //computing triangle heights so that each triangle has unit area
85 for (filter_cnt = 0; filter_cnt < allFilters; filter_cnt++) {
86 triangle_heights->data[0][filter_cnt] =
87 2. / (upper_freqs->data[0][filter_cnt]
88 - lower_freqs->data[0][filter_cnt]);
91 //filling the fft_freqs lookup table, which assigns the frequency in hz to each bin
92 for (bin_cnt = 0; bin_cnt < win_s; bin_cnt++) {
93 fft_freqs->data[0][bin_cnt] = aubio_bintofreq (bin_cnt, samplerate, win_s);
97 /* zeroing begining of filter */
100 /* building each filter table */
101 for (filter_cnt = 0; filter_cnt < n_filters; filter_cnt++) {
103 /* skip first elements */
104 for (bin_cnt = 0; bin_cnt < win_s - 1; bin_cnt++) {
105 if (fft_freqs->data[0][bin_cnt] <= lower_freqs->data[0][filter_cnt] &&
106 fft_freqs->data[0][bin_cnt + 1] > lower_freqs->data[0][filter_cnt]) {
112 /* compute positive slope step size */
114 triangle_heights->data[0][filter_cnt] /
115 (center_freqs->data[0][filter_cnt] - lower_freqs->data[0][filter_cnt]);
117 /* compute coefficients in positive slope */
118 for (; bin_cnt < win_s - 1; bin_cnt++) {
119 filters->data[filter_cnt][bin_cnt] =
120 (fft_freqs->data[0][bin_cnt] -
121 lower_freqs->data[0][filter_cnt]) * riseInc;
123 if (fft_freqs->data[0][bin_cnt + 1] > center_freqs->data[0][filter_cnt])
128 /* compute negative slope step size */
130 triangle_heights->data[0][filter_cnt] /
131 (upper_freqs->data[0][filter_cnt] - center_freqs->data[0][filter_cnt]);
133 /* compute coefficents in negative slope */
134 for (; bin_cnt < win_s - 1; bin_cnt++) {
135 filters->data[filter_cnt][bin_cnt] +=
136 (upper_freqs->data[0][filter_cnt] -
137 fft_freqs->data[0][bin_cnt]) * downInc;
139 if (fft_freqs->data[0][bin_cnt + 1] > upper_freqs->data[0][filter_cnt])
142 /* nothing else to do */
146 /* destroy temporarly allocated vectors */
148 del_fvec (lower_freqs);
149 del_fvec (upper_freqs);
150 del_fvec (center_freqs);
152 del_fvec (triangle_heights);
153 del_fvec (fft_freqs);