这篇文章上次修改于 431 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

首先使用MATLAB(或octave)提取一段录音,代码如下:

close all
clear all
clc
t=5;%录音时长
fs=8000;%采样频率
Nbit=16;%bit数
Nchan=2;%通道数
myvoice=audiorecorder(fs,Nbit,Nchan);
disp('开始录音,按任意键开始')
pause
recordblocking(myvoice,t);
disp('录音结束');
play(myvoice);
myRecording=getaudiodata(myvoice);
plot(myRecording);
audiowrite('mvoice.wav',myRecording,fs);

采集时长5s的任意语音信号,对该语音信号进行分析处理,提取的特征参数主要有语音的短时能量和平均幅度等。
接下来,我们载入该语音信号,并对其加窗处理,常用的窗有矩形窗、汉宁窗和汉明窗等。参考这里,在MATLAB中已经为我们提供了简单的加窗函数:

clc;clear;
[x,fs]=wavread('文件路径\mvoice.wav');%根据版本不同使用audioread或wavread
N=256;%窗口长度
ws=window('rectwin',N);%定义各个窗
w1=window('hamming',N);
w2=window('hanning',N);
wvtool(ws,w1,w2)

原始的语音信号图如下:
_A1Y5MWO3`__7R2EWCD9GQA.png

加窗之后,通过wvtool工具可以看出此时加不同窗的时域和频域特性:
123.png

接下来我们提取语音信号的短时平均能量:

ste=64;%窗移动的步长
x=x'%信号转置
ns1=[];mans1=[];
for i=1:ste:(length(x)-N)
    ns1=[ns1;x(i:i+N-1)];%将数据分段取出再赋值
end
energy=[];energyhm=[];energyhn=[];energyre=[];
for i=1:size(ns1,1)
    energy=[energy;sum((ns1(i,:)).^2)];%计算此时这个数据段的能量
end
for i=1:size(ns1,1)
    energyhm=[energyhm;sum((ns1(i,:).*w1').^2)];%加汉明窗
end
for i=1:size(ns1,1)
    energyhn=[energyhn;sum((ns1(i,:).*w2').^2)];%加汉宁窗
end
for i=1:size(ns1,1)
    energyre=[energyre;sum((ns1(i,:).*ws').^2)];%加矩形窗
end
figure(4)
subplot(3,1,1),plot(energyre),title('矩形窗');
subplot(3,1,2),plot(energyhm),title('汉明窗');
subplot(3,1,3),plot(energyhn),title('汉宁窗');

如上所示,可以看出此时加了三个不同窗的短时平均能量图:
111777.png


提取语音信号的平均幅度:

%计算短时平均幅度
for i=1:ste:(length(x)-N)
    ns1=[ns1;x(i:i+N-1)];
end
am=[];amhm=[];amre=[];amhn=[];
for i=1:size(ns1,1)
    am=[am;sum(abs(ns1(i,:)))];
end
for i=1:size(ns1,1)
    amhm=[amhm;sum(abs(ns1(i,:).*w1'))];
end
for i=1:size(ns1,1)
    amhn=[amhn;sum(abs(ns1(i,:).*w2'))];
end
for i=1:size(ns1,1)
    amre=[amre;sum(abs(ns1(i,:).*ws'))];
end
figure(5)
subplot(3,1,1),plot(amre),title('矩形窗');
subplot(3,1,2),plot(amhm),title('汉明窗');
subplot(3,1,3),plot(amhn),title('汉宁窗');

效果如图:
12222231.png

最后,将语音信号通过一个一阶高通滤波器1-0.95Z,进行预加重:

%预加重
clc;clear;
[x,fs]=audioread('文件路径\mvoice.wav');
len=256;
ste=128;
y=enframe(x,len,ste);
z=filter([1-0.9375],1,y);
figure
subplot(2,1,1),plot(y)
subplot(2,1,2),plot(z)

预加重效果如图所示:
9332.png

后记:在MATLAB里要尽量避免使用循环类语句,可以参考这种使用向量,不用for循环的方法,可以提高效率。


附录:这里给出enframe脚本文件的代码

function f=enframe(x,win,inc)
%ENFRAME split signal up into (overlapping) frames: one per row. F=(X,WIN,INC)


nx=length(x);
nwin=length(win);
if (nwin == 1)
   len = win;
else
   len = nwin;
end
if (nargin < 3)
   inc = len;
end
nf = fix((nx-len+inc)/inc);
f=zeros(nf,len);
indf= inc*(0:(nf-1)).';
inds = (1:len);
f(:) = x(indf(:,ones(1,len))+inds(ones(nf,1),:));
if (nwin > 1)
    w = win(:)';
    f = f .* w(ones(nf,1),:);
end

enframe是语音分帧函数,一般调用格式为y=enframe(x,length,step);对x进行分帧,每帧长度为length,step是指一帧与一帧之间移动的样点数,也就是步长。