annotate dsp/mfcc/mfcc.c @ 23:eea2a08a75a9

* remove some debug output
author cannam
date Thu, 10 Jan 2008 15:14:30 +0000
parents 34808d582f47
children
rev   line source
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