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倒谱为
式中,,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滤波器组的频率响应曲线')
运行结果如下:
案例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语音信号分析与合成(第二版);宋知用(编著)