cannam@21: #include cannam@21: #include cannam@21: #include cannam@21: #include cannam@21: cannam@21: #include "mfcc.h" cannam@21: #include "SBFFT.h" cannam@21: #include "windows.h" cannam@21: cannam@21: /* cannam@21: * cannam@21: * Initialise the MFCC structure and return a pointer to a cannam@21: * feature vector cannam@21: * cannam@21: */ cannam@21: cannam@21: extern mfcc_t* init_mfcc(int fftSize, int nceps , int samplingRate, int WANT_C0){ cannam@21: cannam@21: int i,j; cannam@21: /* Calculate at startup */ cannam@21: double *freqs, *lower, *center, *upper, *triangleHeight, *fftFreqs; cannam@21: cannam@21: /* Allocate space for the structure */ cannam@21: mfcc_t* mfcc_p = (mfcc_t*)malloc(sizeof(mfcc_t)); cannam@21: cannam@21: mfcc_p->lowestFrequency = 66.6666666; cannam@21: mfcc_p->linearFilters = 13; cannam@21: mfcc_p->linearSpacing = 66.66666666; cannam@21: mfcc_p->logFilters = 27; cannam@21: mfcc_p->logSpacing = 1.0711703; cannam@21: cannam@21: /* FFT and analysis window sizes */ cannam@21: mfcc_p->fftSize = fftSize; cannam@21: cannam@21: mfcc_p->totalFilters = mfcc_p->linearFilters + mfcc_p->logFilters; cannam@21: cannam@21: mfcc_p->samplingRate = samplingRate; cannam@21: cannam@21: /* The number of cepstral componenents */ cannam@21: mfcc_p->nceps = nceps; cannam@21: cannam@21: /* Set if user want C0 */ cannam@21: mfcc_p->WANT_C0 = WANT_C0; cannam@21: cannam@21: /* Allocate space for feature vector */ cannam@21: if (mfcc_p->WANT_C0==1) { cannam@21: mfcc_p->ceps = (double*)calloc(nceps+1,sizeof(double)); cannam@21: } else { cannam@21: mfcc_p->ceps = (double*)calloc(nceps,sizeof(double)); cannam@21: } cannam@21: cannam@21: /* Allocate space for local vectors */ cannam@21: mfcc_p->mfccDCTMatrix = (double**)calloc(mfcc_p->nceps+1, sizeof(double*)); cannam@21: for (i=0;inceps+1; i++) { cannam@21: mfcc_p->mfccDCTMatrix[i]= (double*)calloc(mfcc_p->totalFilters, sizeof(double)); cannam@21: } cannam@21: cannam@21: mfcc_p->mfccFilterWeights = (double**)calloc(mfcc_p->totalFilters, sizeof(double*)); cannam@21: for (i=0;itotalFilters; i++) { cannam@21: mfcc_p->mfccFilterWeights[i] = (double*)calloc(mfcc_p->fftSize, sizeof(double)); cannam@21: } cannam@21: cannam@21: freqs = (double*)calloc(mfcc_p->totalFilters+2,sizeof(double)); cannam@21: cannam@21: lower = (double*)calloc(mfcc_p->totalFilters,sizeof(double)); cannam@21: center = (double*)calloc(mfcc_p->totalFilters,sizeof(double)); cannam@21: upper = (double*)calloc(mfcc_p->totalFilters,sizeof(double)); cannam@21: cannam@21: triangleHeight = (double*)calloc(mfcc_p->totalFilters,sizeof(double)); cannam@21: fftFreqs = (double*)calloc(mfcc_p->fftSize,sizeof(double)); cannam@21: cannam@21: for (i=0;ilinearFilters;i++) { cannam@21: freqs[i] = mfcc_p->lowestFrequency + ((double)i) * mfcc_p->linearSpacing; cannam@21: } cannam@21: cannam@21: for (i=mfcc_p->linearFilters; itotalFilters+2; i++) { cannam@21: freqs[i] = freqs[mfcc_p->linearFilters-1] * cannam@21: pow(mfcc_p->logSpacing, (double)(i-mfcc_p->linearFilters+1)); cannam@21: } cannam@21: cannam@21: /* Define lower, center and upper */ cannam@21: memcpy(lower, freqs,mfcc_p->totalFilters*sizeof(double)); cannam@21: memcpy(center, &freqs[1],mfcc_p->totalFilters*sizeof(double)); cannam@21: memcpy(upper, &freqs[2],mfcc_p->totalFilters*sizeof(double)); cannam@21: cannam@21: for (i=0;itotalFilters;i++){ cannam@21: triangleHeight[i] = 2./(upper[i]-lower[i]); cannam@21: } cannam@21: cannam@21: for (i=0;ifftSize;i++){ cannam@21: fftFreqs[i] = ((double) i / ((double) mfcc_p->fftSize ) * cannam@21: (double) mfcc_p->samplingRate); cannam@21: } cannam@21: cannam@21: /* Build now the mccFilterWeight matrix */ cannam@21: for (i=0;itotalFilters;i++){ cannam@21: cannam@21: for (j=0;jfftSize;j++) { cannam@21: cannam@21: if ((fftFreqs[j] > lower[i]) && (fftFreqs[j] <= center[i])) { cannam@21: cannam@21: mfcc_p->mfccFilterWeights[i][j] = triangleHeight[i] * cannam@21: (fftFreqs[j]-lower[i]) / (center[i]-lower[i]); cannam@21: cannam@21: } cannam@21: else cannam@21: { cannam@21: cannam@21: mfcc_p->mfccFilterWeights[i][j] = 0.0; cannam@21: cannam@21: } cannam@21: cannam@21: if ((fftFreqs[j]>center[i]) && (fftFreqs[j]mfccFilterWeights[i][j] = mfcc_p->mfccFilterWeights[i][j] + triangleHeight[i] * (upper[i]-fftFreqs[j]) cannam@21: / (upper[i]-center[i]); cannam@21: } cannam@21: else cannam@21: { cannam@21: cannam@21: mfcc_p->mfccFilterWeights[i][j] = mfcc_p->mfccFilterWeights[i][j] + 0.0; cannam@21: cannam@21: } cannam@21: } cannam@21: cannam@21: } cannam@21: cannam@21: #ifndef PI cannam@21: #define PI 3.14159265358979323846264338327950288 cannam@21: #endif cannam@21: cannam@21: /* cannam@21: * cannam@21: * We calculate now mfccDCT matrix cannam@21: * NB: +1 because of the DC component cannam@21: * cannam@21: */ cannam@21: cannam@21: for (i=0; itotalFilters; j++) { cannam@21: mfcc_p->mfccDCTMatrix[i][j] = (1./sqrt((double) mfcc_p->totalFilters / 2.)) cannam@21: * cos((double) i * ((double) j + 0.5) / (double) mfcc_p->totalFilters * PI); cannam@21: } cannam@21: } cannam@21: cannam@21: for (j=0;jtotalFilters;j++){ cannam@21: mfcc_p->mfccDCTMatrix[0][j] = (sqrt(2.)/2.) * mfcc_p->mfccDCTMatrix[0][j]; cannam@21: } cannam@21: cannam@21: /* The analysis window */ cannam@21: mfcc_p->window = hamming(mfcc_p->fftSize); cannam@21: cannam@21: /* Allocate memory for the FFT */ cannam@21: mfcc_p->imagIn = (double*)calloc(mfcc_p->fftSize,sizeof(double)); cannam@21: mfcc_p->realOut = (double*)calloc(mfcc_p->fftSize,sizeof(double)); cannam@21: mfcc_p->imagOut = (double*)calloc(mfcc_p->fftSize,sizeof(double)); cannam@21: cannam@21: free(freqs); cannam@21: free(lower); cannam@21: free(center); cannam@21: free(upper); cannam@21: free(triangleHeight); cannam@21: free(fftFreqs); cannam@21: cannam@21: return mfcc_p; cannam@21: cannam@21: } cannam@21: cannam@21: /* cannam@21: * cannam@21: * Free the memory that has been allocated cannam@21: * cannam@21: */ cannam@21: cannam@21: extern void close_mfcc(mfcc_t* mfcc_p) { cannam@21: cannam@21: int i; cannam@21: cannam@21: /* Free the structure */ cannam@21: for (i=0;inceps+1;i++) { cannam@21: free(mfcc_p->mfccDCTMatrix[i]); cannam@21: } cannam@21: free(mfcc_p->mfccDCTMatrix); cannam@21: cannam@21: for (i=0;itotalFilters; i++) { cannam@21: free(mfcc_p->mfccFilterWeights[i]); cannam@21: } cannam@21: free(mfcc_p->mfccFilterWeights); cannam@21: cannam@21: /* Free the feature vector */ cannam@21: free(mfcc_p->ceps); cannam@21: cannam@21: /* The analysis window */ cannam@21: free(mfcc_p->window); cannam@21: cannam@21: /* Free the FFT */ cannam@21: free(mfcc_p->imagIn); cannam@21: free(mfcc_p->realOut); cannam@21: free(mfcc_p->imagOut); cannam@21: cannam@21: /* Free the structure itself */ cannam@21: free(mfcc_p); cannam@21: mfcc_p = NULL; cannam@21: cannam@21: } cannam@21: cannam@21: /* cannam@21: * cannam@21: * Extract the MFCC on the input frame cannam@21: * cannam@21: */ cannam@21: cannam@21: cannam@21: // looks like we have to have length = mfcc_p->fftSize ?????? cannam@21: cannam@21: extern int do_mfcc(mfcc_t* mfcc_p, double* frame, int length){ cannam@21: cannam@21: int i,j; cannam@21: cannam@21: double *fftMag; cannam@21: double *earMag; cannam@21: cannam@21: double *inputData; cannam@21: cannam@21: double tmp; cannam@21: cannam@21: earMag = (double*)calloc(mfcc_p->totalFilters, sizeof(double)); cannam@21: inputData = (double*)calloc(mfcc_p->fftSize, sizeof(double)); cannam@21: cannam@21: /* Zero-pad if needed */ cannam@21: memcpy(inputData, frame, length*sizeof(double)); cannam@21: cannam@21: /* Calculate the fft on the input frame */ cannam@21: fft_process(mfcc_p->fftSize, 0, inputData, mfcc_p->imagIn, mfcc_p->realOut, mfcc_p->imagOut); cannam@21: cannam@21: /* Get the magnitude */ cannam@21: fftMag = abs_fft(mfcc_p->realOut, mfcc_p->imagOut, mfcc_p->fftSize); cannam@21: cannam@21: /* Multiply by mfccFilterWeights */ cannam@21: for (i=0;itotalFilters;i++) { cannam@21: tmp = 0.; cannam@21: for(j=0;jfftSize/2; j++) { cannam@21: tmp = tmp + (mfcc_p->mfccFilterWeights[i][j]*fftMag[j]); cannam@21: } cannam@21: if (tmp>0) cannam@21: earMag[i] = log10(tmp); cannam@21: else cannam@21: earMag[i] = 0.0; cannam@21: } cannam@21: cannam@21: /* cannam@21: * cannam@21: * Calculate now the ceptral coefficients cannam@21: * with or without the DC component cannam@21: * cannam@21: */ cannam@21: cannam@21: if (mfcc_p->WANT_C0==1) { cannam@21: cannam@21: for (i=0;inceps+1;i++) { cannam@21: tmp = 0.; cannam@21: for (j=0;jtotalFilters;j++){ cannam@21: tmp = tmp + mfcc_p->mfccDCTMatrix[i][j]*earMag[j]; cannam@21: } cannam@21: /* Send to workspace */ cannam@21: mfcc_p->ceps[i] = tmp; cannam@21: } cannam@21: cannam@21: } cannam@21: else cannam@21: { cannam@21: for (i=1;inceps+1;i++) { cannam@21: tmp = 0.; cannam@21: for (j=0;jtotalFilters;j++){ cannam@21: tmp = tmp + mfcc_p->mfccDCTMatrix[i][j]*earMag[j]; cannam@21: } cannam@21: /* Send to workspace */ cannam@21: mfcc_p->ceps[i-1] = tmp; cannam@21: } cannam@21: } cannam@21: cannam@21: free(fftMag); cannam@21: free(earMag); cannam@21: free(inputData); cannam@21: cannam@21: return mfcc_p->nceps; cannam@21: cannam@21: } cannam@21: cannam@21: cannam@21: cannam@21: