文章目录
-
- 1.Mel频率倒谱系数(Mel-Frequency Cepstral Coefficients)
- 2.梅尔参数的提取
1.Mel频率倒谱系数(Mel-Frequency Cepstral Coefficients)
我们将频谱通过一组Mel滤波器得到Mel频谱。
公式表述就是:log X[k] = log (Mel-Spectrum)。这时候我们在log X[k]上进行倒谱分析:
1)取对数:log X[k] = log H[k] + log E[k]。
2)进行逆变换:x[k] = h[k] + e[k]。
在Mel频谱上面获得的倒谱系数h[k]就称为Mel频率倒谱系数,简称MFCC。
2.梅尔参数的提取
现在咱们来总结下提取MFCC特征的过程:
1)先对语音进行预加重、分帧和加窗;
2)对每一个短时分析窗,通过FFT得到对应的频谱;
3)将上面的频谱通过Mel滤波器组得到Mel频谱;
4)在Mel频谱上面进行倒谱分析(取对数,做逆变换,实际逆变换一般是通过DCT离散余弦变换来实现,取DCT后的第2个到第13个系数作为MFCC系数),获得Mel频率倒谱系数MFCC,这个MFCC就是这帧语音的特征;
这时候,语音就可以通过一系列的倒谱向量来描述了,每个向量就是每帧的MFCC特征向量。
这样就可以通过这些倒谱向量对语音分类器进行训练和识别了。
参考:https://blog.csdn.net/zouxy09/article/details/9156785
1)预加重
预加重的目的是提升高频部分,使信号的频谱变得平坦,保持在低频到高频的整个频带中,能用同样的信噪比求频谱。同时,也是为了消除发生过程中声带和嘴唇的效应,来补偿语音信号受到发音系统所抑制的高频部分,也为了突出高频的共振峰。
实现代码
%MFCC参数提取
clear all; clc; close all;
[x,Fs]=audioread('bluesky3.wav');
%对输入的语音序列x进行MFCC参数的提取,返回MFCC参数和一阶
%差分MFCC参数,Mel滤波器的阶数为24
%fft变换的长度为256,采样频率为8000Hz,对x 256点分为一帧
%Mel滤波
fs = 8000; %采样频率
fl = 0; %fl是设计滤波器的最低频率
fh = fs / 2; %fh是设计滤波器的最高频率
bl = 1125 * log(1 + fl/700); %最低频率对应的Mel频率
bh = 1125 * log(1 + fh/700); %最高频率对应的Mel频率
p = 24; %在fl和fh之间设计Mel滤波器的个数
N = 256; %FFT点数,N越大,频率分辨率越高,误差越小
MelF = linspace(0, bh-bl, p+2); %在0至bh-bl的Mel频率范围内产生p+2个Mel频率值
F = 700 * (exp(MelF/1125) - 1); %将上一步产生的p+2个Mel频率值转化为p+2个实际频率值
df = fs / N; %计算频率分辨率
n = N/2 + 1; %计算fs/2内对应的FFT点数
f = (0:n-1) * df; %计算频率序列,共有n个频率点
bank = zeros(24, n); %生成24行n列的全零矩阵
for m1 = 2:p+1 %循环起始数为2,因为下方语句中用到m-1的值,其中m-1必须为正整数,所以m为大于等于2的正整数
%F为实际频率,分别找到三角滤波器左中右对应的频率
F_left = F(m1-1);
F_mid = F(m1);
F_right = F(m1+1);
%使用ceil()函数向上取整,计算实际频率对应的FFT点数
n_left = ceil(F_left / df); %频率F_left对应的FFT点数
n_mid = ceil(F_mid / df); %频率F_mid对应的FFT点数
n_right = ceil(F_right / df); %频率F_right对应的FFT点数
%用三角窗的频率响应函数作图
for k = 1:n %根据FFT点数画三角窗
if k>=n_left & k<=n_mid
bank(m1-1,k) = (k-n_left)/(n_mid-n_left); %画第m-1个滤波器的左半部分
elseif k>n_mid & k<=n_right
bank(m1-1,k) = (n_right-k)/(n_right-n_mid); %画第m-1个滤波器的右半部分
end
end
end
% 归一化mel滤波器组系数
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
% 归一化倒谱提升窗口
%乘以倒谱提升窗口,目的是对MFCC系数中某些谱线增强
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,256,80);
% 计算每帧的MFCC参数
for i=1:size(xx,1)
y = xx(i,:);
s = y' .* hamming(256);
t = abs(fft(s)); %快速傅里叶变换
t = t.^2; %计算谱线能量
c1=dctcoef * log(bank * t(1:129));
c2 = c1.*w';%乘以倒谱提升窗口,目的是对MFCC系数中某些谱线增强
m(i,:)=c2';
end
%差分系数
%差量倒频谱参数(Delta cepstrum):虽然已经求出 13 个特征参数,
%然而在实际应用于语音识别时,我们通常会再加上差量倒频谱参数,
%以显示倒频谱参数对时间的变化。它的意义为倒频谱参数相对于时间的斜率,
%也就是代表倒频谱参数在时间上的动态变化,
%公式如下: △Cm(t) = [St=-MMCm(t+t)t] /[St=-MMt2] 这里 M 的值一般是取 2 或 3。
%因此,如果加上差量运算,就会产生 26 维的特征向量;如果再加上差差量运算,就会产生 39 维的特征向量。
%一般我们在 PC 上进行的语音识别,就是使用 39 维的特征向量。
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,:);
ccc_1=ccc(:,1);
ccc_2=ccc(:,13);
figure(1)
plot(x); %画出原始语音的信号波形
title('原始波形');
figure(2)
plot(ccc_1);ylabel('幅值'); %画出第1列数据经过差分后的MFCC
hold on;
plot(ccc_2,'m');title('经过差分后的MFCC');ylabel('幅值'); %画出第13列数据经过差分后的MFCC
legend('第1列数据','第2列数据'); %显示图例
figure(3)
plot(m(:,1)); %画出不经过差分之前得到的第一列数据MFCC
title('不经过差分之前得到的第一列数据MFCC');
运行结果