语音信号分帧以后,可以在时域中处理,也可以在频域中处理。这里主要介绍时域处理中提取语音信号的特性。
设语音波形时域信号为
、加窗函数
分帧处理后得到的第i帧语音信号为
,则
满足:
式中, 为窗函数,一般为矩形窗或汉明窗; 是一帧的数值, , 为帧长;inc为帧移长度;fn为分帧后的总帧数。
1、短时能量
计算第i帧语音信号
的短时能量公式为
具体代码如下:
% 短时能量
filedir=[]; % 设置路径
filename='F:\音频\wav\MORSE.wav'; % 设置文件名
fle=[filedir filename]; % 构成完整的路径和文件名
[x,Fs]=wavread(fle); % 读入数据文件
wlen=200; inc=80; % 给出帧长和帧移
win=hanning(wlen); % 给出海宁窗
N=length(x); % 信号长度
X=enframe(x,win,inc)'; % 分帧
fn=size(X,2); % 求出帧数
time=(0:N-1)/Fs; % 计算出信号的时间刻度
for i=1 : fn
u=X(:,i); % 取出一帧
u2=u.*u; % 求出能量
En(i)=sum(u2); % 对一帧累加求和
end
subplot 211; plot(time,x); % 画出时间波形
title('MORSE语音波形');
ylabel('幅值'); xlabel(['时间/s' 10 '(a)']);
frameTime=frame2time(fn,wlen,inc,Fs); % 求出每帧对应的时间
subplot 212; plot(frameTime,En) % 画出短时能量图
title('短时能量');
ylabel('幅值'); xlabel(['时间/s' 10 '(b)']);
运行程序后求出的短时能量图如图所示:
附: 程序中调用了frame2time函数,用于计算分帧后每一帧对应的时间。具体代码如下:
function frameTime=frame2time(frameNum,framelen,inc,fs)
% 分帧后计算每帧对应的时间
frameTime=(((1:frameNum)-1)*inc+framelen/2)/fs;
2、短时平均过零率
短时平均过零率表示一帧语音中语音信号波形穿过横轴(零点平)的次数。对于联系语音信号,过零即意味着时域波形通过时间轴;而对于离散信号,如果相邻的取样值改变符号,则称为过零。短时平均过零率就是样本数值改变符号的次数。
短时平均过零率为
式中,
是符号函数,即
理论上短时平均过零率是按上式计算,而在MATLAB编程中,却用另一种方法。按上述过零的描述,即离散信号相邻的取样值改变符号,那它们的乘积一定为负数,即
具体代码如下:
%短时平均过零率
filedir=[]; % 设置路径
filename='F:\音频\wav\MORSE.wav'; % 设置文件名
fle=[filedir filename]; % 构成完整的路径和文件名
[xx,Fs]=wavread(fle); % 读入数据文件
x=xx-mean(xx); % 消除直流分量
wlen=200; inc=80; % 设置帧长、帧移
win=hanning(wlen); % 窗函数
N=length(x); % 求数据长度
X=enframe(x,win,inc)'; % 分帧
fn=size(X,2); % 获取帧数
zcr1=zeros(1,fn); % 初始化
for i=1:fn
z=X(:,i); % 取得一帧数据
for j=1: (wlen- 1) ; % 在一帧内寻找过零点
if z(j)* z(j+1)< 0 % 判断是否为过零点
zcr1(i)=zcr1(i)+1; % 是过零点,记录1次
end
end
end
time=(0:N-1)/Fs; % 计算时间坐标
frameTime=frame2time(fn,wlen,inc,Fs); % 求出每帧对应的时间
% 作图
subplot 211; plot(time,x); grid;
title('MORSE语音波形');
ylabel('幅值'); xlabel(['时间/s' 10 '(a)']);
subplot 212; plot(frameTime,zcr1); grid;
title('短时平均过零率');
ylabel('幅值'); xlabel(['时间/s' 10 '(b)']);
运行程序后求出的短时平均过零率如图所示: