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_triangle_bands (aubio_filterbank_t * fb,
30 smpl_t samplerate, fvec_t * freqs)
33 fvec_t *filters = aubio_filterbank_get_coeffs (fb);
34 uint_t n_filters = filters->channels, win_s = filters->length;
36 uint_t fn; /* filter counter */
37 uint_t bin; /* bin counter */
39 /* freqs define the bands of triangular overlapping windows.
40 throw a warning if filterbank object fb is too short. */
41 if (freqs->length - 2 > n_filters) {
42 AUBIO_WRN ("not enough filters, %d allocated but %d requested\n",
43 n_filters, freqs->length - 2);
46 if (freqs->length - 2 < n_filters) {
47 AUBIO_WRN ("too many filters, %d allocated but %d requested\n",
48 n_filters, freqs->length - 2);
51 if (freqs->data[0][freqs->length - 1] > samplerate / 2) {
52 AUBIO_WRN ("Nyquist frequency is %fHz, but highest frequency band ends at \
53 %fHz\n", samplerate / 2, freqs->data[0][freqs->length - 1]);
56 /* convenience reference to lower/center/upper frequency for each triangle */
57 fvec_t *lower_freqs = new_fvec (n_filters, 1);
58 fvec_t *upper_freqs = new_fvec (n_filters, 1);
59 fvec_t *center_freqs = new_fvec (n_filters, 1);
61 /* height of each triangle */
62 fvec_t *triangle_heights = new_fvec (n_filters, 1);
64 /* lookup table of each bin frequency in hz */
65 fvec_t *fft_freqs = new_fvec (win_s, 1);
67 /* fill up the lower/center/upper */
68 for (fn = 0; fn < n_filters; fn++) {
69 lower_freqs->data[0][fn] = freqs->data[0][fn];
70 center_freqs->data[0][fn] = freqs->data[0][fn + 1];
71 upper_freqs->data[0][fn] = freqs->data[0][fn + 2];
74 /* compute triangle heights so that each triangle has unit area */
75 for (fn = 0; fn < n_filters; fn++) {
76 triangle_heights->data[0][fn] =
77 2. / (upper_freqs->data[0][fn] - lower_freqs->data[0][fn]);
80 /* fill fft_freqs lookup table, which assigns the frequency in hz to each bin */
81 for (bin = 0; bin < win_s; bin++) {
82 fft_freqs->data[0][bin] =
83 aubio_bintofreq (bin, samplerate, (win_s - 1) * 2);
86 /* zeroing of all filters */
89 if (fft_freqs->data[0][1] >= lower_freqs->data[0][0]) {
90 /* - 1 to make sure we don't miss the smallest power of two */
92 (uint_t) FLOOR (samplerate / lower_freqs->data[0][0]) - 1;
93 AUBIO_WRN ("Lowest frequency bin (%.2fHz) is higher than lowest frequency \
94 band (%.2f-%.2fHz). Consider increasing the window size from %d to %d.\n",
95 fft_freqs->data[0][1], lower_freqs->data[0][0],
96 upper_freqs->data[0][0], (win_s - 1) * 2,
97 aubio_next_power_of_two (min_win_s));
100 /* building each filter table */
101 for (fn = 0; fn < n_filters; fn++) {
103 /* skip first elements */
104 for (bin = 0; bin < win_s - 1; bin++) {
105 if (fft_freqs->data[0][bin] <= lower_freqs->data[0][fn] &&
106 fft_freqs->data[0][bin + 1] > lower_freqs->data[0][fn]) {
112 /* compute positive slope step size */
114 triangle_heights->data[0][fn] /
115 (center_freqs->data[0][fn] - lower_freqs->data[0][fn]);
117 /* compute coefficients in positive slope */
118 for (; bin < win_s - 1; bin++) {
119 filters->data[fn][bin] =
120 (fft_freqs->data[0][bin] - lower_freqs->data[0][fn]) * riseInc;
122 if (fft_freqs->data[0][bin + 1] >= center_freqs->data[0][fn]) {
128 /* compute negative slope step size */
130 triangle_heights->data[0][fn] /
131 (upper_freqs->data[0][fn] - center_freqs->data[0][fn]);
133 /* compute coefficents in negative slope */
134 for (; bin < win_s - 1; bin++) {
135 filters->data[fn][bin] +=
136 (upper_freqs->data[0][fn] - fft_freqs->data[0][bin]) * downInc;
138 if (filters->data[fn][bin] < 0.) {
139 filters->data[fn][bin] = 0.;
142 if (fft_freqs->data[0][bin + 1] >= upper_freqs->data[0][fn])
145 /* nothing else to do */
149 /* destroy temporarly allocated vectors */
150 del_fvec (lower_freqs);
151 del_fvec (upper_freqs);
152 del_fvec (center_freqs);
154 del_fvec (triangle_heights);
155 del_fvec (fft_freqs);
161 aubio_filterbank_set_mel_coeffs_slaney (aubio_filterbank_t * fb,
166 /* Malcolm Slaney parameters */
167 smpl_t lowestFrequency = 133.3333;
168 smpl_t linearSpacing = 66.66666666;
169 smpl_t logSpacing = 1.0711703;
171 uint_t linearFilters = 13;
172 uint_t logFilters = 27;
173 uint_t n_filters = linearFilters + logFilters;
175 uint_t fn; /* filter counter */
177 /* buffers to compute filter frequencies */
178 fvec_t *freqs = new_fvec (n_filters + 2, 1);
180 /* first step: fill all the linear filter frequencies */
181 for (fn = 0; fn < linearFilters; fn++) {
182 freqs->data[0][fn] = lowestFrequency + fn * linearSpacing;
184 smpl_t lastlinearCF = freqs->data[0][fn - 1];
186 /* second step: fill all the log filter frequencies */
187 for (fn = 0; fn < logFilters + 2; fn++) {
188 freqs->data[0][fn + linearFilters] =
189 lastlinearCF * (POW (logSpacing, fn + 1));
192 /* now compute the actual coefficients */
193 retval = aubio_filterbank_set_triangle_bands (fb, samplerate, freqs);
195 /* destroy vector used to store frequency limits */