📄 mfcc-core.c
字号:
for(i = framesize; i >= 2; i--) wave[i] -= wave[i - 1] * preEmph; wave[1] *= 1.0 - preEmph; }/** * Apply hamming window. * * @param wave [i/o] waveform data in the current frame * @param framesize [in] frame size * @param w [i/o] MFCC calculation work area */void Hamming(float *wave, int framesize, MFCCWork *w){ int i;#ifdef MFCC_SINCOS_TABLE for(i = 1; i <= framesize; i++) wave[i] *= w->costbl_hamming[i-1];#else float a; a = 2 * PI / (framesize - 1); for(i = 1; i <= framesize; i++) wave[i] *= 0.54 - 0.46 * cos(a * (i - 1));#endif}/** * Apply FFT * * @param xRe [i/o] real part of waveform * @param xIm [i/o] imaginal part of waveform * @param p [in] 2^p = FFT point * @param w [i/o] MFCC calculation work area */void FFT(float *xRe, float *xIm, int p, MFCCWork *w){ int i, ip, j, k, m, me, me1, n, nv2; double uRe, uIm, vRe, vIm, wRe, wIm, tRe, tIm; n = 1<<p; nv2 = n / 2; j = 0; for(i = 0; i < n-1; i++){ if(j > i){ tRe = xRe[j]; tIm = xIm[j]; xRe[j] = xRe[i]; xIm[j] = xIm[i]; xRe[i] = tRe; xIm[i] = tIm; } k = nv2; while(j >= k){ j -= k; k /= 2; } j += k; } for(m = 1; m <= p; m++){ me = 1<<m; me1 = me / 2; uRe = 1.0; uIm = 0.0;#ifdef MFCC_SINCOS_TABLE wRe = w->costbl_fft[m-1]; wIm = w->sintbl_fft[m-1];#else wRe = cos(PI / me1); wIm = -sin(PI / me1);#endif for(j = 0; j < me1; j++){ for(i = j; i < n; i += me){ ip = i + me1; tRe = xRe[ip] * uRe - xIm[ip] * uIm; tIm = xRe[ip] * uIm + xIm[ip] * uRe; xRe[ip] = xRe[i] - tRe; xIm[ip] = xIm[i] - tIm; xRe[i] += tRe; xIm[i] += tIm; } vRe = uRe * wRe - uIm * wIm; vIm = uRe * wIm + uIm * wRe; uRe = vRe; uIm = vIm; } }}/** * Convert wave -> (spectral subtraction) -> mel-frequency filterbank * * @param wave [in] waveform data in the current frame * @param w [i/o] MFCC calculation work area * @param para [in] configuration parameters */voidMakeFBank(float *wave, MFCCWork *w, Value *para){ int k, bin, i; double Re, Im, A, P, NP, H, temp; for(k = 1; k <= para->framesize; k++){ w->fb.Re[k - 1] = wave[k]; w->fb.Im[k - 1] = 0.0; /* copy to workspace */ } for(k = para->framesize + 1; k <= w->fb.fftN; k++){ w->fb.Re[k - 1] = 0.0; w->fb.Im[k - 1] = 0.0; /* pad with zeroes */ } /* Take FFT */ FFT(w->fb.Re, w->fb.Im, w->fb.n, w); if (w->ssbuf != NULL) { /* Spectral Subtraction */ for(k = 1; k <= w->fb.fftN; k++){ Re = w->fb.Re[k - 1]; Im = w->fb.Im[k - 1]; P = sqrt(Re * Re + Im * Im); NP = w->ssbuf[k - 1]; if((P * P - w->ss_alpha * NP * NP) < 0){ H = w->ss_floor; }else{ H = sqrt(P * P - w->ss_alpha * NP * NP) / P; } w->fb.Re[k - 1] = H * Re; w->fb.Im[k - 1] = H * Im; } } /* Fill filterbank channels */ for(i = 1; i <= para->fbank_num; i++) w->fbank[i] = 0.0; if (para->usepower) { for(k = w->fb.klo; k <= w->fb.khi; k++){ Re = w->fb.Re[k-1]; Im = w->fb.Im[k-1]; A = Re * Re + Im * Im; bin = w->fb.loChan[k]; Re = w->fb.loWt[k] * A; if(bin > 0) w->fbank[bin] += Re; if(bin < para->fbank_num) w->fbank[bin + 1] += A - Re; } } else { for(k = w->fb.klo; k <= w->fb.khi; k++){ Re = w->fb.Re[k-1]; Im = w->fb.Im[k-1]; A = sqrt(Re * Re + Im * Im); bin = w->fb.loChan[k]; Re = w->fb.loWt[k] * A; if(bin > 0) w->fbank[bin] += Re; if(bin < para->fbank_num) w->fbank[bin + 1] += A - Re; } } /* Take logs */ for(bin = 1; bin <= para->fbank_num; bin++){ temp = w->fbank[bin]; if(temp < 1.0) temp = 1.0; w->fbank[bin] = log(temp); }}/** * Calculate 0'th cepstral coefficient. * * @param w [i/o] MFCC calculation work area * @param para [in] configuration parameters * * @return */float CalcC0(MFCCWork *w, Value *para){ int i; float S; S = 0.0; for(i = 1; i <= para->fbank_num; i++) S += w->fbank[i]; return S * w->sqrt2var;}/** * Apply DCT to filterbank to make MFCC. * * @param mfcc [out] output MFCC vector * @param para [in] configuration parameters * @param w [i/o] MFCC calculation work area */void MakeMFCC(float *mfcc, Value *para, MFCCWork *w){#ifdef MFCC_SINCOS_TABLE int i, j, k; k = 0; /* Take DCT */ for(i = 0; i < para->mfcc_dim; i++){ mfcc[i] = 0.0; for(j = 1; j <= para->fbank_num; j++) mfcc[i] += w->fbank[j] * w->costbl_makemfcc[k++]; mfcc[i] *= w->sqrt2var; }#else int i, j; float B, C; B = PI / para->fbank_num; /* Take DCT */ for(i = 1; i <= para->mfcc_dim; i++){ mfcc[i - 1] = 0.0; C = i * B; for(j = 1; j <= para->fbank_num; j++) mfcc[i - 1] += w->fbank[j] * cos(C * (j - 0.5)); mfcc[i - 1] *= w->sqrt2var; }#endif}/** * Re-scale cepstral coefficients. * * @param mfcc [i/o] a MFCC vector * @param para [in] configuration parameters * @param w [i/o] MFCC calculation work area */void WeightCepstrum (float *mfcc, Value *para, MFCCWork *w){#ifdef MFCC_SINCOS_TABLE int i; for(i=0;i<para->mfcc_dim;i++) { mfcc[i] *= w->sintbl_wcep[i]; }#else int i; float a, b, *cepWin; cepWin = (float *)mymalloc(para->mfcc_dim * sizeof(float)); a = PI / para->lifter; b = para->lifter / 2.0; for(i = 0; i < para->mfcc_dim; i++){ cepWin[i] = 1.0 + b * sin((i + 1) * a); mfcc[i] *= cepWin[i]; } free(cepWin);#endif}/************************************************************************//************************************************************************//************************************************************************//************************************************************************//************************************************************************//** * Setup work area for parameters, values, buffers, tables to compute * MFCC vectors, with a given parameter configurations * * @param para [in] configuration parameters * * @return pointer to the newly allocated work area. */MFCCWork *WMP_work_new(Value *para){ MFCCWork *w; /* newly allocated area should be cleared */ w = (MFCCWork *)mymalloc(sizeof(MFCCWork)); memset(w, 0, sizeof(MFCCWork)); /* set filterbank information */ if (InitFBank(w, para) == FALSE) return NULL;#ifdef MFCC_SINCOS_TABLE /* prepare tables */ make_costbl_hamming(w, para->framesize); make_fft_table(w, w->fb.n); if (para->mfcc_dim >= 0) { make_costbl_makemfcc(w, para->fbank_num, para->mfcc_dim); make_sintbl_wcep(w, para->lifter, para->mfcc_dim); }#endif /* prepare some buffers */ w->fbank = (double *)mymalloc((para->fbank_num+1)*sizeof(double)); w->bf = (float *)mymalloc(w->fb.fftN * sizeof(float)); w->bflen = w->fb.fftN; return w;}/** * Calculate MFCC and log energy for one frame. Perform spectral subtraction * if @a ssbuf is specified. * * @param w [i/o] MFCC calculation work area * @param mfcc [out] buffer to hold the resulting MFCC vector * @param para [in] configuration parameters */voidWMP_calc(MFCCWork *w, float *mfcc, Value *para){ float energy = 0.0; float c0 = 0.0; int p; if (para->zmeanframe) { ZMeanFrame(w->bf, para->framesize); } if (para->energy && para->raw_e) { /* calculate log raw energy */ energy = CalcLogRawE(w->bf, para->framesize); } /* pre-emphasize */ PreEmphasise(w->bf, para->framesize, para->preEmph); /* hamming window */ Hamming(w->bf, para->framesize, w); if (para->energy && ! para->raw_e) { /* calculate log energy */ energy = CalcLogRawE(w->bf, para->framesize); } /* filterbank */ MakeFBank(w->bf, w, para); /* 0'th cepstral parameter */ if (para->c0) c0 = CalcC0(w, para); /* MFCC */ MakeMFCC(mfcc, para, w); /* weight cepstrum */ WeightCepstrum(mfcc, para, w); /* set energy to mfcc */ p = para->mfcc_dim; if (para->c0) mfcc[p++] = c0; if (para->energy) mfcc[p++] = energy;}/** * Free all work area for MFCC computation * * @param w [i/o] MFCC calculation work area */voidWMP_free(MFCCWork *w){ if (w->fbank) { FreeFBank(&(w->fb)); free(w->fbank); free(w->bf); w->fbank = NULL; w->bf = NULL; }#ifdef MFCC_SINCOS_TABLE if (w->costbl_hamming) { free(w->costbl_hamming); w->costbl_hamming = NULL; } if (w->costbl_fft) { free(w->costbl_fft); w->costbl_fft = NULL; } if (w->sintbl_fft) { free(w->sintbl_fft); w->sintbl_fft = NULL; } if (w->costbl_makemfcc) { free(w->costbl_makemfcc); w->costbl_makemfcc = NULL; } if (w->sintbl_wcep) { free(w->sintbl_wcep); w->sintbl_wcep = NULL; }#endif free(w);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -