annotate dsp/mfcc/MFCC.c @ 25:54a962727271

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