ref: fdf39bad6a0efebca0fe1dba5f44861e89df20bd
dir: /src/filterbank.c/
/* Copyright (C) 2007 Amaury Hazan Ported to aubio from LibXtract http://libxtract.sourceforge.net/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "aubio_priv.h" #include "filterbank.h" // Struct Declaration /** \brief A structure to store a set of n_filters Mel filters */ typedef struct aubio_mel_filter_ { int n_filters; smpl_t **filters; }; // Initialization int aubio_mfcc_init(int N, smpl_t nyquist, int style, smpl_t freq_min, smpl_t freq_max, int freq_bands, smpl_t **fft_tables){ int n, i, k, *fft_peak, M, next_peak; smpl_t norm, mel_freq_max, mel_freq_min, norm_fact, height, inc, val, freq_bw_mel, *mel_peak, *height_norm, *lin_peak; mel_peak = height_norm = lin_peak = NULL; fft_peak = NULL; norm = 1; mel_freq_max = 1127 * log(1 + freq_max / 700); mel_freq_min = 1127 * log(1 + freq_min / 700); freq_bw_mel = (mel_freq_max - mel_freq_min) / freq_bands; mel_peak = (smpl_t *)malloc((freq_bands + 2) * sizeof(smpl_t)); /* +2 for zeros at start and end */ lin_peak = (smpl_t *)malloc((freq_bands + 2) * sizeof(smpl_t)); fft_peak = (int *)malloc((freq_bands + 2) * sizeof(int)); height_norm = (smpl_t *)malloc(freq_bands * sizeof(smpl_t)); if(mel_peak == NULL || height_norm == NULL || lin_peak == NULL || fft_peak == NULL) return XTRACT_MALLOC_FAILED; M = N >> 1; mel_peak[0] = mel_freq_min; lin_peak[0] = 700 * (exp(mel_peak[0] / 1127) - 1); fft_peak[0] = lin_peak[0] / nyquist * M; for (n = 1; n <= freq_bands; n++){ /*roll out peak locations - mel, linear and linear on fft window scale */ mel_peak[n] = mel_peak[n - 1] + freq_bw_mel; lin_peak[n] = 700 * (exp(mel_peak[n] / 1127) -1); fft_peak[n] = lin_peak[n] / nyquist * M; } for (n = 0; n < freq_bands; n++){ /*roll out normalised gain of each peak*/ if (style == XTRACT_EQUAL_GAIN){ height = 1; norm_fact = norm; } else{ height = 2 / (lin_peak[n + 2] - lin_peak[n]); norm_fact = norm / (2 / (lin_peak[2] - lin_peak[0])); } height_norm[n] = height * norm_fact; } i = 0; for(n = 0; n < freq_bands; n++){ /*calculate the rise increment*/ if(n > 0) inc = height_norm[n] / (fft_peak[n] - fft_peak[n - 1]); else inc = height_norm[n] / fft_peak[n]; val = 0; /*zero the start of the array*/ for(k = 0; k < i; k++) fft_tables[n][k] = 0.f; /*fill in the rise */ for(; i <= fft_peak[n]; i++){ fft_tables[n][i] = val; val += inc; } /*calculate the fall increment */ inc = height_norm[n] / (fft_peak[n + 1] - fft_peak[n]); val = 0; next_peak = fft_peak[n + 1]; /*reverse fill the 'fall' */ for(i = next_peak; i > fft_peak[n]; i--){ fft_tables[n][i] = val; val += inc; } /*zero the rest of the array*/ for(k = next_peak + 1; k < N; k++) fft_tables[n][k] = 0.f; } free(mel_peak); free(lin_peak); free(height_norm); free(fft_peak); return XTRACT_SUCCESS; }