美尔频率倒谱系数(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滤波器组的频率响应曲线')

运行结果如下:

 案例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语音信号分析与合成(第二版);宋知用(编著)

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于DTW的阿拉伯数字识别的matlab编程实现: 1. 提取美尔频率倒谱系数(MFCC) MFCC是一种用于音频和语音处理的特征提取方法,常用于语音识别。它们是基于人耳听觉模型的,因此对于人听来说,它们更具有区分度。MFCC的主要步骤如下: 1) 前置处理:对音频信号进行预加重处理,以增强高频部分,减少低频部分。 2) 分帧:将音频信号按照固定长度进行分帧,通常为20-40ms,帧移通常为10-20ms。 3) 加窗:对每一帧进行加窗操作,常用的窗函数包括汉明窗、海宁窗等。 4) 傅里叶变换:对每一帧进行FFT(快速傅里叶变换)得到频谱。 5) Mel滤波器组:将频谱转换到Mel尺度上,使用一组Mel滤波器对频谱进行滤波。 6) DCT(离散余弦变换):对每个Mel滤波器输出进行DCT得到MFCC系数。 下面是一个简单的matlab代码实现: ```matlab % 读取音频文件 filename = 'sample.wav'; [x, fs] = audioread(filename); % 预加重 preemph = [1, -0.97]; x = filter(preemph, 1, x); % 分帧 frame_len = 25; % 每帧长度为25ms frame_shift = 10; % 帧移为10ms frame_size = round(frame_len * fs / 1000); frame_shift_size = round(frame_shift * fs / 1000); frames = buffer(x, frame_size, frame_size-frame_shift_size, 'nodelay'); % 加窗 window = hamming(frame_size); frames = bsxfun(@times, frames, window); % FFT NFFT = 2^nextpow2(frame_size); mag_frames = abs(fft(frames, NFFT, 2)); % Mel滤波器组 low_freq = 0; high_freq = fs/2; nfilt = 26; mel_pts = linspace(hz2mel(low_freq), hz2mel(high_freq), nfilt+2); hz_pts = mel2hz(mel_pts); bin = floor((NFFT+1)*hz_pts/fs); filter_bank = zeros(nfilt, floor(NFFT/2+1)); for j = 1:nfilt for i = bin(j):bin(j+1) filter_bank(j,i) = (i - bin(j))/(bin(j+1)-bin(j)); end for i = bin(j+1):bin(j+2) filter_bank(j,i) = (bin(j+2)-i)/(bin(j+2)-bin(j+1)); end end % 应用Mel滤波器组 filtered_frames = filter_bank * mag_frames(:,1:NFFT/2+1)'; % 取对数 log_filtered_frames = log(filtered_frames+eps); % DCT num_ceps = 12; mfcc = dct(log_filtered_frames); mfcc = mfcc(1:num_ceps,:); ``` 2. 动态时间规整(DTW) DTW是一种用于信号、图像、语音等序列数据的相似性度量方法,可以用于比较两个序列的相似性。它可以解决两个序列长度不同的问题。DTW的基本思路是将其中一个序列沿着时间轴进行拉伸或压缩,使其与另一个序列匹配。 下面是一个简单的matlab代码实现: ```matlab % 计算MFCC系数 mfcc1 = compute_mfcc('sample1.wav'); mfcc2 = compute_mfcc('sample2.wav'); % 计算距离矩阵 d = pdist2(mfcc1', mfcc2', 'euclidean'); % 动态时间规整 dtw = zeros(size(d)); for i = 1:size(d,1) for j = 1:size(d,2) if i == 1 && j == 1 dtw(i,j) = d(i,j); elseif i == 1 dtw(i,j) = d(i,j) + dtw(i,j-1); elseif j == 1 dtw(i,j) = d(i,j) + dtw(i-1,j); else dtw(i,j) = d(i,j) + min([dtw(i-1,j), dtw(i,j-1), dtw(i-1,j-1)]); end end end ``` 以上代码中,`compute_mfcc`函数是用来计算MFCC系数的,可以使用前面提到的MFCC计算代码。`pdist2`函数计算两个序列之间的距离矩阵,`dtw`矩阵则是动态时间规整后的距离矩阵。 3. 阿拉伯数字识别 对于阿拉伯数字的识别,可以先录制一些样本,计算它们的MFCC系数,并将它们保存到一个数据库中。当需要识别一个新的数字时,首先计算它的MFCC系数,然后与数据库中的每个数字进行比较,找到最相似的数字。 下面是一个简单的matlab代码实现: ```matlab % 计算MFCC系数 mfcc_test = compute_mfcc('test.wav'); % 加载数据库 load('database.mat', 'database'); % 计算距离矩阵 min_distance = Inf; min_index = 0; for i = 1:length(database) d = pdist2(mfcc_test', database{i}.mfcc', 'euclidean'); distance = dtw(d); if distance < min_distance min_distance = distance; min_index = i; end end % 输出识别结果 fprintf('The number is %d\n', database{min_index}.label); ``` 以上代码中,`database`是一个保存了数字MFCC系数及标签的结构体数组,可以使用MATLAB自带的`save`函数保存到磁盘中。当需要识别一个新的数字时,计算它的MFCC系数,并遍历数据库中所有数字,计算它们与测试MFCC系数之间的距离并计算DTW距离,找到最小距离对应的数字标签即为识别结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值