目录
- MATLAB——PCM编译码
- 一、实验原理
- 1.掌握PCM编码原理和译码原理
- 2. 练习使用Matlab编程实现PCM编码和译码
- 3. 了解失真度的概念,能对译码结果进行失真度分析
- 二、实验原理
- 三、实验要求
- 1、用Matlab产生一模拟信号,如: 或者自己编写一信号,或者找某一语音信号……。
- 2、在满足抽样定理要求下,对该信号进行抽样,用Matlab编程实现,画出抽样信号,并与原信号进行对比。
- 3、对抽样信号进行PCM编码,用Matlab编程实现,画出编码波形(矩形脉冲、单极性不归零),并标出某个抽样值的8位编码结果。
- 4、对经信道传输得到的PCM编码进行PCM解码,用Matlab编程实现,并画出解码波形。
- 5、对解码结果进行失真度分析。
- 6、(扩展练习)采用PCM编码,2PSK结合simulink实现语音信号(可使用Matlab自带的语音信号)的传输仿真。
- 四、实验内容
- 4.1用Matlab产生一模拟信号
- 4.2画出抽样信号,并与原信号进行对比
- 4.3对抽样信号进行PCM编码
- 4.4 PCM解码
- 4.5失真度分析
- 4.6 simulink实现语音信号的传输仿真
- 五、引用
MATLAB——PCM编译码
一、实验原理
1.掌握PCM编码原理和译码原理
2. 练习使用Matlab编程实现PCM编码和译码
3. 了解失真度的概念,能对译码结果进行失真度分析
二、实验原理
脉冲编码调制就是把一个时间连续,取值连续的模拟信号变换成时间离散,取值离散的数字信号后在信道中传输。脉冲编码调制就是对模拟信号先抽样,再对样值幅度量化,编码的过程。
抽样,就是对模拟信号进行周期性扫描,把时间上连续的信号变成时间上离散的信号,抽样必须遵循奈奎斯特抽样定理。该模拟信号经过抽样后还应当包含原信号中所有信息,也就是说能无失真的恢复原模拟信号。它的抽样速率的下限是由抽样定理确定的。
量化,就是把经过抽样得到的瞬时值将其幅度离散,即用一组规定的电平,把瞬时抽样值用最接近的电平值来表示,通常是用二进制表示。
量化误差,量化后的信号和抽样信号的差值。量化误差在接收端表现为噪声,称为量化噪声。 量化级数越多误差越小,相应的二进制码位数越多,要求传输速率越高,频带越宽。 为使量化噪声尽可能小而所需码位数又不太多,通常采用非均匀量化的方法进行量化。 非均匀量化根据幅度的不同区间来确定量化间隔,幅度小的区间量化间隔取得小,幅度大的区间量化间隔取得大。一个模拟信号经过抽样量化后,得到已量化的脉冲幅度调制信号,它仅为有限个数值。
编码,就是用一组二进制码组来表示每一个有固定电平的量化值。然而,实际上量化是在编码过程中同时完成的,故编码过程也称为模/数变换,可记作A/D。
为解决均匀量化时小信号量化误差大,音质差的问题,在实际中采用不均匀选取量化间隔的非线性量化方法,即量化特性在小信号时分层密,量化间隔小,而在大信号时分层疏,量化间隔大。在实际中使用的是两种对数形式的压缩特性:A律和μ律。
三、实验要求
1、用Matlab产生一模拟信号,如: 或者自己编写一信号,或者找某一语音信号……。
2、在满足抽样定理要求下,对该信号进行抽样,用Matlab编程实现,画出抽样信号,并与原信号进行对比。
3、对抽样信号进行PCM编码,用Matlab编程实现,画出编码波形(矩形脉冲、单极性不归零),并标出某个抽样值的8位编码结果。
4、对经信道传输得到的PCM编码进行PCM解码,用Matlab编程实现,并画出解码波形。
5、对解码结果进行失真度分析。
6、(扩展练习)采用PCM编码,2PSK结合simulink实现语音信号(可使用Matlab自带的语音信号)的传输仿真。
四、实验内容
4.1用Matlab产生一模拟信号
t=0:1/2000:0.1;
f=cos(100*pi*t)+2*sin(200*pi*t)+3*cos(300*pi*t);
plot(t,f);
xlabel('t');
title('f(t)的时域波形');
4.2画出抽样信号,并与原信号进行对比
clear;
clc;
T=0.0005;
t=-0.05:T:0.05;
fs=2000;
sdt=1/fs;
t1=-0.05:sdt:0.05;
% 原始信号
f=cos(100*pi*t)+2*sin(200*pi*t)+3*cos(300*pi*t);
%抽样信号
fs=cos(100*pi*t1)+2*sin(200*pi*t1)+3*cos(300*pi*t1);
figure;
subplot(2,1,1);plot(t,f);title('原始信号');grid on;
subplot(2,1,2);stem(t1,fs,'.');title('抽样信号');grid on;
4.3对抽样信号进行PCM编码
% 原始信号
f=cos(100*pi*t)+2*sin(200*pi*t)+3*cos(300*pi*t);
%抽样信号
fs=cos(100*pi*t1)+2*sin(200*pi*t1)+3*cos(300*pi*t1);
max = max(abs(fs));
% 原始信号
figure;
subplot(2,1,1);plot(t,f);title('原始信号');grid on;
subplot(2,1,2);stem(t1,fs,'.');title('抽样信号');grid on;
pcm_encode = PCMcoding(fs);
figure;
stairs(pcm_encode);%绘制信号的阶梯图
axis([0 328 -0.1 1.1]);
title('PCM 编码');axis([0 168 -0.1 1.1]);
set(gca,'xtick',[ 1 9 17 25 33 41 49 57 168]);
xticklabels({'1','9','17','25','33','41','49','57','168'})
grid on;
function code=PCMcoding(S)
z=sign(S); %判断S的正负
MaxS=max(abs(S)); %求S的最大值
S=abs(S/MaxS); %归一化
Q=2048*S; %量化
code=zeros(length(S),8); %PCM编码存储矩阵
%%
% 段落码判断程序
for i=1:length(S)
if (Q(i)>128)&&(Q(i)<=2048)
code(i,2)=1; %在第五段与第八段之间,段位码第一位都为"1"
end
if (Q(i)>32)&&(Q(i)<=128)||(Q(i)>512)&&(Q(i)<=2048)
code(i,3)=1; %在第三四七八段内,段位码第二位为"1"
end
if (Q(i)>16)&&(Q(i)<=32)||(Q(i)>64)&&(Q(i)<=128)||(Q(i)>256)&&(Q(i)<=512)||(Q(i)>1024)&&(Q(i)<=2048)
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位于第几段,bin2dec将二进制整数的文本表示转换为双精度值,
end
a=[0,16,32,64,128,256,512,1024]; %13折线各段起始对应的量化单位数
b=[1,1,2,4,8,16,32,64]; %除以16,得到每段的最小量化间隔
for i=1:length(S)
q=ceil((Q(i)-a(N(i)))/b(N(i))); %求出在段内的位置,ceil将 X 的每个元素四舍五入到大于或等于该元素的最接近整数
if q==0
code(i,(5:8))=[0,0,0,0]; %如果输入为零则输出"0"
else k=dec2bin(q-1,4); %将字符数组或字符串转换为数值数组,编码段内码为二进制,dec2bin将十进制整数转换为其二进制表示字符向量
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
我们选取观察的点是模拟信号中负值最大的点,同时也是抽样信号的第5个点。它的PCM编码结果应该是0111 1111,我们打开Workbench中pcm_encode,观察第33~40位。发现编码结果确实是0111 1111,符合编码逻辑,证明代码编写无误。
4.4 PCM解码
function s=PCMdecoding(encode, max)
encode=(reshape(encode',8,length(encode)/8))';
l=size(encode,1);
a=[0,16,32,64,128,256,512,1024];
b=[1 1 2 4 8 16 32 64];
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)/2048;
else
k(i)=(a(T)+b(T)*c(Y))/2048;
end
if x==0
s(i)=-k(i);
else
s(i)=k(i);
end
end
s = s*max;
end
通过原始信号与PCM编码译码后的对比可以看到能够比较好地重建出原始信号。通过下图能够更好得出对比的效果。
4.5失真度分析
figure;
subplot(2,1,1);plot(t,f);title('原始信号');grid on;
subplot(2,1,2);stem(t1,fs,'.');title('抽样信号');grid on;
pcm_encode = PCMcoding(fs);
pcm_decode = PCMdecoding(pcm_encode, max);
figure;
plot(t, pcm_decode);hold on
title('PCM 译码');grid on;
plot(t,f);
title('原始信号');grid on;
% 计算失真度
da=0;
for i=1:length(t)
dc=(f(i)-pcm_decode(i))^2/length(t);
da=da+dc;
end
fprintf('失真度是:%.6f\n',da);
失真度我们认为是前后信号之间的均方误差,经过计算得到为:
失真度是:0.010716
4.6 simulink实现语音信号的传输仿真
首先我设计了一个2psk的编码模块,可以将单极性基带二进制码转换为2PSK信号。从Scope模块中我们可以得到Bernoulli Binary模块生成的随机二进制基带信号生成的2PSK波形,验证模块的正确性。
接下来我将之前编写的PCM编码和解码模块和2PSK模块结合起来,模拟语音信号编码、传输和解码过程。我使用了MATLAB自带的语音包crisp,可以发出鸟鸣的声音。
接下来我将之前编写的PCM编码和解码模块和2PSK模块结合起来,模拟语音信号编码、传输和解码过程。语音信号的选择我使用了MATLAB自带的语音包crisp,可以发出鸟鸣的声音。
load chirp % matlab自带语音信号
y1=[y,y];
x=y1(1:20000); %取前20000个采样点
sound(x,Fs);
接下来就是将语音信号进行传输的Simulink仿真了,simout就是经过传输的语音信号,但注意这是pcm八进制编码的形式,必须要进行解码,同时和原信号进行对比,验证传输的正确性。
%% 译码
demodata=simout(2:160001);
zz=pcm_decode(demodata,0.8);
figure;
subplot(1,1,1);
plot(zz);
title('译码的语音信号');
sound(zz,Fs);
%x是初始的语音信号矩阵
figure;
plot(x,'b');
hold on
%zz是译码得到的语音信号
plot(zz,'r');
legend('原语音信号','恢复的语音信号');
title('语音信号对比');
五、引用
[1]邢巨伟.模拟信号的数字化传输-PCM编码[J].黑龙江科技信息,2014(33):116.
[2]陈奎.语音PCM编码通信系统的SIMULINK仿真[J].福建电脑,2012,28(10):115-117.
[3]赵守彬,李鸿刚.利用Matlab实现PCM编码的A律13折线法量化[J].科技信息,2009(36):547.