mfcc

来源:互联网 发布:百度人工智能产品 编辑:程序博客网 时间:2024/05/22 19:56

     在研究MFCC算法时,从网上下了一份代码,经过小改编译通过了,可程序一跑就蹦,费了好几天的功夫也没找到问题的原因。

化了一个月的时间边看资料,边整理代码,参照原有代码自己实现了一份。目前代码调通了,还没有能力验证结果的正确性。


     这里使用的FFT算法是从网上下载的。稍后也将其附上。欢迎有MFCC经验的朋友帮忙指正其中存在的问题。

      

#ifndef MFCC_H
#define MFCC_H
#include <stdio.h>
#include <math.h>
#include <QVector>
#include <QMap>
#define MOD_256  8
#define MOD_512  9
#define MOD_1024 10
class CMFCC
{
public:
    CMFCC(int Mod);
    int mfcc(double * data,int size);
protected:
    void preEmphasis();
    void procFrame();
    void procHammingWindows(double * buffer);
    void fft(double * buffer);
    int Melf(double * buffer);
    void DCT(double *lnpower,int len,double * dct,int dctnum);
private:
    double * m_data;
    int m_size;
    int m_frameSize;
    double m_factor;
    double m_hammingFactor;
    int m_mod;
    int m_resoultSize;
};


#include "MFCC.h"
#include <memory.h>
#include "FFT.h"
#include "Mel.h"
#include "PlotWidget.h"
#include <QDebug>
#include <math.h>
#define PI 3.141592653589793
CMFCC::CMFCC(int mod)
    :m_data(0),m_size(0),m_frameSize(pow(2,mod))
    ,m_factor(0.97),m_hammingFactor(0.46),m_mod(mod)
{
}
int CMFCC::mfcc(double * data,int size)
{
    m_data = data;
    m_size = size;
    this->preEmphasis();
    this->procFrame();
    return 0;
}
void CMFCC::preEmphasis()
{
    for(int i =1; i< m_size; i++)
    {
        m_data[i] = m_data[i] - m_factor * m_data[i-1];
    }
}
void CMFCC::procFrame()
{
    //plot("data",0,m_data,m_size,Qt::blue);
    int dis = m_frameSize - m_frameSize / 3;
    double * buffer = new double[m_frameSize];
    int i = 0;
    for(; i< m_size-m_frameSize; i+= dis)
    {
        double * s = m_data + i;
        //double * e = m_data + i + m_frameSize;
        memcpy(buffer,s,m_frameSize * sizeof(double));
        //plot("frame",0,buffer,m_frameSize,Qt::blue);
        this->procHammingWindows(buffer);
        //plot("ccc",0,buffer,m_frameSize,Qt::red);
        this->fft(buffer);
        //plot("fft",0,buffer,m_frameSize,Qt::red);
        this->Melf(buffer);
        //plot("fft",0,buffer,m_frameSize/2,Qt::red);
    }
    /*
    int n = i - m_size;
    if(n > 0)
    {
        memset(buffer,0,m_frameSize*sizeof(double));
        memcpy(buffer,m_data+m_size-n,m_frameSize*sizeof(double));
        //plot("frame",0,buffer,m_frameSize,Qt::blue);
        this->procHammingWindows(buffer);
        this->fft(buffer);
        this->Melf(buffer);
        //plot("fft",0,buffer,m_frameSize,Qt::red);
    }
    */
    delete[] buffer;
}
void CMFCC::procHammingWindows(double * buffer)
{
    int size = m_frameSize -1;
    for(int i=0; i<m_frameSize; i++)
    {
        double d = (2 * PI * i)/size;
        double w = (1-m_hammingFactor) - m_hammingFactor * cos(d);
        buffer[i] = buffer[i] * w;
    }
}
void CMFCC::fft(double * buffer)
{
    complex *tx = new complex[m_frameSize];
    for(int i = 0; i<m_frameSize; i++)
    {
        tx[i].real = buffer[i];
        tx[i].img = 0;
    }
    complex * dx = new complex[m_frameSize];
    complex * nex_t = new complex[m_frameSize];
    memset(dx,0,m_frameSize * sizeof(complex));
    memset(nex_t,0,m_frameSize * sizeof(complex));
    FFT(tx,dx,nex_t,m_frameSize,m_mod);
    for(int i=0; i<m_frameSize; i++)
    {
        buffer[i] = dx[i].real;
    }
    delete tx;
    delete dx;
    delete nex_t;
}
int CMFCC::Melf(double * buffer)
{
    CMel mel;
    int n = mel.mel(buffer,m_frameSize/2);
    //output("mel :",buffer,n);
    double dctNum = 10;
    double *dct = new double[dctNum];
    memset(dct,0,dctNum*sizeof(double));
    DCT(buffer,n,dct,dctNum);
    //output("dtc :",dct,dctNum);
    plot("dtc",0,dct,dctNum,Qt::red);
    delete[] dct;
    return dctNum;
}
void CMFCC::DCT(double *data,int len,double * dct,int dctnum)
{
    //double temp[100];
    //memset(temp,0,100*sizeof(double));
    //memcpy(temp,data,len*sizeof(double));
    double k = pow(2.0/(double)len,0.5);
    for(int i=0;i<dctnum;i++)
    {
        for(int j=0;j<len;j++)
        {
            double d = data[j];
            if(d > std::numeric_limits<double>::min())
            {
                double d1 = log(data[j]);
                double d2 = cos(i*(j-0.5)*3.141592653589793/len);
                double d3 = d1 * d2;
                double d5 = dct[i];
                d5 += d3;
                dct[i] += d3;
            }
            //dct[i] += log(data[j])*cos(i*(j-0.5)*3.141592653589793/len);
        }
        double md = dct[i];
        dct[i] *= k;
    }
    //double temp2[100];
    //memset(temp2,0,100*sizeof(double));
    //memcpy(temp2,dct,dctnum*sizeof(double));
    //int n = 0;
}


0 0