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