1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2005 Nicolas Chetry, copyright 2008 QMUL.
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
21 #include "dsp/transforms/FFT.h"
22 #include "base/Window.h"
24 MFCC::MFCC(MFCCConfig config)
28 /* Calculate at startup */
29 double *freqs, *lower, *center, *upper, *triangleHeight, *fftFreqs;
31 lowestFrequency = 66.6666666;
33 linearSpacing = 66.66666666;
35 logSpacing = 1.0711703;
37 /* FFT and analysis window sizes */
38 fftSize = config.fftsize;
39 fft = new FFTReal(fftSize);
41 totalFilters = linearFilters + logFilters;
42 logPower = config.logpower;
44 samplingRate = config.FS;
46 /* The number of cepstral componenents */
49 /* Set if user want C0 */
50 WANT_C0 = (config.want_c0 ? 1 : 0);
52 /* Allocate space for feature vector */
54 ceps = (double*)calloc(nceps+1, sizeof(double));
56 ceps = (double*)calloc(nceps, sizeof(double));
59 /* Allocate space for local vectors */
60 mfccDCTMatrix = (double**)calloc(nceps+1, sizeof(double*));
61 for (i = 0; i < nceps+1; i++) {
62 mfccDCTMatrix[i]= (double*)calloc(totalFilters, sizeof(double));
65 mfccFilterWeights = (double**)calloc(totalFilters, sizeof(double*));
66 for (i = 0; i < totalFilters; i++) {
67 mfccFilterWeights[i] = (double*)calloc(fftSize, sizeof(double));
70 freqs = (double*)calloc(totalFilters+2,sizeof(double));
72 lower = (double*)calloc(totalFilters,sizeof(double));
73 center = (double*)calloc(totalFilters,sizeof(double));
74 upper = (double*)calloc(totalFilters,sizeof(double));
76 triangleHeight = (double*)calloc(totalFilters,sizeof(double));
77 fftFreqs = (double*)calloc(fftSize,sizeof(double));
79 for (i = 0; i < linearFilters; i++) {
80 freqs[i] = lowestFrequency + ((double)i) * linearSpacing;
83 for (i = linearFilters; i < totalFilters+2; i++) {
84 freqs[i] = freqs[linearFilters-1] *
85 pow(logSpacing, (double)(i-linearFilters+1));
88 /* Define lower, center and upper */
89 memcpy(lower, freqs,totalFilters*sizeof(double));
90 memcpy(center, &freqs[1],totalFilters*sizeof(double));
91 memcpy(upper, &freqs[2],totalFilters*sizeof(double));
93 for (i=0;i<totalFilters;i++){
94 triangleHeight[i] = 2./(upper[i]-lower[i]);
97 for (i=0;i<fftSize;i++){
98 fftFreqs[i] = ((double) i / ((double) fftSize ) *
99 (double) samplingRate);
102 /* Build now the mccFilterWeight matrix */
103 for (i=0;i<totalFilters;i++){
105 for (j=0;j<fftSize;j++) {
107 if ((fftFreqs[j] > lower[i]) && (fftFreqs[j] <= center[i])) {
109 mfccFilterWeights[i][j] = triangleHeight[i] *
110 (fftFreqs[j]-lower[i]) / (center[i]-lower[i]);
115 mfccFilterWeights[i][j] = 0.0;
118 if ((fftFreqs[j]>center[i]) && (fftFreqs[j]<upper[i])) {
120 mfccFilterWeights[i][j] = mfccFilterWeights[i][j]
121 + triangleHeight[i] * (upper[i]-fftFreqs[j])
122 / (upper[i]-center[i]);
126 mfccFilterWeights[i][j] = mfccFilterWeights[i][j] + 0.0;
133 * We calculate now mfccDCT matrix
134 * NB: +1 because of the DC component
137 const double pi = 3.14159265358979323846264338327950288;
139 for (i = 0; i < nceps+1; i++) {
140 for (j = 0; j < totalFilters; j++) {
141 mfccDCTMatrix[i][j] = (1./sqrt((double) totalFilters / 2.))
142 * cos((double) i * ((double) j + 0.5) / (double) totalFilters * pi);
146 for (j = 0; j < totalFilters; j++){
147 mfccDCTMatrix[0][j] = (sqrt(2.)/2.) * mfccDCTMatrix[0][j];
150 /* The analysis window */
151 window = new Window<double>(config.window, fftSize);
153 /* Allocate memory for the FFT */
154 realOut = (double*)calloc(fftSize, sizeof(double));
155 imagOut = (double*)calloc(fftSize, sizeof(double));
157 earMag = (double*)calloc(totalFilters, sizeof(double));
158 fftMag = (double*)calloc(fftSize/2, sizeof(double));
164 free(triangleHeight);
172 /* Free the structure */
173 for (i = 0; i < nceps+1; i++) {
174 free(mfccDCTMatrix[i]);
178 for (i = 0; i < totalFilters; i++) {
179 free(mfccFilterWeights[i]);
181 free(mfccFilterWeights);
183 /* Free the feature vector */
186 /* The analysis window */
202 * Extract the MFCC on the input frame
205 int MFCC::process(const double *inframe, double *outceps)
207 double *inputData = (double *)malloc(fftSize * sizeof(double));
208 for (int i = 0; i < fftSize; ++i) inputData[i] = inframe[i];
210 window->cut(inputData);
212 /* Calculate the fft on the input frame */
213 fft->forward(inputData, realOut, imagOut);
217 return process(realOut, imagOut, outceps);
220 int MFCC::process(const double *real, const double *imag, double *outceps)
224 for (i = 0; i < fftSize/2; ++i) {
225 fftMag[i] = sqrt(real[i] * real[i] + imag[i] * imag[i]);
228 for (i = 0; i < totalFilters; ++i) {
232 /* Multiply by mfccFilterWeights */
233 for (i = 0; i < totalFilters; i++) {
235 for (j = 0; j < fftSize/2; j++) {
236 tmp = tmp + (mfccFilterWeights[i][j] * fftMag[j]);
238 if (tmp > 0) earMag[i] = log10(tmp);
239 else earMag[i] = 0.0;
241 if (logPower != 1.0) {
242 earMag[i] = pow(earMag[i], logPower);
248 * Calculate now the cepstral coefficients
249 * with or without the DC component
255 for (i = 0; i < nceps+1; i++) {
257 for (j = 0; j < totalFilters; j++){
258 tmp = tmp + mfccDCTMatrix[i][j] * earMag[j];
265 for (i = 1; i < nceps+1; i++) {
267 for (j = 0; j < totalFilters; j++){
268 tmp = tmp + mfccDCTMatrix[i][j] * earMag[j];