From 3c18f9ee1f7276f0557e2f2ca1255f9955a1268e Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Wed, 7 Oct 2009 23:32:42 +0200 Subject: [PATCH] src/spectral/filterbank_mel.{c,h}: rename _set_mel_coeffs to _set_triangle_bands, add some warnings, setters return uint_t, --- src/spectral/filterbank_mel.c | 51 ++++++++++++++++++++++++++++------- src/spectral/filterbank_mel.h | 10 +++---- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/spectral/filterbank_mel.c b/src/spectral/filterbank_mel.c index 0bd68874..3d0a9531 100644 --- a/src/spectral/filterbank_mel.c +++ b/src/spectral/filterbank_mel.c @@ -25,9 +25,9 @@ #include "spectral/filterbank.h" #include "mathutils.h" -void -aubio_filterbank_set_mel_coeffs (aubio_filterbank_t * fb, fvec_t * freqs, - smpl_t samplerate) +uint_t +aubio_filterbank_set_triangle_bands (aubio_filterbank_t * fb, + smpl_t samplerate, fvec_t * freqs) { fvec_t *filters = aubio_filterbank_get_coeffs (fb); @@ -43,6 +43,16 @@ aubio_filterbank_set_mel_coeffs (aubio_filterbank_t * fb, fvec_t * freqs, n_filters, freqs->length - 2); } + if (freqs->length - 2 < n_filters) { + AUBIO_WRN ("too many filters, %d allocated but %d requested\n", + n_filters, freqs->length - 2); + } + + if (freqs->data[0][freqs->length - 1] > samplerate / 2) { + AUBIO_WRN ("Nyquist frequency is %fHz, but highest frequency band ends at \ +%fHz\n", samplerate / 2, freqs->data[0][freqs->length - 1]); + } + /* convenience reference to lower/center/upper frequency for each triangle */ fvec_t *lower_freqs = new_fvec (n_filters, 1); fvec_t *upper_freqs = new_fvec (n_filters, 1); @@ -69,12 +79,24 @@ aubio_filterbank_set_mel_coeffs (aubio_filterbank_t * fb, fvec_t * freqs, /* fill fft_freqs lookup table, which assigns the frequency in hz to each bin */ for (bin = 0; bin < win_s; bin++) { - fft_freqs->data[0][bin] = aubio_bintofreq (bin, samplerate, (win_s - 1) * 2); + fft_freqs->data[0][bin] = + aubio_bintofreq (bin, samplerate, (win_s - 1) * 2); } /* zeroing of all filters */ fvec_zeros (filters); + if (fft_freqs->data[0][1] >= lower_freqs->data[0][0]) { + /* - 1 to make sure we don't miss the smallest power of two */ + uint_t min_win_s = + (uint_t) FLOOR (samplerate / lower_freqs->data[0][0]) - 1; + AUBIO_WRN ("Lowest frequency bin (%.2fHz) is higher than lowest frequency \ +band (%.2f-%.2fHz). Consider increasing the window size from %d to %d.\n", + fft_freqs->data[0][1], lower_freqs->data[0][0], + upper_freqs->data[0][0], (win_s - 1) * 2, + aubio_next_power_of_two (min_win_s)); + } + /* building each filter table */ for (fn = 0; fn < n_filters; fn++) { @@ -82,10 +104,10 @@ aubio_filterbank_set_mel_coeffs (aubio_filterbank_t * fb, fvec_t * freqs, for (bin = 0; bin < win_s - 1; bin++) { if (fft_freqs->data[0][bin] <= lower_freqs->data[0][fn] && fft_freqs->data[0][bin + 1] > lower_freqs->data[0][fn]) { + bin++; break; } } - bin++; /* compute positive slope step size */ smpl_t riseInc = @@ -97,10 +119,11 @@ aubio_filterbank_set_mel_coeffs (aubio_filterbank_t * fb, fvec_t * freqs, filters->data[fn][bin] = (fft_freqs->data[0][bin] - lower_freqs->data[0][fn]) * riseInc; - if (fft_freqs->data[0][bin + 1] > center_freqs->data[0][fn]) + if (fft_freqs->data[0][bin + 1] >= center_freqs->data[0][fn]) { + bin++; break; + } } - bin++; /* compute negative slope step size */ smpl_t downInc = @@ -112,7 +135,11 @@ aubio_filterbank_set_mel_coeffs (aubio_filterbank_t * fb, fvec_t * freqs, filters->data[fn][bin] += (upper_freqs->data[0][fn] - fft_freqs->data[0][bin]) * downInc; - if (fft_freqs->data[0][bin + 1] > upper_freqs->data[0][fn]) + if (filters->data[fn][bin] < 0.) { + filters->data[fn][bin] = 0.; + } + + if (fft_freqs->data[0][bin + 1] >= upper_freqs->data[0][fn]) break; } /* nothing else to do */ @@ -127,12 +154,15 @@ aubio_filterbank_set_mel_coeffs (aubio_filterbank_t * fb, fvec_t * freqs, del_fvec (triangle_heights); del_fvec (fft_freqs); + return 0; } -void +uint_t aubio_filterbank_set_mel_coeffs_slaney (aubio_filterbank_t * fb, smpl_t samplerate) { + uint_t retval; + /* Malcolm Slaney parameters */ smpl_t lowestFrequency = 133.3333; smpl_t linearSpacing = 66.66666666; @@ -160,9 +190,10 @@ aubio_filterbank_set_mel_coeffs_slaney (aubio_filterbank_t * fb, } /* now compute the actual coefficients */ - aubio_filterbank_set_mel_coeffs (fb, freqs, samplerate); + retval = aubio_filterbank_set_triangle_bands (fb, samplerate, freqs); /* destroy vector used to store frequency limits */ del_fvec (freqs); + return retval; } diff --git a/src/spectral/filterbank_mel.h b/src/spectral/filterbank_mel.h index 9b5d21f6..cb269fb5 100644 --- a/src/spectral/filterbank_mel.h +++ b/src/spectral/filterbank_mel.h @@ -39,18 +39,18 @@ extern "C" { #endif -/** filterbank initialization for mel filters +/** filterbank initialization with triangular and overlapping bands \param fb filterbank object \param freqs arbitrary array of boundary frequencies \param samplerate audio sampling rate This function computes the coefficients of the filterbank based on the - boundaries found in freqs, in Hz, and using triangular overlapping windows. + boundaries found in freqs, in Hz, and using triangular overlapping bands. */ -void aubio_filterbank_set_mel_coeffs (aubio_filterbank_t * fb, - fvec_t * freqs, smpl_t samplerate); +uint_t aubio_filterbank_set_triangle_bands (aubio_filterbank_t * fb, + smpl_t samplerate, fvec_t * freqs); /** filterbank initialization for Mel filters using Slaney's coefficients @@ -60,7 +60,7 @@ void aubio_filterbank_set_mel_coeffs (aubio_filterbank_t * fb, This function fills the filterbank coefficients according to Malcolm Slaney. */ -void aubio_filterbank_set_mel_coeffs_slaney (aubio_filterbank_t * fb, +uint_t aubio_filterbank_set_mel_coeffs_slaney (aubio_filterbank_t * fb, smpl_t samplerate); #ifdef __cplusplus -- 2.26.2