#ifndef MEL_H
#define MEL_H
#include
void output(const QString & name,double *d,int size);
class CMel
{
public:
CMel();
int mel(double *data,int size);
protected:
void filtter(double d, double * powerSample);
private:
};
#endif // MEL_H
#include "Mel.h"
#include
#include
#include
#define FILTTER_NUM 25
//滤波器的中心频率,最大8khz
const int FiltFreq[FILTTER_NUM+1] = {0,100,200,300,400,500,600,700,800,900,
1000,1149,1320,1516,1741,2000,2297,2639,3031,3482,
4000,4595,5278,6063,6964,8001};
//滤波器的带宽
const int BW[FILTTER_NUM+1]={100,100,100,100,100,100,100,100,100,100,
124,160,184,211,242,278,320,367,422,484,
556,639,734,843,969,1112};
void output(const QString & name,double *d,int size)
{
QDebug &out = qDebug();
out << name << " ";
for(int i=0; i i++)
{
out << d[i];
}
}
CMel::CMel()
{
}
int CMel::mel(double *data,int size)
{
//处理滤波
double *powerSamp = new double[FILTTER_NUM + 1];
memset(powerSamp,0,FILTTER_NUM*sizeof(double));
for(int i=0; i i++)
{
filtter(data[i],powerSamp);
}
//拷贝结果数据
for(int i=0;i<FILTTER_NUM;i++)
{
data[i]= powerSamp[i];
}
delete[] powerSamp;
return FILTTER_NUM;
}
void CMel::filtter(double d, double * powerSample)
{
//一个频点,必点包含在上个滤波器的右半部和下个滤波器的左半部
for(int i = 0; i<FILTTER_NUM;i++)
{
if(d > FiltFreq[i] && d < FiltFreq[i+1])
{
//右半部分
double filterpara = 1 - (d-i*BW[i])/BW[i];
filterpara += powerSample[i];
powerSample[i]=filterpara;
//左半部分
filterpara = 1 + (d-i*BW[i+1])/BW[i+1];
filterpara += powerSample[i+1];
powerSample[i+1]=filterpara;
}
}
}
这个算法,参照了网上的一个算法,将mel频率域的计算转换的时域计算,转换的关键就在cpp文件的开头定义的每个摩尔滤波器的中中频率对应的时域中心频率列表和每个滤波器的带宽列表。