MATLAB——PCM编译码实验

目录

  • 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. 了解失真度的概念,能对译码结果进行失真度分析

二、实验原理

脉冲编码调制就是把一个时间连续,取值连续的模拟信号变换成时间离散,取值离散的数字信号后在信道中传输。脉冲编码调制就是对模拟信号先抽样,再对样值幅度量化,编码的过程。

抽样,就是对模拟信号进行周期性扫描,把时间上连续的信号变成时间上离散的信号,抽样必须遵循奈奎斯特抽样定理。该模拟信号经过抽样后还应当包含原信号中所有信息,也就是说能无失真的恢复原模拟信号。它的抽样速率的下限是由抽样定理确定的。
在这里插入图片描述

量化,就是把经过抽样得到的瞬时值将其幅度离散,即用一组规定的电平,把瞬时抽样值用最接近的电平值来表示,通常是用二进制表示。

量化误差,量化后的信号和抽样信号的差值。量化误差在接收端表现为噪声,称为量化噪声。 量化级数越多误差越小,相应的二进制码位数越多,要求传输速率越高,频带越宽。 为使量化噪声尽可能小而所需码位数又不太多,通常采用非均匀量化的方法进行量化。 非均匀量化根据幅度的不同区间来确定量化间隔,幅度小的区间量化间隔取得小,幅度大的区间量化间隔取得大。一个模拟信号经过抽样量化后,得到已量化的脉冲幅度调制信号,它仅为有限个数值。
MATLAB——PCM编译码实验_第1张图片

MATLAB——PCM编译码实验_第2张图片

编码,就是用一组二进制码组来表示每一个有固定电平的量化值。然而,实际上量化是在编码过程中同时完成的,故编码过程也称为模/数变换,可记作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)的时域波形');

MATLAB——PCM编译码实验_第3张图片

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;

MATLAB——PCM编译码实验_第4张图片

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

MATLAB——PCM编译码实验_第5张图片
MATLAB——PCM编译码实验_第6张图片
MATLAB——PCM编译码实验_第7张图片
我们选取观察的点是模拟信号中负值最大的点,同时也是抽样信号的第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

MATLAB——PCM编译码实验_第8张图片
通过原始信号与PCM编码译码后的对比可以看到能够比较好地重建出原始信号。通过下图能够更好得出对比的效果。
MATLAB——PCM编译码实验_第9张图片

4.5失真度分析

MATLAB——PCM编译码实验_第10张图片

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波形,验证模块的正确性。

MATLAB——PCM编译码实验_第11张图片
MATLAB——PCM编译码实验_第12张图片
接下来我将之前编写的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八进制编码的形式,必须要进行解码,同时和原信号进行对比,验证传输的正确性。

MATLAB——PCM编译码实验_第13张图片

%% 译码
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('语音信号对比');

MATLAB——PCM编译码实验_第14张图片
MATLAB——PCM编译码实验_第15张图片
MATLAB——PCM编译码实验_第16张图片

五、引用

[1]邢巨伟.模拟信号的数字化传输-PCM编码[J].黑龙江科技信息,2014(33):116.
[2]陈奎.语音PCM编码通信系统的SIMULINK仿真[J].福建电脑,2012,28(10):115-117.
[3]赵守彬,李鸿刚.利用Matlab实现PCM编码的A律13折线法量化[J].科技信息,2009(36):547.

你可能感兴趣的:(通信原理,matlab,pcm,开发语言)