Mercurial > hg > qm-dsp
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 |