📄 fe_mfcc.cpp
字号:
///////////////////////////////////////////////////////////////////////////////
// This is a part of the Feature program.
// Version: 1.0
// Date: February 22, 2003
// Programmer: Oh-Wook Kwon
// Copyright(c) 2003 Oh-Wook Kwon. All rights reserved. owkwon@ucsd.edu
///////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "FE_feature.h"
int Fe::mel_cepstrum_basic(short *sample, int frameSize, float *mel_cep, int ceporder, int fft_size)
{
vector<float> frameA(frameSize);
preprocessing(sample, frameSize, &frameA[0]);
m_window.Windowing(&frameA[0], frameSize, WIN_HAMMING);
_mel_cepstrum_basic(&frameA[0], frameSize, mel_cep, m_fbOrder, ceporder, fft_size);
return 1;
}
int Fe::_mel_cepstrum_basic(float *sample, int frameSize, float *mel_cep, int fborder, int ceporder, int fft_size)
{
int i;
if(m_dctMatrix.size() != ceporder*fborder || ceporder != m_cepOrder){
m_dctMatrix.resize((ceporder+1)*fborder);
MfccInitDCTMatrix (&m_dctMatrix[0], ceporder, fborder);
m_idctMatrix.resize((ceporder+1)*fborder);
MfccInitIDCTMatrix (&m_idctMatrix[0], ceporder, fborder);
}
vector<float> filter_bank(m_fbOrder);
_filterbank_basic(sample, frameSize, &filter_bank[0], fborder, fft_size, 0, 0);
MfccDCT (&filter_bank[0], &m_dctMatrix[0], ceporder, fborder, mel_cep);
/* scale down to be consistent with other kinds of cepstrum coefficients */
float f=fborder/(float)fft_size;
for(i=0;i<=ceporder;i++) mel_cep[i]*=f;
return 1;
}
/* Supporting routine for MFCC */
#define MfccRound(x) ((int)((x)+0.5))
void Fe::MfccInitMelFilterBanks (float startingFrequency, float samplingRate, int fftLength, int numChannels)
{
int i, k;
vector<float> freq(numChannels+2);
vector<int> bin(numChannels+2);
float start_mel, fs_per_2_mel;
/* Constants for calculation */
freq[0] = startingFrequency;
start_mel = (float)(2595.0 * log10 (1.0 + startingFrequency / 700.0));
bin[0] = MfccRound(fftLength * freq[0] / samplingRate);
freq[numChannels+1] = (float)(samplingRate / 2.0);
fs_per_2_mel = (float)(2595.0 * log10 (1.0 + (samplingRate / 2.0) / 700.0));
bin[numChannels+1] = MfccRound(fftLength * freq[numChannels+1] / samplingRate);
/* Calculating mel-scaled frequency and the corresponding FFT-bin */
/* number for the lower edge of the band */
for (k = 1; k <= numChannels; k++) {
freq[k] = (float)(700 * (pow (10, (start_mel + (float) k / (numChannels + 1) * (fs_per_2_mel - start_mel)) / 2595.0) - 1.0));
bin[k] = MfccRound(fftLength * freq[k] / samplingRate);
}
/* This part is never used to compute MFCC coefficients */
/* but initialized for completeness */
m_MelWeight.resize(fftLength/2+1);
for(i = 0; i<bin[0]; i++){
m_MelWeight[i]=0;
}
m_MelWeight[fftLength/2]=1;
/* Initialize low, center, high indices to FFT-bin */
m_MelFB.resize(numChannels);
for (k = 0; k <= numChannels; k++) {
if(k<numChannels){
m_MelFB[k].m_lowX=bin[k];
m_MelFB[k].m_centerX=bin[k+1];
m_MelFB[k].m_highX=bin[k+2];
}
for(i = bin[k]; i<bin[k+1]; i++){
m_MelWeight[i]=(i-bin[k]+1)/(float)(bin[k+1]-bin[k]+1);
}
}
m_MelCenterFreq.resize(numChannels+2);
m_MelCenterIdx.resize(numChannels+2);
for(k=0;k<=numChannels+1;k++){
m_MelCenterFreq[k]=freq[k];
m_MelCenterIdx[k]=bin[k];
}
return;
}
/* Be careful that the assumed ordering is [c0 c1 c2 ... c12] */
int Fe::MfccInitDCTMatrix (float *dctMatrix, int ceporder, int numChannels)
{
int i, j;
for (i = 0; i <= ceporder; i++){
for (j = 0; j < numChannels; j++){
dctMatrix[i * numChannels + j] = (float) cos (M_PI * (float) i / (float) numChannels * ((float) j + 0.5));
if(i==0) dctMatrix[i * numChannels + j]*=(float)sqrt(1/(float)numChannels);
else dctMatrix[i * numChannels + j]*=(float)sqrt(2/(float)numChannels);
}
}
return 1;
}
/* Be careful that the assumed ordering is [c0 c1 c2 ... c12] */
int Fe::MfccInitIDCTMatrix (float *idctMatrix, int ceporder, int numChannels)
{
int i, j;
for (j = 0; j < numChannels; j++){
for (i = 0; i <= ceporder; i++){
idctMatrix[j * (ceporder+1) + i] = (float) cos (M_PI * (float) i / (float) numChannels * ((float) j + 0.5));
if(i==0) idctMatrix[j * (ceporder+1) + i]*=(float)sqrt(1/(float)numChannels);
else idctMatrix[j * (ceporder+1) + i]*=(float)sqrt(2/(float)numChannels);
}
}
return 1;
}
void Fe::MfccDCT (float *x, float *dctMatrix, int ceporder, int numChannels, float *mel_cep)
{
int i, j;
for (i = 0; i <= ceporder; i++) {
mel_cep[i] = 0.0;
for (j = 0; j < numChannels; j++){
mel_cep[i] += x[j] * dctMatrix[i * numChannels + j];
}
}
return;
}
void Fe::MfccIDCT (float *mel_cep, float *idctMatrix, int ceporder, int numChannels, float *x)
{
int i, j;
for (j = 0; j < numChannels; j++) {
x[j] = 0;
for (i = 0; i <= ceporder; i++) {
x[j] += mel_cep[i] * idctMatrix[j * (ceporder+1) + i];
}
}
return;
}
void Fe::MfccMelFilterBank (float *sigFFT, int numChannels, float* output, int normalize)
{
float sum, wsum;
int i, k;
for (k=0;k<numChannels;k++){
MfccMelFB *melFB=&m_MelFB[k];
sum = sigFFT[melFB->m_centerX];
wsum=1;
for (i = melFB->m_lowX; i < melFB->m_centerX; i++){
sum += m_MelWeight[i] * sigFFT[i];
wsum += m_MelWeight[i];
}
for (i = melFB->m_centerX+1; i <= melFB->m_highX; i++){
sum += (1 - m_MelWeight[i-1]) * sigFFT[i];
wsum += (1 - m_MelWeight[i-1]);
}
output[k] = sum;
if(normalize) {
assert(wsum>0);
output[k] /= wsum;
}
}
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -