关于mfcc系数提取

文件 "mfcc.cpp"

 

#include  " mfcc.h "
#include 
< math.h >
#include 
< stdlib.h >

mfcc::mfcc()
{
        melbank();
        calcu_hamming();
        cal_stren_win();

        calcu_dct();
        qi
=1;
        
int i,j;
        
for(i=0;i<5;i++)
                
for(j=1;j<=256;j++)
                
{
                        buf[i][j]
=0;
                }

        
for(i=0;i<=256;i++)
        
{
                queue[i]
=0;     workingi[i]=0;
        }

        Pos
=0;
}


/*%归一化倒谱提升窗口
w=1+6*sin(pi*[1:12]./12);
w=w/max(w);
*/


void  mfcc::proc()
{
        
int i,j;
        
double sum;
        
double proc_buf1[25];
//      for(i=256;i>=1;i--)working[i]=working[i]-0.9375*working[i-1];

        
for(i=256;i>=1;i--)working[i]=working[i]-working[i-1];
        
//    s=y'.*hamming(256);
        for(i=1;i<=256;i++)working[i-1]=working[i]*hamming[i];
        
//同时错一格。
//    t=abs(fft(s));
        fft();
        
for(i=256;i>=1;i--)
        
{working[i]=working[i-1]*working[i-1]+workingi[i-1]*workingi[i-1];
                workingi[i
-1]=0;
        }

        
for(i=1;i<=24;i++)
        
{
                sum
=0;
                
for(j=1;j<=129;j++)
                
{
                        sum
=sum+x[i][j]*working[j];
                }

                
if(sum!=0)
                proc_buf1[i]
=log(sum);
                
else proc_buf1[i]=-3000;
        }

        
for(i=1;i<=12;i++)
        
{
                sum
=0;

                
for(j=1;j<=24;j++)
                
{
                        sum
=sum+dctcoef[i][j]*proc_buf1[j];
                }

                buf[Pos][i]
=sum*stren_win[i];
        }

        Pos
=(Pos+1)%5;
        
for(i=1;i<=12;i++){
                result[i]
=buf[(Pos+2)%5][i];
//    dtm(i,:)=-2*m(i-2,:)-m(i-1,:)+m(i+1,:)+2*m(i+2,:);
                result[i+12]=-2*buf[(Pos)%5][i]
               
-buf[(Pos+1)%5][i]+buf[(Pos+3)%5][i]+2*buf[(Pos+4)%5][i];
                result[i
+12]=result[i+12]/3;
        }

}


void  mfcc::cal_stren_win()
{
        
int i;
        
double b=0.0;
        
for(i=1;i<=12;i++){
                stren_win[i]
=1+6*sin(pi*(double)i/(double)12);
                
if(b<stren_win[i])b=stren_win[i];
        }

        
for(i=1;i<=12;i++){
                stren_win[i]
=stren_win[i]/b;
        }

}


void  mfcc::calcu_hamming()
{
        
int i;
        
for(i=1;i<=256;i++){
        hamming[i]
=0.54-0.46*cos(2*pi*(i-1)/(256-1));
        }

}


void  mfcc::read( short   * data)
{
        
int i;
        
for(i=0;i<INC_MFCC;i++){
                queue[qi]
=(double)data[i];
                qi
=qi%257+1;
        }

        Level
=0.0;
        
for(i=0;i<257;i++){
                working[i]
=queue[(qi+i+256)%257+1];
                Level
=Level+fabs(working[i]);
        }

}


void  mfcc:: set ()
{
        
int i;
        
for(i=0;i<257;i++) working[i]=i;
//      working[1]=1;
}


void  mfcc::calcu_dct()
{
/*      %DCT系数,12*24
for k=1:12
    n=0:23;
    dctcoef(k,:)=cos((2*n+1)*k*pi/(2*24));
end
*/

        
int k,n;
        
for(k=1;k<=12;k++)
        
for(n=0;n<=23;n++)
        
{
                dctcoef[k][n
+1]=cos((double)(2*n+1)*k*pi/(double)(2*24));
        }

}


void  mfcc::melbank()
{
        
double f0,fn2,lr;
        
int b1,b2,b3,b4,k2,k3,k4,mn,mx;
        
double bl[5];
        
double pf[LEN_PF_MFCC],fp[LEN_PF_MFCC],pm[LEN_PF_MFCC],v[LEN_PF_MFCC];
        
int r[LEN_PF_MFCC],c[LEN_PF_MFCC];
        
int i,j;
        
for(i=0;i<SIZE_X_X_MFCC;i++){
                
for(j=0;j<SIZE_X_Y_MFCC;j++){
                        x[i][j]
=0.0;
                }

        }

        f0
=(double)700/(double)FS_MFCC;
//      fn2=floor(n/2);

        fn2
=floor((double)N_MFCC/2);

        lr
=log((f0+FH_MFCC)/(f0+FL_MFCC))/(P_MFCC+1.0);
//// convert to fft bin numbers with 0 for DC term
//      bl=N*((f0+FL)*exp([0 1 p p+1]*lr)-f0);
        bl[1]=N_MFCC*((f0+FL_MFCC)*exp(0*lr)-f0);
        bl[
2]=N_MFCC*((f0+FL_MFCC)*exp(1*lr)-f0);
        bl[
3]=N_MFCC*((f0+FL_MFCC)*exp(P_MFCC*lr)-f0);
        bl[
4]=N_MFCC*((f0+FL_MFCC)*exp((P_MFCC+1)*lr)-f0);

        b2
=(int)ceil(bl[2]);
        b3
=(int)floor(bl[3]);
/*if any(w=='y')
  pf=log((f0+(b2:b3)/n)/(f0+fl))/lr;
  fp=floor(pf);
  r=[ones(1,b2) fp fp+1 p*ones(1,fn2-b3)];
  c=[1:b3+1 b2+1:fn2+1];
  v=2*[0.5 ones(1,b2-1) 1-pf+fp pf-fp ones(1,fn2-b3-1) 0.5];
  mn=1;
  mx=fn2+1;
else
*/

  b1
=(int)floor(bl[1])+1;
  b4
=(int)__min(fn2,ceil(bl[4]))-1;
        k2
=b2-b1+1;
        k3
=b3-b1+1;
        k4
=b4-b1+1;
  mn
=b1+1;
  mx
=b4+1;
//  pf=log((f0+(b1:b4)/n)/(f0+fl))/lr;
  for(i=1,j=b1;j<=b4;i++,j++){
        pf[i]
=log(((double)f0+(double)i/(double)N_MFCC)/(f0+FL_MFCC))/lr;
//  fp=floor(pf);
        fp[i]=floor(pf[i]);
//  pm=pf-fp;
        pm[i]=pf[i]-fp[i];
  }

//  k2=b2-b1+1;
//  k3=b3-b1+1;
//  k4=b4-b1+1;
//  r=[fp(k2:k4) 1+fp(1:k3)];
//  c=[k2:k4 1:k3];
//  v=2*[1-pm(k2:k4) pm(1:k3)];

  
for(i=1,j=k2;j<=k4;i++,j++){
        r[i]
=(int)fp[j];
        c[i]
=j;
        v[i]
=2*(1-pm[j]);
  }

  
for(j=1;j<=k3;j++,i++){
        r[i]
=1+(int)fp[j];
        c[i]
=j;
        v[i]
=2*pm[j];
  }


//  mn=b1+1;
//  mx=b4+1;
//if any(w=='n')
//  v=1-cos(v*pi/2);
//elseif any(w=='m')
//  v=1-0.92/1.08*cos(v*pi/2);
  for(j=1;j<i;j++){
        v[j]
=1-0.92/1.08*cos(v[j]*pi/2);
        x[r[j]][c[j]
+mn-1]=v[j];
  }

//end
//if nargout > 1
//  x=sparse(r,c,v);
//else

//  x=sparse(r,c+mn-1,v,p,1+fn2);
//end
        double buf;
        
for(i=1;i<=24;i++)
        
for(j=1;j<=129;j++)
                
if(x[i][j]>buf)buf=x[i][j];

        
for(i=1;i<=24;i++)
        
for(j=1;j<=129;j++)
                x[i][j]
=x[i][j]/buf;

}


void  mfcc::fft()
{
        
int i,j,k,n,nv2,nm1,l,le,le1,ip,sign=-1;
        
double tr,ti,ur,ui,wr,wi;
        
double *xr;
        
double *xi;
        xr
=working;
        xi
=workingi;
        n
=1<<8;
        nv2
=n>>1;
        nm1
=n-1;
        j
=0;
        
for(i=0;i<nm1;i++)
        
{
                
if(i<j){
                        tr
=xr[j];
                        ti
=xi[j];
                        xr[j]
=xr[i];
                        xi[j]
=xi[i];
                        xr[i]
=tr;
                        xi[i]
=ti;
                }

                k
=nv2;
                
while(k<=j){
                        j
-=k;
                        k
=k>>1;
                }

                j
+=k;
        }

        
for(l=1;l<=8;l++)
        
{
                le
=1<<l;
                le1
=le/2;
                ur
=1.;
                ui
=0.;
                wr
=cos(pi/le1);
                wi
=-sin(pi/le1);
                
for(j=0;j<le1;j++)
                
{

                        
for(i=j;i<n;i+=le)
                        
{
                                ip
=i+le1;
                                tr
=xr[ip]*ur-xi[ip]*ui;
                                ti
=xr[ip]*ui+xi[ip]*ur;
                                xr[ip]
=xr[i]-tr;
                                xi[ip]
=xi[i]-ti;
                                xr[i]
=xr[i]+tr;
                                xi[i]
=xi[i]+ti;
                        }

                        tr
=ur*wr-ui*wi;
                        ti
=ur*wi+ui*wr;
                        ur
=tr;
                        ui
=ti;

                }

        }

        
return;
}


int  mfcc::report_begin()
{
        
if(Level>THRESHOUD_BEGIN*257)return(1);
        
else return(0);
}


int  mfcc::report_end()
{
        
if(Level<THRESHOUD_END*257)return(1);
        
else return(0);
}

                                              

文件"mfcc.h"

 

#ifndef MFCC_H_XPP
#define  MFCC_H_XPP
#define  X_M_MFCC
#define  X_N_MFCC
#define  FL_MFCC 0  // low end of the
// lowest filter as a fraction of fs (default = 0)
#define  FH_MFCC 0.5  // high end of
// highest filter as a fraction of fs (default = 0.5)                                                                    
#define  FS_MFCC 8000  // sample rate in Hz
#define  N_MFCC 256  // length of fft
#define  P_MFCC 24   // number of filters in filterbank
#define  LEN_PF_MFCC 256
#define  pi 3.141592653589
#define  SIZE_X_X_MFCC 32
#define  SIZE_X_Y_MFCC 140
#define  SIZE_DCT_X_MFCC 13
#define  SIZE_DCT_Y_MFCC 25
#define  INC_MFCC 80
#define  THRESHOUD_BEGIN 350
#define  THRESHOUD_END 250

class  mfcc {
private:

        
void melbank();
        
double x[SIZE_X_X_MFCC][SIZE_X_Y_MFCC];
        
double dctcoef[SIZE_DCT_X_MFCC][SIZE_DCT_Y_MFCC];
        
void calcu_dct();
        
double hamming[257];
        
void calcu_hamming();
        
void cal_stren_win();
        
double stren_win[13];
        
int Pos;
        
double buf[5][25];
        
double queue[300];
        
double working[257];
        
double workingi[257];
        
void fft();
        
int qi;
        
double Level;
public:
        
double result[25];
        
void proc();
        
void set();
        
void read(short *);
        
int report_begin();
        
int report_end();
        mfcc();
}
;

#endif                                              

样例程序:

 

#include  " mfcc.h "
void  main( int  argc,  char   * argv[])
{
        mfcc test;
        
while(1){
//      将长度80的语音缓冲区刷新的操作。这里简略。
        test.read(SpeechBuffer);//SpeechBuffer是从第0个有效的一段80个语音样点。                                         
                
//语音样点是短整型16位PCM信号,
        test.proc();
/*      接下来,对象test提供3个结果如下:
        test.result;test.result是从第一个有效的,并非从第0个有效,
                        //是24个参数,前12个是主参数,后12个是查分参数。
        test.report_begin()语音起始标志
        test.report_end()语音结束标志。
*/

        }

}

来源:
以上程序是我在学(精华区x-3-1-6)课程的
时候做大作业时自己写的一个类。
当时我是根据Matlab中MFCC的源码中翻译成C++的。
在现在的Matlab中没有这个函数,
得要到
http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
上把相应的语音库当下来,
然后,
自己编一个Matlab程序清单如下:
文件"mfcc.m"
function ccc=mfcc(x)
%归一化mel滤波器组系数
bank=melbankm(24,256,8000,0,0.5,'m');
bank=full(bank);
bank=bank/max(bank(:));

%DCT系数,12*24
for k=1:12
    n=0:23;
    dctcoef(k,:)=cos((2*n+1)*k*pi/(2*24));
end

%归一化倒谱提升窗口
w=1+6*sin(pi*[1:12]./12);
w=w/max(w);

%预加重滤波器
xx=double(x);
xx=filter([1 -1],1,xx);

%语音信号分帧
%xx=enframe(xx,256,80);
xppl=length(xx);
j=1;
for i=65:80:xppl-256,
    xx1(j,:)=xx(i:i+256-1)';
    j=j+1;
end
xx=xx1;

%计算每帧的MFCC参数
for i=1:size(xx,1)
    y=xx(i,:);
    s=y'.*hamming(256);
    t=abs(fft(s));
    t=t.^2;
    t=t+2*realmin;
    c1=dctcoef*log(bank*t(1:129));
    c2=c1.*w';
    m(i,:)=c2';
end

%差分参数
dtm=zeros(size(m));
for i=3:size(m,1)-2
    dtm(i,:)=-2*m(i-2,:)-m(i-1,:)+m(i+1,:)+2*m(i+2,:);
end
dtm=dtm/3;

%合并mfcc参数和一阶差分mfcc参数
ccc=[m dtm];
%去除首尾两帧,因为这两帧的一阶差分参数为0
ccc=ccc(3:size(m,1)-2,:);
return

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值