人类交换信息最方便的、最快捷的一种方式是语言,在高度发达的信息社会中,用数字化的方法进行语音的识别、合成、增强、传送和储存等是整个数字化通信网中最重要、最基本的组成部分之一。数字电话通信、高音质的窄带语音通信系统、智能机器人、声控打字机、语言学习机、自动翻译机等,都要用到语音信号处理技术,随着现在集成电路和微电子技术的飞速发展,语音信号处理系统逐步走向实用化。[1]
语音信号处理是一个新兴的交叉学科,是语音和数字信号处理两个学科的结合产物。与认知科学、心理学、语言学、计算机科学、模式识别和人工智能学科有着密切的联系。语音信号处理技术的发展依赖于这些学科的发展,语音信号处理技术的进步也将促进这些领域的进展。
语音信号处理目的是得到一些语音特征参数,以便高效的传输或存储,或通过某种处理以达到特定目的,如语音合成,辨识出讲话者、识别出讲话的内容等。
随着现代科学技术和计算机技术的发展,除了人与人的自然语言的沟通,人机对话和智能机领域也开始使用语言。这些人造的语言拥有词汇,语法,语法结构和语义内容等。控制论创始人维纳在1950年曾经指出:“通常,我们把语言仅仅看做人与人之间的通信手段,但是,要使人向机器、机器向人及机器向机器讲话,那也是完全办得到的”[1],一般的语音信息交换大致可以分为三类:
①人与人之间的语音通信:它包括语音压缩与编码、语音增强等。
②第一类人机语言通信的问题,指机器讲话、人听话的研究,即语音合成。
③第二类人机语言通信的问题,指人讲话、机器听话的情况,即语音识别和理解。
上述这些应用程序构成的语音信号处理技术的主要内容。早在两千多年前,人们便进行了语言的学习。因为缺乏适当的设备,长期以来,一直由耳听和用口模仿来研究。因此,这种语言的研究通常被称为“口耳学校,所以对于语言仅仅停留在定性描述上。
语音信号处理的研究可以追溯到1876年贝尔电话的发明,其在真正意义上首次用声电,电声转换技术实现了远距离语音传输。 1939年Homer Dudley提出并研制成功第一个声码器,奠定了语音产生模型的基础。这项发明在语音信号处理领域具有划时代意义。 19世纪60年代,赫姆霍兹用声学的方法对元音和唱歌进行研究,奠定了基础语言的声学基础。在20世纪40年代,一种语言声学的专用仪器 – 语谱图仪问世。它可以让你把语音的时变频谱用语图表示出来,得到一个“可见的语言”。 1984年Haskins实验室研制成功“语音回放机,此仪器可以自动转换手工绘制的语谱图成为语言,并进行语音合成。在20世纪50年代对语言产生的声学理论有了系统描述。随着计算机的出现,语音分析技术可以在电子计算机上进行,在此基础上,语音信号处理无论是在基础研究或在技术应用,都已取得了突破性进展。以下讨论的语音信号的三个主要分支的发展和当前状态处理(语音合成,语音编码和语音识别技术)
语音合成技术,第一个合成器是在1835年由W.von Kempelen发,经过Weston改进的机械讲话机。机器完全模仿人的生理过程,分别应用了特别设计的哨和软管模拟肺部空气动力、模拟口腔。Homer Dudley在1939年发明了第一台电子语音合成器,它不是一个简单的生理过程的模拟,而是在电子电路基础上来实现语音产生源 – 滤波器理论。
语音编码的目的就是在保证一定语音质量的前提下,尽可能降低编码比特率,以节省频率资源。[1]语音编码技术的研究开始于1939年, Homer Dudley提出并实现了在低带宽电话电报上传输语音信号的通道声码器,第一个研制成功了语音编码技术。到20世纪70年代,国际电联于1972年发布了64kbit/s脉冲编码调制(PCM)语音编码算法的G.711建议,它被广泛应用于数字交换机、数字通信等领域,从而占据统治地位。在1995年11月ITU-T SG15全会上共轭代数码激励线性预测(CS-ACELP)的8kbit/s语音编码G.729建议被通过,并于1996年6月ITU-T SG15会议上通过G.729附件A:减少复杂度的8kbit/s CS-ACELP语音编解码器,正式成为国际标准。这几种语音编码算法也成为分组化语音通信的可选算法。[1]
语音识别的研究开始于20世纪50年代贝尔实验室的Audry系统,它是第一个可以识别10个英文数字的语音识别系统, 1959年Fry和Denes等人采用频谱分析和模式匹配来进行识别决策构建音素识别器来辨别9个辅音和4个元音。20世纪60年代末单语音识别的研究取得实质性进展,并将其作为一个重要的课题。一方面是因为计算机的计算能力有了迅速的提高,计算机能够提供实现复杂算法的硬件、软件;另一方面,数字信号处理在当时有了蓬勃发展,从而自20世纪60年代末开始引起了语音识别的研究热潮。动态规划(DP)和线性预测编码(LPC)分析技术就是在这时期提出的,其中线性预测编码较好地解决了语音信号产生模型的问题,对语音识别、语音合成、语音分析、语音编码的研究发展产生了重大的影响。
在20世纪70年代末和80年代初,Buzo、Linda、Gray等人解决了矢量量化码本生成的方法,并将应用到语音编码中,从此矢量量化技术很快被推广应用。从20世纪80年代开始,语音识别研究进一步深入,更多地追求从整体统计的角度来建立语音识别系统。HMM技术就是一个典型技术。在20世纪80年代末,美国卡内基梅陇大学用VQ/HMM实现997个词的非特定人连续语音识别系统SPHINX成为世界上第一个高性能的非特定人、大词汇量、连续语音识别系统。这些研究让语音识别进入了新时代。
通过采集大量语音信号的观察和分析,发现语音信号主要有下面两个特点:
①在频域内,语音信号的频谱分量主要集中在300Hz~3400Hz的范围之内。利用这个特点,可以用一个防混迭的带通滤波器将此范围内的语音信号频率分量取出,然后按8kHz的采样率对语音信号进行采样,就可以得到离散的语音信号。
②在时域内,语音信号具有“短时性”的特点,即在整体上,语音信号的特征是随着时间变化而变化的,但在一段较短的时间间隔内,语音信号保持平稳。在浊音段表现出信号的周期特性,在清音段表现出随机噪声的特征。
4 语音信号的处理
4.1语音信号分析技术
语音信号的分析是语音信号处理的基础和前提,语音通信、语音合成和语音识别这些技术只有在分析出可表示语音信号本质特征的参数,才能利用这些参数进行高效的处理。而且,语音信号分析的准确性和精确性也决定了语音合成的音质好坏。因此,在语音信号处理应用中语音信号分析具有十分重要的地位。
语音分析中使用到的是“短时时间分析技术”。之所以不能用处理平稳信号的数字信号处理技术对它进行分析,是因为语音信号的属性和特征是随时间变化而变化的,它是一个非平稳态的过程。然而,由于不同的语音由口腔肌肉通过运动产生的声音,口腔肌肉运动的频率相对声音频率反应是很慢的,所以另一方面,虽然声音信号有时变性,但在短期的时间内,它的基本特征保持不变,即是相对稳定的,因此,可以将语音信号看成是一个准稳态过程,即语音信号具有短时平稳特性。所以语音信号的分析和处理一般建立在短时的基础上,进行短时分析,将语音分成多段,每一段为一帧,帧长一般取10-30ms。这样,每一帧的语音信号为稳定的,然后将每一帧的分析结果组成一个整体即为整体的语音信号特征参数。[3]
根据分析参数的性质,语音信号分析划分成时域分析,频域分析,同态分析等,本文将简要介绍短时能量分析,短时自相关分析,AMDF方法提取基音周期,谱估计等。
4.2语音信号的时域分析
语音信号的时域分析是分析和提取语音信号的时域参数。语音分析时,第一次接触到的且也是最直观的是时域波形。语音信号本来就是时域信号,因此时域分析是最早的,也是最广泛使用的分析方法,这种方法是直接使用的语音信号时域波形。通常用于时域分析基本的参数分析,如语音分割,预处理,大型分类。这种分析方法的特点是:(1)表示语音信号更直观,清晰的物理意义。 (2)实施相对简单,运算少。 (3)可以得到一些语音的重要参数。(4)只使用一般的简单设备,如示波器。
语音信号时域参数包括短时能量,短时过零率,短时自相关函数和短时平均幅度差函数等等,这是一个基本的短时参数,在各种语音信号处理中都有重要的应用。
4.2.1 MATLAB的简单应用
在语音信号处理中将会用到MATLAB,MATLAB是一种功能强大、效率高、交互性好的数值计算和可视化计算机高级语言,通过MATLAB可以对数字化的语音信号进行时频域分析。通过MATLAB可以方便地展现语音信号的时域及频域曲线,并且根据语音的特性对语音进行分析。例如短时能量分析,短时自相关分析等,通过MATLAB也可以对数字化的语音信号进行估计和判别。例如AMDF法提取基音周期,谱估计等。
下面对一语音绘制其原始信号波形、原始信号频谱、原始信号幅值和原始信号相位,以此来简单介绍MATLAB的使用。(注:本文使用的是MATLAB 2009)
打开MATLAB,单击文件(File),选择新建选项(New),在右弹窗选择建立空白M文件(Blank M-File)如图4.1;
图4.1 MATLAB主界面
在打开的M文件里,将程序写入,注意输入法要用英文输入法。将程序写入后,单机保存按钮,选择要保存的文件夹,保存好后,单击Debug选择运行如图4.2
图4.2 MATLAB的M文件界面
运行后,若出现错误返回主界面找到错误的地方(Error in==>yuanshi at 4 magXabs(x);)表示第四行“magXabs(x);”语句错误如图4.3,单击后到M文件修改此语句为“magX=abs(x)”,调试后运行,得到最终结果。如图4.4
图4.3 程序错误时MATLAB的主界面
图4.4 语音信号分析结果
附录A 原始信号
[x,fs,bits]=wavread('zhuoyin',[1024 2120]);
sound(x,fs,bits);
X=fft(x,3096);
magX=abs(X);
angX=angle(X);
subplot(221);plot(x);title('原始信号波形');
subplot(222);plot(X); title('原始信号频谱');
subplot(223);plot(magX);title('原始信号幅值');
subplot(224);plot(angX);title('原始信号相位');
附录B 短时能量
x=wavread('beiyong.wav');
%计算N=50,帧移=50时的语音能量
s=fra(50,50,x) %对输入的语音信号进行分帧,其中帧长50,帧移50
s2=s.^2; %一帧内各样点的能量
energy=sum(s2,2) %求一帧能量
subplot(2,2,1) %定义画图数量和布局
plot(energy) %画N=50时的语音能量图
xlabel('帧数') %横坐标
ylabel('短时能量E') %纵坐标
legend('N=50') %曲线标识
axis([0,1500,0,40]) %定义横纵坐标范围
%计算N=100,帧移=100时的语音能量
s= fra(100,100,x)
s2=s.^2;
energy=sum(s2,2)
subplot(2,2,2)
plot(energy) %画N=100时的语音能量图
xlabel('帧数')
ylabel('短时能量')
legend('N=100')
axis([0,750,0,80]) %定义横纵坐标范围
%计算N=400,帧移=400时的语音能量
s=fra(400,400,x)
s2=s.^2;
energy=sum(s2,2)
subplot(2,2,3)
plot(energy) %画N=400时的语音能量图
xlabel('帧数')
ylabel('短时能量')
legend('N=400')
axis([0,190,0,200]) %定义横纵坐标范围
%计算N=800,帧移=800时的语音能量
s=fra(800,800,x)
s2=s.^2;
energy=sum(s2,2)
subplot(2,2,4)
plot(energy) %画N=400时的语音能量图
xlabel('帧数')
ylabel('短时能量')
legend('N=800')
axis([0,95,0,400]) %定义横纵坐标范围
%其中fra()为分帧函数,其MATLAB程序如下:
function f=fra(len,inc,x) %对读入语音分帧,len为帧长;inc为帧重样点数;x为
%输入语音数据
fh=fix(((size(x,1)-len)/inc)+1) %计算帧数
f=zeros(fh,len); %设一个零矩阵,行为帧数,列为帧长
i=1;n=1;
while i<=fh %帧间循环
j=1;
while j<=len %帧内循环
f(i,j)=x(n);
j=j+1;n=n+1;
end
n=n-len+inc; %下一帧开始位置
i=i+1;
end
附录C 短时自相关分析
x= wavread('zhuoyin.wav');
s1=x(1:320);
N=320; %选择的窗长,加N=320的矩形窗
A=[];
for k=1:320;
sum=0;
for m=1:N-(k-1);
sum=sum+s1(m)*s1(m+k-1); %计算自相关
end
A(k)=sum;
end
for k=1:320
A1(k)=A(k)/A(1); %归一化A(k)
end
N=160; %选择的窗长,%加N=160的矩形窗
B=[];
for k=1:320;
sum=0;
for m=1:N-(k-1);
sum=sum+s1(m+k-1); %计算自相关
end
B(k)=sum;
end
for k=1:320
B1(k)=B(k)/B(1); %归一化B(k)
end
N=70; %选择的窗长,加N=70的矩形窗
C=[];
for k=1:320;
sum=0;
for m=1:N-(k-1);
sum=sum+s1(m)*s1(m+k-1); %计算自相关
end
C(k)=sum;
end
for k=1:320
C1(k)=C(k)/C(1); %归一化C(k)
end
s2=s1/max(s1)
figure(1)
subplot(4,1,1)
plot(s2)
title('语音信号')
xlabel('样点数')
ylabel('幅值')
axis([0,320,-2,2])
subplot(4,1,2)
plot(A1)
xlabel('延时k')
ylabel('R(k)')
axis([1,320,-2,2]);
legend('N=320')
subplot(4,1,3)
plot(B1);
xlabel('延时k')
ylabel('R(k)')
axis([1,320,-2,2]);
legend('N=160')
subplot(4,1,4)
plot(C1);
xlabel('延时k')
ylabel('R(k)')
axis([0,320,-2,2]);
legend('N=70')
附录D AMDF法提取
b=wavread('zhuoyin.wav');
b1=b(1:640);
N=320;
A=[];
for k=1:320;
sum=0;
for m=1:N;
sum=sum+abs(b1(m)-b1(m+k-1));
end
A(k)=sum;
end
s=b(1:320)
figure(1)
subplot(2,1,1)
plot(s);
xlabel('样点')
ylabel('·幅度')
axis([0,320,-2*10^3,2*10^3])
subplot(2,1,2)
plot(A);
xlabel('延时k')
ylabel('AMDF')
axis([0,320,0,3.5*10^5])
附录E 功率谱估计
%直接法
Fs=8000; %采样频率
nFFT=10240;
n=0:1/Fs:1;
%产生含有噪声的序列改变n的取值范围观察图形的变换
x=wavread('zhuoyin.wav');
X=fft(x,nFFT);
Pxx=abs(X).^2/length(n);
t=0:round(nFFT/2-1);
k=t*Fs/nFFT;
P=10*log(Pxx(t+1));
plot(k,P);
%间接法
Fs=8000; %采样频率
nFFT=1023;
n=0:1/Fs:1;
%产生含有噪声的序列改变n的取值范围观察图形的变换
x=wavread('zhuoyin.wav');
Cx=xcorr(x,'unbiased');
Cxk=fft(Cx,nFFT);
Pxx=abs(Cxk);%求解PSD
t=0:round(nFFT/2-1);
k=t*Fs/nFFT;
P=10*log(Pxx(t+1)); %纵坐标的单位为dB
plot(k,P);
%Welch法
Fs=8000;
nfft=1024;
t=0:1/Fs:1;
xn=wavread('zhuoyin.wav');
X=fft(xn,nfft);
window=boxcar(100); %矩形窗
noverlap=20; %数据无重叠
[Pxx,f1]=pwelch(xn,window,noverlap,nfft,Fs);
PXX=10*log10(Pxx);
plot(f1,PXX);
title('矩形窗');
xlabel('频率(Hz)');
ylabel('功率谱(dB)');