source: src/spectral/filterbank_mel.c @ 3c18f9e

feature/autosinkfeature/constantqfeature/pitchshiftfeature/pydocstringsfeature/timestretchpitchshiftsamplertimestretchyinfft+
Last change on this file since 3c18f9e was 3c18f9e, checked in by Paul Brossier <piem@piem.org>, 11 years ago

src/spectral/filterbank_mel.{c,h}: rename _set_mel_coeffs to _set_triangle_bands, add some warnings, setters return uint_t,

  • Property mode set to 100644
File size: 6.1 KB
Line 
1/*
2  Copyright (C) 2007-2009 Paul Brossier <piem@aubio.org>
3                      and Amaury Hazan <ahazan@iua.upf.edu>
4
5  This file is part of aubio.
6
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.
11
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.
16
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/>.
19
20*/
21
22#include "aubio_priv.h"
23#include "fvec.h"
24#include "cvec.h"
25#include "spectral/filterbank.h"
26#include "mathutils.h"
27
28uint_t
29aubio_filterbank_set_triangle_bands (aubio_filterbank_t * fb,
30    smpl_t samplerate, fvec_t * freqs)
31{
32
33  fvec_t *filters = aubio_filterbank_get_coeffs (fb);
34  uint_t n_filters = filters->channels, win_s = filters->length;
35
36  uint_t fn;                    /* filter counter */
37  uint_t bin;                   /* bin counter */
38
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);
44  }
45
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);
49  }
50
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]);
54  }
55
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);
60
61  /* height of each triangle */
62  fvec_t *triangle_heights = new_fvec (n_filters, 1);
63
64  /* lookup table of each bin frequency in hz */
65  fvec_t *fft_freqs = new_fvec (win_s, 1);
66
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];
72  }
73
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]);
78  }
79
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);
84  }
85
86  /* zeroing of all filters */
87  fvec_zeros (filters);
88
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 */
91    uint_t min_win_s =
92        (uint_t) FLOOR (samplerate / lower_freqs->data[0][0]) - 1;
93    AUBIO_WRN ("Lowest frequency bin (%.2fHz) is higher than lowest frequency \
94band (%.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));
98  }
99
100  /* building each filter table */
101  for (fn = 0; fn < n_filters; fn++) {
102
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]) {
107        bin++;
108        break;
109      }
110    }
111
112    /* compute positive slope step size */
113    smpl_t riseInc =
114        triangle_heights->data[0][fn] /
115        (center_freqs->data[0][fn] - lower_freqs->data[0][fn]);
116
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;
121
122      if (fft_freqs->data[0][bin + 1] >= center_freqs->data[0][fn]) {
123        bin++;
124        break;
125      }
126    }
127
128    /* compute negative slope step size */
129    smpl_t downInc =
130        triangle_heights->data[0][fn] /
131        (upper_freqs->data[0][fn] - center_freqs->data[0][fn]);
132
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;
137
138      if (filters->data[fn][bin] < 0.) {
139        filters->data[fn][bin] = 0.;
140      }
141
142      if (fft_freqs->data[0][bin + 1] >= upper_freqs->data[0][fn])
143        break;
144    }
145    /* nothing else to do */
146
147  }
148
149  /* destroy temporarly allocated vectors */
150  del_fvec (lower_freqs);
151  del_fvec (upper_freqs);
152  del_fvec (center_freqs);
153
154  del_fvec (triangle_heights);
155  del_fvec (fft_freqs);
156
157  return 0;
158}
159
160uint_t
161aubio_filterbank_set_mel_coeffs_slaney (aubio_filterbank_t * fb,
162    smpl_t samplerate)
163{
164  uint_t retval;
165
166  /* Malcolm Slaney parameters */
167  smpl_t lowestFrequency = 133.3333;
168  smpl_t linearSpacing = 66.66666666;
169  smpl_t logSpacing = 1.0711703;
170
171  uint_t linearFilters = 13;
172  uint_t logFilters = 27;
173  uint_t n_filters = linearFilters + logFilters;
174
175  uint_t fn;                    /* filter counter */
176
177  /* buffers to compute filter frequencies */
178  fvec_t *freqs = new_fvec (n_filters + 2, 1);
179
180  /* first step: fill all the linear filter frequencies */
181  for (fn = 0; fn < linearFilters; fn++) {
182    freqs->data[0][fn] = lowestFrequency + fn * linearSpacing;
183  }
184  smpl_t lastlinearCF = freqs->data[0][fn - 1];
185
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));
190  }
191
192  /* now compute the actual coefficients */
193  retval = aubio_filterbank_set_triangle_bands (fb, samplerate, freqs);
194
195  /* destroy vector used to store frequency limits */
196  del_fvec (freqs);
197
198  return retval;
199}
Note: See TracBrowser for help on using the repository browser.