【Matlab】PCM语音编解码
一.绪论
1.1 研究背景
??随着信息技术的快速发展,现代通信技术,尤其是语音信号处理技术,在日常生活中得到了广泛的应用。压缩编码技术是语音信号处理过程中非常重要的环节,可分为波形编码、参数编码和混合编码三类。脉冲编码调制(即脉冲编码)PCM,Pluse Code Modulation)波形编码在语音信号处理过程中应用最广泛,是数字通信系统发展的飞跃。
1.2 PCM技术研究现状
??脉冲编码调制的概念是1937年法国工程师AlecReeres最早提出的。随着集成电路技术的快速发展,超大型集成电路PCM编辑和解码器的出现使其在光纤通信、数字微波通信、卫星通信、信号处理、军事和民用电子技术领域发挥着越来越重要的作用。
??PCM 即脉冲编码调制 (Pulse Code Modulation)。在PCM 在此过程中,采样、量化和编码输入的模拟信号,代表模拟信号的范围 ;接收器将这些代码还原为原始模拟信号。即数字音频 A/D 转换包括三个过程 :采样、量化、编码。
??话音PCM抽样频率为8kHz,每个量化样值对应8位二进制码,因此语音数字编码信号的速率为8bits×8kHz=64kbps = 8kb/s。随着量化级数的增加和级差的缩小,量化噪声降低。量化级数增加,即样值数增加,需要更长的二进制编码。因此,随着二进制编码位数的增加,量化噪声降低,即随着数字编码信号速率的提高。
??自然界中的声音非常复杂,波形非常复杂,所以我们经常使用脉冲代码调制代码,即PCM编码。在计算机应用中,能达到最高保真水平的是PCM编码。需要注意的是,PCM约定俗成无损编码,因为PCM代表数字音频中最好的保真水平,并不意味着PCM确保信号绝对保真,PCM只有最大限度的无限接近。
??目前PCM编码广泛应用于通信、计算机、数字仪表、遥控遥测等领域,其应用广度和深度也在不断扩大和深化。随着全球数字化和信息化的不断发展,脉冲编码调制将有更好的发展和应用前景。
1.3 研究内容
??本设计针对PCM探讨编解码及其特点,并以编解码为基础MATLAB对PCM通信系统进行仿真,其研究内容主要有以下几个部分: ??①利用Matlab编写PCM编解码相关函数程序,并调用PCM编解码函数以正弦波和三种不同的语音信号(锣声、哈利路亚、笑声)为输入信号,实现模拟和验证PCM编解码的正确性。 ??②采用Matlab中的Simulink进行PCM编解码模拟、噪声影响和性能分析。 ??③采用GUI语音输入完成界面操作,PCM编码,PCM解码、语音还原输出等一系列操作。
二. PCM编解码的基本原理
2.1 PCM语音编码原理
??通常,我们将从模拟信号抽样、量化到转换为二进制符号的基本过程称为脉冲编码调制和脉冲编码调制。PCM编码过程实际上是抽样-量化-编码语音信号的过程。它是将模拟信号转换为二进制信号的常用方法。PCM编码的具体步骤如下: ??1)根据信号本身的频率特征(如正弦信号根据采样定理以信号带宽2倍以上的频率提取抽样值,语音信号根据其自身的频率Fs,为了准确表示信号,通常需要保留10kHz以下频谱成分,G.711标准中规定PCM抽样频率为8kHz)进行抽样 ??2)量化模拟信号的每个抽样值,其本质是用数字量来表示时域中离散的每个抽样值。在这个过程中,量化精度会产生量化误差,量化精度越高,自然量化误差越小。常用的量化方法有两种:均匀量化和不均匀量化。 ??由于量化器信噪比公式均匀量化(S/N)=M由此可见,随着量化电平数M的增加,量化器的信噪比显著提高。当输入小信号时,量化间隔会变小,量化噪声的平均功率会变小。此时,小信号的量噪比难以满足要求;由于语音信号中小电压的可能性较大,且不均匀量化噪声对大小信号的影响大致相同,因此,采用不均匀量化来提高语音信号中小信号的量噪比。
??在PCM语音编码主要是先压缩抽样值,然后均匀量化,实现不均匀量化,通常采用8位PCM编码来保证PCM编解码系统的通信质量。
??在本实验中,我们选择15折线压缩律进行实验。μ法律压缩特性由下表示: ??对上式做一些修正。μ修正后的表达式如下: ??从上面的风格可以看出:满足当 x = 0时,y = 0;当x = 1时,y = 1.然而,在其他方面自然存在一些误差。然而,只有小电压(x < 只有在1/128,才会有轻微的误差。通常使用参数。μ表示上式常数255。其特征曲线如下图2-1所示:
??15折线律中使用的折叠码与13折线律相同。其中第一位c1表示量化值的极性正负。后七位分为段落码和段内码两部分,用于表示量化值的绝对值。其中第2至4位(c2 c3 c4)是段落代码,共3位,可以表示8个斜率段落;其他4位(c5 ~ c8)为段内码,可表示每段16种量化电平。段内代表的16个量化电平均匀划分。
??因此,这7位码总共可以表示27 = 128种量化值。段落码和段内码的编码规则在下表2-1中给出。
??在上述编码方法中,虽然段内代码按量化间隔均匀编码,但由于每段的斜率和长度不同,不同段落的量化间隔也不同。其中,第一段和第二段最短,斜率最大,横坐标x的归一动态范围仅为1/128。将其分为16段后,每段的动态范围仅为(1/128) * (1/16) = 1/2048。
??这是最小量化间隔,后来称为最小量化间隔(1/2048)为一个量化单位。第八段最长,横坐标x的动态范围为1/2。等分16后,每段长度为1/32。如果使用均匀量化,仍希望对小电压保持相同的动态范围,则需要使用11位码组。现在不均匀量化只需要7位。
??如下图2-2所示PCM编码原理框图,首先通过冲激脉冲对编码器中的模拟信号进行抽样,在抽样时得到信号抽样值。抽样值仍然是模拟量。在它量化之前,通常用保持电路将其作短暂保存,以便电路有时间对其进行量化。在实际电路中,抽样和保持电路常被称为抽样保持电路。图中的量化器将模拟抽样信号转换为离散数字,然后在编码器中进行二进制编码。这样,每个二进制码组都代表一个量化的信号抽样值。
??常用的编码方法有逐步比较等。常用的二进制码有天然二进制码和折叠二进制码。
2.2 PCM语音解码原理
??接收端实现PCM解码原理框图如图2-3所示,其主要原理是逐步比较A/D转换。
??输入本地译码器的记忆电路c7值后,恒流源产生下次比较所需的权值电流Iw。输出编码器c8值后,抽样值的编码已经完成,因此比较器需要等待下一个抽样值到达,不需要恒流源产生新的权值电流。本地译码器部分仍保留在接收端的译码器中。
??由记忆电路接收发送的码组。当记忆电路接收码组的最后一个时c8后,恒流源产生另一个权值电流,相当于最后一个间隔的中间值。由于编码器中的比较器只是抽样的绝对值,当地的翻译器只产生正值电流,因此在接收器的翻译中,最后一步是基于接收码组的第一个c1值控制输出电流的正负极性。可获得接收端PCM语音解码。
三.软件设计
3.1信号产生与采样
信号产生与采样部分的代码如图3-1所示(正弦波),此处以正弦波为例是为了方便进行PCM编解码正确性的验证。由奈奎斯特采样定理可知该信号的采样频率要大于4000Hz。根据上述原理可知此处选取的信号采样频率为8000Hz,代码和信号采样前后对比如图3-2所示。max函数的作用是用来计算信号采样后各个幅度的极值,为之后PCM编码过程中的量化做准备。
3.2 PCM编码
PCM编码的程序设计采用调用PCM编码函数的方法来实现。该编码函数分为三个部分:采样信号的量化,段落码判断和段内码判断,并且此处采用的压缩律为美国和日本地区所通用的μ-15折线律,先将其分为255个量化区间并采用8位编码,其中从左至右第一位表示采样信号的正负,第二位至第四位表示采样信号处于15折线律的哪一段上,为段落码;第五位至第八位为段内码,用于表示在该段16个量化区间中的位置,每一段的量化间隔分别为分别1/16,1/8,1/4,1/2,1,2,4,8。这三个部分的函数分别如图图3-4,图3-5及图3-6所示。通过如图3-7所示程序调用,结果如图3-8所示。
3.3 PCM解码
根据PCM解码的相关原理,可以得到该部分的程序框图如图3-9所示,其中相对幅度即还原后抽样信号的幅值与所有抽样信号的幅值的最大值之比,从而可设计出PCM解码函数如图3-10所示,调用代码如图3-11所示,解码效果图如图3-12所示。
由PCM译码的波形和原始信号波形的对比可以看出,运用μ-15折线律作为压缩律对原始信号进行PCM编解码的还原度还是比较高的。
3.4 PCM编解码的Simulink实现
由PCM编解码原理,可设计出如图3-13所示的PCM编解码系统。
在图3-13中,我们以一个非周期性正弦波chirp为例,先对该波进行量化,然后将量化后的信号通过对其进行编码,译码和解码,并设置其采样8位2进制编码和解码,随后将解码过后的信号通过一个低通滤波器,滤除其中的高频噪声,从而对原来量化过后的信号进行还原。
3.5 PCM编解码的GUI实现
此处采用GUI界面操作完成语音输入,PCM编码,PCM解码,语音还原输出,界面如图3-18所示,该系统可以使用弹出式菜单分别进行三种不同种类语音:锣声,哈利路亚和笑声的输入,并通过PCM编解码对其进行还原输出,三种不同种类语音输入与语音还原输出后的对比图如图3-19,图3-20和图3-21所示。
四.性能分析
4.1 具体信号分析
此处主要对正弦还原信号进行失真度分析的测试,如图4-1所示。可得到失真度的大小为0.002030(如图4-2所示),说明对应具体信号而言,PCM编解码后的输出信号还原度较高。
4.2 语音信号分析
根据图3-19所示程序,同样可以得到三个语音信号(在采样个数相同的条件下)分别为0.0054,0.0048和0.0044,说明语音信号的PCM编解码输出信号还原度比单频信号要略低。
附录代码:
采用美国,日本地区标准的μ-15折线律作为PCM编码的压缩律 .m文件说明: 编解码函数: PCMcode,PCMdecode 运行顺序: project3_1 project3_2 project3_3 project3_4 推荐直接GUI操作 PROJECT3GUI.m是设计GUI界面的,直接点PROJECT3GUI.fig就好了 注:simulink.slk是2018版的matlab编写的,要运行的话需要用2018以上的matlab版本
编码函数(PCMcode.m)
function code=PCMcode(S) z=sign(S); %判断S的正负 MaxS=max(abs(S)); %求S的最大值 S=abs(S/MaxS); %归一化 Q=255*S; %量化 code=zeros(length(S),1); %代码存储
矩阵(全零) % 段落码判断程序 for i=1:length(S) if (Q(i)>=15)&&(Q(i)<=255) code(i,2)=1; %在第五段与第八段之间,段位码第一位都为"1" end if (Q(i)>3)&&(Q(i)<15)||(Q(i)>=63)&&(Q(i)<=255) code(i,3)=1; %在第三四七八段内,段位码第二位为"1" end if (Q(i)>=1)&&(Q(i)<3)||(Q(i)>=7)&&(Q(i)<15)||(Q(i)>=31)&&(Q(i)<63)||(Q(i)>=127)&&(Q(i)<=255) code(i,4)=1; %在二四六八段内,段位码第三位为"1" end end N=zeros(length(S)); %段内码判断程序 for i=1:length(S) N(i)=bin2dec(num2str(code(i,2:4)))+1; %找到code位于第几段 end a=[0,1,3,7,15,31,63,127]; %量化间隔 b=[1/16,1/8,1/4,1/2,1,2,4,8]; %除以16,得到每段的最小量化间隔 for i=1:length(S) q=ceil((Q(i)-a(N(i)))/b(N(i))); %求出在段内的位置 if q==0 code(i,(5:8))=[0,0,0,0]; %如果输入为零则输出"0" else k=num2str(dec2bin(q-1,4)); %编码段内码为二进制 code(i,5)=str2num(k(1)); code(i,6)=str2num(k(2)); code(i,7)=str2num(k(3)); code(i,8)=str2num(k(4)); end if z(i)>0 code(i,1)=1; elseif z(i)<0 code(i,1)=0; end %符号位的判断 end code = reshape(code', 1, []); end
解码函数(PCMdecode.m)
function s=PCMdecode(encode, max)
encode=(reshape(encode',8,length(encode)/8))';
l=size(encode,1);
a=[0,1,3,7,15,31,63,127];
b=[1/16 1/8 1/4 1/2 1 2 4 8];
c=[0 1.5:15.5];
for i=1:l
x=encode(i,1);
T=bin2dec(num2str(encode(i,(2:4))))+1;
Y=bin2dec(num2str(encode(i,(5:8))));
if Y==0
k(i)=a(T)/255;
else
k(i)=(a(T)+b(T)*c(Y))/255;
end
if x==0
s(i)=-k(i);
else
s(i)=k(i);
end
end
s = s*max;
end
信号采样(project3_1.m)
clear;clc;
T=0.0005;
t=-0.01:T:0.01;
fs=8000; %取采样频率为8000Hz
sdt=1/fs;
t1=-0.01:sdt:0.01;
xt=cos(2*pi*30*t)+sin(2*pi*120*t);
st=cos(2*pi*30*t1)+sin(2*pi*120*t1);
maximum = max(abs(st));
% 原始信号
figure;
subplot(2,1,1);plot(t,xt);title('原始信号');grid on;
subplot(2,1,2);stem(t1,st,'.');title('抽样信号');grid on;
PCM编码(project3_2.m)
pcm_encode = PCMcode(xt);
figure;
stairs(pcm_encode);
axis([0 200 -2 2]);
title('PCM 编码');
grid on;
PCM解码(project3_3.m)
pcm_decode = PCMdecode(pcm_encode, maximum);
figure;
subplot(2,1,1);plot(t, pcm_decode);
title('PCM 译码');grid on;
subplot(2,1,2);plot(t,xt);
title('原始信号');grid on;
结果分析(project3_4.m)
da=0;
for i=1:length(t)
dc=(xt(i)-pcm_decode(i))^2/length(t);
da=da+dc;
end
fprintf('失真度是:%.6f\n',da);
GUI(PROJECT3GUI.m)
完整工程文件后续会上传到博客资源当中。