comparison dsp/mfcc/MFCC.c @ 250:a106e551e9a4

...
author Chris Cannam <c.cannam@qmul.ac.uk>
date Thu, 10 Jan 2008 15:16:08 +0000
parents
children
comparison
equal deleted inserted replaced
249:18a0dffa5c1a 250:a106e551e9a4
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5
6 #include "mfcc.h"
7 #include "SBFFT.h"
8 #include "windows.h"
9
10 /*
11 *
12 * Initialise the MFCC structure and return a pointer to a
13 * feature vector
14 *
15 */
16
17 extern mfcc_t* init_mfcc(int fftSize, int nceps , int samplingRate, int WANT_C0){
18
19 int i,j;
20 /* Calculate at startup */
21 double *freqs, *lower, *center, *upper, *triangleHeight, *fftFreqs;
22
23 /* Allocate space for the structure */
24 mfcc_t* mfcc_p = (mfcc_t*)malloc(sizeof(mfcc_t));
25
26 mfcc_p->lowestFrequency = 66.6666666;
27 mfcc_p->linearFilters = 13;
28 mfcc_p->linearSpacing = 66.66666666;
29 mfcc_p->logFilters = 27;
30 mfcc_p->logSpacing = 1.0711703;
31
32 /* FFT and analysis window sizes */
33 mfcc_p->fftSize = fftSize;
34
35 mfcc_p->totalFilters = mfcc_p->linearFilters + mfcc_p->logFilters;
36
37 mfcc_p->samplingRate = samplingRate;
38
39 /* The number of cepstral componenents */
40 mfcc_p->nceps = nceps;
41
42 /* Set if user want C0 */
43 mfcc_p->WANT_C0 = WANT_C0;
44
45 /* Allocate space for feature vector */
46 if (mfcc_p->WANT_C0==1) {
47 mfcc_p->ceps = (double*)calloc(nceps+1,sizeof(double));
48 } else {
49 mfcc_p->ceps = (double*)calloc(nceps,sizeof(double));
50 }
51
52 /* Allocate space for local vectors */
53 mfcc_p->mfccDCTMatrix = (double**)calloc(mfcc_p->nceps+1, sizeof(double*));
54 for (i=0;i<mfcc_p->nceps+1; i++) {
55 mfcc_p->mfccDCTMatrix[i]= (double*)calloc(mfcc_p->totalFilters, sizeof(double));
56 }
57
58 mfcc_p->mfccFilterWeights = (double**)calloc(mfcc_p->totalFilters, sizeof(double*));
59 for (i=0;i<mfcc_p->totalFilters; i++) {
60 mfcc_p->mfccFilterWeights[i] = (double*)calloc(mfcc_p->fftSize, sizeof(double));
61 }
62
63 freqs = (double*)calloc(mfcc_p->totalFilters+2,sizeof(double));
64
65 lower = (double*)calloc(mfcc_p->totalFilters,sizeof(double));
66 center = (double*)calloc(mfcc_p->totalFilters,sizeof(double));
67 upper = (double*)calloc(mfcc_p->totalFilters,sizeof(double));
68
69 triangleHeight = (double*)calloc(mfcc_p->totalFilters,sizeof(double));
70 fftFreqs = (double*)calloc(mfcc_p->fftSize,sizeof(double));
71
72 for (i=0;i<mfcc_p->linearFilters;i++) {
73 freqs[i] = mfcc_p->lowestFrequency + ((double)i) * mfcc_p->linearSpacing;
74 }
75
76 for (i=mfcc_p->linearFilters; i<mfcc_p->totalFilters+2; i++) {
77 freqs[i] = freqs[mfcc_p->linearFilters-1] *
78 pow(mfcc_p->logSpacing, (double)(i-mfcc_p->linearFilters+1));
79 }
80
81 /* Define lower, center and upper */
82 memcpy(lower, freqs,mfcc_p->totalFilters*sizeof(double));
83 memcpy(center, &freqs[1],mfcc_p->totalFilters*sizeof(double));
84 memcpy(upper, &freqs[2],mfcc_p->totalFilters*sizeof(double));
85
86 for (i=0;i<mfcc_p->totalFilters;i++){
87 triangleHeight[i] = 2./(upper[i]-lower[i]);
88 }
89
90 for (i=0;i<mfcc_p->fftSize;i++){
91 fftFreqs[i] = ((double) i / ((double) mfcc_p->fftSize ) *
92 (double) mfcc_p->samplingRate);
93 }
94
95 /* Build now the mccFilterWeight matrix */
96 for (i=0;i<mfcc_p->totalFilters;i++){
97
98 for (j=0;j<mfcc_p->fftSize;j++) {
99
100 if ((fftFreqs[j] > lower[i]) && (fftFreqs[j] <= center[i])) {
101
102 mfcc_p->mfccFilterWeights[i][j] = triangleHeight[i] *
103 (fftFreqs[j]-lower[i]) / (center[i]-lower[i]);
104
105 }
106 else
107 {
108
109 mfcc_p->mfccFilterWeights[i][j] = 0.0;
110
111 }
112
113 if ((fftFreqs[j]>center[i]) && (fftFreqs[j]<upper[i])) {
114
115 mfcc_p->mfccFilterWeights[i][j] = mfcc_p->mfccFilterWeights[i][j] + triangleHeight[i] * (upper[i]-fftFreqs[j])
116 / (upper[i]-center[i]);
117 }
118 else
119 {
120
121 mfcc_p->mfccFilterWeights[i][j] = mfcc_p->mfccFilterWeights[i][j] + 0.0;
122
123 }
124 }
125
126 }
127
128 #ifndef PI
129 #define PI 3.14159265358979323846264338327950288
130 #endif
131
132 /*
133 *
134 * We calculate now mfccDCT matrix
135 * NB: +1 because of the DC component
136 *
137 */
138
139 for (i=0; i<nceps+1; i++) {
140 for (j=0; j<mfcc_p->totalFilters; j++) {
141 mfcc_p->mfccDCTMatrix[i][j] = (1./sqrt((double) mfcc_p->totalFilters / 2.))
142 * cos((double) i * ((double) j + 0.5) / (double) mfcc_p->totalFilters * PI);
143 }
144 }
145
146 for (j=0;j<mfcc_p->totalFilters;j++){
147 mfcc_p->mfccDCTMatrix[0][j] = (sqrt(2.)/2.) * mfcc_p->mfccDCTMatrix[0][j];
148 }
149
150 /* The analysis window */
151 mfcc_p->window = hamming(mfcc_p->fftSize);
152
153 /* Allocate memory for the FFT */
154 mfcc_p->imagIn = (double*)calloc(mfcc_p->fftSize,sizeof(double));
155 mfcc_p->realOut = (double*)calloc(mfcc_p->fftSize,sizeof(double));
156 mfcc_p->imagOut = (double*)calloc(mfcc_p->fftSize,sizeof(double));
157
158 free(freqs);
159 free(lower);
160 free(center);
161 free(upper);
162 free(triangleHeight);
163 free(fftFreqs);
164
165 return mfcc_p;
166
167 }
168
169 /*
170 *
171 * Free the memory that has been allocated
172 *
173 */
174
175 extern void close_mfcc(mfcc_t* mfcc_p) {
176
177 int i;
178
179 /* Free the structure */
180 for (i=0;i<mfcc_p->nceps+1;i++) {
181 free(mfcc_p->mfccDCTMatrix[i]);
182 }
183 free(mfcc_p->mfccDCTMatrix);
184
185 for (i=0;i<mfcc_p->totalFilters; i++) {
186 free(mfcc_p->mfccFilterWeights[i]);
187 }
188 free(mfcc_p->mfccFilterWeights);
189
190 /* Free the feature vector */
191 free(mfcc_p->ceps);
192
193 /* The analysis window */
194 free(mfcc_p->window);
195
196 /* Free the FFT */
197 free(mfcc_p->imagIn);
198 free(mfcc_p->realOut);
199 free(mfcc_p->imagOut);
200
201 /* Free the structure itself */
202 free(mfcc_p);
203 mfcc_p = NULL;
204
205 }
206
207 /*
208 *
209 * Extract the MFCC on the input frame
210 *
211 */
212
213
214 // looks like we have to have length = mfcc_p->fftSize ??????
215
216 extern int do_mfcc(mfcc_t* mfcc_p, double* frame, int length){
217
218 int i,j;
219
220 double *fftMag;
221 double *earMag;
222
223 double *inputData;
224
225 double tmp;
226
227 earMag = (double*)calloc(mfcc_p->totalFilters, sizeof(double));
228 inputData = (double*)calloc(mfcc_p->fftSize, sizeof(double));
229
230 /* Zero-pad if needed */
231 memcpy(inputData, frame, length*sizeof(double));
232
233 /* Calculate the fft on the input frame */
234 fft_process(mfcc_p->fftSize, 0, inputData, mfcc_p->imagIn, mfcc_p->realOut, mfcc_p->imagOut);
235
236 /* Get the magnitude */
237 fftMag = abs_fft(mfcc_p->realOut, mfcc_p->imagOut, mfcc_p->fftSize);
238
239 /* Multiply by mfccFilterWeights */
240 for (i=0;i<mfcc_p->totalFilters;i++) {
241 tmp = 0.;
242 for(j=0;j<mfcc_p->fftSize/2; j++) {
243 tmp = tmp + (mfcc_p->mfccFilterWeights[i][j]*fftMag[j]);
244 }
245 if (tmp>0)
246 earMag[i] = log10(tmp);
247 else
248 earMag[i] = 0.0;
249 }
250
251 /*
252 *
253 * Calculate now the ceptral coefficients
254 * with or without the DC component
255 *
256 */
257
258 if (mfcc_p->WANT_C0==1) {
259
260 for (i=0;i<mfcc_p->nceps+1;i++) {
261 tmp = 0.;
262 for (j=0;j<mfcc_p->totalFilters;j++){
263 tmp = tmp + mfcc_p->mfccDCTMatrix[i][j]*earMag[j];
264 }
265 /* Send to workspace */
266 mfcc_p->ceps[i] = tmp;
267 }
268
269 }
270 else
271 {
272 for (i=1;i<mfcc_p->nceps+1;i++) {
273 tmp = 0.;
274 for (j=0;j<mfcc_p->totalFilters;j++){
275 tmp = tmp + mfcc_p->mfccDCTMatrix[i][j]*earMag[j];
276 }
277 /* Send to workspace */
278 mfcc_p->ceps[i-1] = tmp;
279 }
280 }
281
282 free(fftMag);
283 free(earMag);
284 free(inputData);
285
286 return mfcc_p->nceps;
287
288 }
289
290
291
292