美尔频率倒谱系数(MFCC)的计算及其应用案例

MFCC特征参数提取原理框图如下图所示

(1)预处理
预处理包括预加重、分帧、加窗函数。
预加重:在第1章中已指出声门脉冲的频率响应曲线接近于一个二阶低通滤波器,而口腔的辐射响应也接近于一个一阶高通滤波器。预加重的目的是为了补偿高频分量的损失,提升高频分量。预加重的滤波器常设为

式中,a为一个常数。
分帧处理:由于一个语音信号是一个准稳态的信号,把它分成较短的帧,在每帧信号中可将其看作稳态信号,可用处理稳态信号的方法来处理。同时,为了使一帧与另一帧之间的参数能较平稳地过渡,在相邻两帧之间互相有部分重叠。

加窗函数:加窗函数的目的是减少频域中的泄漏,将对每一帧语音乘以汉明窗或海宁窗。语音信号x(n)经预处理后为xi(m),其中下标i表示分帧后的第i帧。
(2)快速傅里叶变换
对每一帧信号进行FFT变换,从时域数据转变为频域数据:

(3)计算谱线能量
对每一帧FFT后的数据计算谱线的能量:

(4)计算通过美尔滤波器的能量
把求出的每帧谱线能量谱通过美尔滤波器,并计算在该美尔滤波器中的能量。在频域中相当于把每帧的能量谱E(i,k)(其中i表示第i帧,k表示频域中的第k条谱线)与美尔滤波器的频域响应   Hm(k)相乘并相加:

(5)计算DCT倒谱
序列x(n)的FFT倒谱\hat{x}(n)

式中,\hat{X}(k)=ln{FT[x(n)]}=ln{X(k)},FT和FT^-1表示傅里叶变换和傅里叶逆变换。序列x(n)的DCT为

式中,参数N是序列x(n)的长度;C(k)是正交因子,可表示为


 

在上式中求取FFT的倒谱是把X(k)取对数后计算FFT的逆变换。而这里求DCT的倒谱和求FFT的倒谱相类似,把美尔滤波器的能量取对数后计算DCT:


 

式中,S(i,m)是由上式求出的美尔滤波器能量;m是指第m个美尔滤波器(共有M个);i是指第i帧;n是DCT后的谱线。

案例1、fs为8000Hz,利用函数melbankm设计24个Mel滤波器,最低频率f1=0Hz,最高频率fh=0.5Hz,使用三角窗函数

程序如下:

clear all; clc; close all;

% 调用melbankm函数,在0-0.5区间设计24个Mel滤波器,用三角形窗函数
bank=melbankm(24,256,8000,0,0.5,'t');
bank=full(bank);
bank=bank/max(bank(:));              % 幅值归一化

df=8000/256;                         % 计算分辨率
ff=(0:128)*df;                       % 频率坐标刻度
for k=1 : 24                         % 绘制24个Mel滤波器响应曲线
    plot(ff,bank(k,:),'k','linewidth',2); hold on;
end
hold off; grid;
xlabel('频率/Hz'); ylabel('相对幅值')
title('Mel滤波器组的频率响应曲线')

运行结果如下:

美尔频率倒谱系数(MFCC)的计算及其应用案例_第1张图片

 案例2、4)根据MFCC系数计算流程,计算一段语音的MFCC系数。

计算MFCC系数的函数Nmfcc

函数定义如下:
ccc = Nmfcc(x,fs,p,frameSize, inc);
其中,x是输人语音序列;Mel滤波器的个数为p;采样频率为fs;frameSize为帧长和FFT
点数;inc为帧移;ccc为MFCC参数。

函数程序如下:

function ccc=Nmfcc(x,fs,p,frameSize,inc)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                 function ccc=Nmfcc(x);
% x是输入语音序列,Mel滤波器的个数为p,采样频率为fs,frameSize为帧长和FFT点数,inc为帧移;ccc为MFCC参数。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% 按帧长为frameSize,Mel滤波器的个数为p,采样频率为fs
% 提取Mel滤波器参数,用汉明窗函数
bank=melbankm(p,frameSize,fs,0,0.5,'m');
% 归一化Mel滤波器组系数
bank=full(bank);
bank=bank/max(bank(:));

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

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

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

% 语音信号分帧
xx=enframe(xx,frameSize,inc);
n2=fix(frameSize/2)+1;
% 计算每帧的MFCC参数
for i=1:size(xx,1)
  y = xx(i,:);
  s = y' .* hamming(frameSize);
  t = abs(fft(s));
  t = t.^2;
  c1=dctcoef * log(bank * t(1:n2));
  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,:);

主程序如下:

%实验要求四:MFCC计算程序
clear all; clc; close all;

[x1,fs]=audioread('C3_4_y_4.wav');                            % 读入信号C3_4_y_4.wav
wlen=200;                                                                  % 帧长
inc=80;                                                                     % 帧移
num=8;                                                                      %Mel滤波器个数
x1=x1/max(abs(x1));                                                 % 幅值归一化
time=(0:length(x1)-1)/fs;
subplot 211; plot(time,x1,'b') 
title('(a)语音信号');
ylabel('幅值'); xlabel(['时间/s' ]);  
ccc1=Nmfcc(x1,fs,num,wlen,inc);
fn=size(ccc1,1)+4;                                                  %前后各有两帧被舍弃
cn=size(ccc1,2);
z=zeros(1,cn);
ccc2=[z;z;ccc1;z;z];
frameTime=FrameTimeC(fn,wlen,inc,fs);               % 求出每帧对应的时间
subplot 212; plot(frameTime,ccc2(:,1:cn/2),'b')      % 画出每通道的MFCC系数
title('(b)MFCC系数');
ylabel('幅值'); xlabel(['时间/s' ]);  

参考文献:

语音信号处理实验教程;梁瑞宇、赵力、魏昕(编著) 

MATLAB语音信号分析与合成(第二版);宋知用(编著)

你可能感兴趣的:(算法)