Matlab基于μ律15折线的PCM语音编解码系统(GUI设计simulink附完整代码)

Posted 阿汪先生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Matlab基于μ律15折线的PCM语音编解码系统(GUI设计simulink附完整代码)相关的知识,希望对你有一定的参考价值。

【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所示:

图2-1 μ律15折线律的特性曲线

  由于其第一段和第二段的斜率不同,不能合并为一条直线,故当考虑到信号的正负电压时,仅正电压第一段和负电压第一段的斜率相同,可以连成一条直线。所以,得到的是15段折线,称为15折线压缩特性。
  μ律不易用电子线路准确实现,所以目前实用中是采用特性近似的15折线代替μ律。这时,和A律一样,也把纵坐标 y 从0到1之间划分为8等份。对应于各转折点的横坐标 x 值可以按照下式计算:

  计算结果列于下表中:

表2-1 μ律折线的斜率


  在15折线律中采用的折叠码与13折线律相同也有8位。其中第一位c1表示量化值的极性正负。后面的7位分为段落码和段内码两部分,用于表示量化值的绝对值。其中第2至4位(c2 c3 c4)是段落码,共计3位,可以表示8种斜率的段落;其他4位(c5 ~ c8)为段内码,可以表示每一段落内的16种量化电平。段内码代表的16个量化电平是均匀划分的。

  所以,这7位码总共能表示27 = 128种量化值。在下面的表2-1中给出了段落码和段内码的编码规则。

表2-2 段落码和段内码的编码规则


  在上述编码方法中,虽然段内码是按量化间隔均匀编码的,但是因为各个段落的斜率不等,长度不等,故不同段落的量化间隔是不同的。其中第1和2段最短,斜率最大,其横坐标x的归一化动态范围只有1/128。再将其等分为16小段后,每一小段的动态范围只有(1/128) * (1/16) = 1/2048。

  这就是最小量化间隔,后面将此最小量化间隔(1/2048)称为1个量化单位。第8段最长,其横坐标x的动态范围为1/2。将其16等分后,每段长度为1/32。假若采用均匀量化而仍希望对于小电压保持有同样的动态范围1/2048,则需要用11位的码组才行。现在采用非均匀量化,只需要7位就够了。

  如下图2-2所示为PCM编码的原理框图,它首先在编码器中由冲激脉冲对模拟信号抽样,得到在抽样时刻上的信号抽样值。这个抽样值仍然是模拟量。在它量化之前,通常用保持电路将其作短暂保存,以便电路有时间对其进行量化。在实际电路中,常把抽样和保持电路作在一起,称为抽样保持电路。图中的量化器把模拟抽样信号变成离散的数字量,然后在编码器中进行二进制编码。这样,每个二进制码组就代表一个量化后的信号抽样值。

  常用的编码方法有逐次比较法等等。常用的二进制码有自然二进制码及折叠二进制码等。

图2-2 PCM编码的原理框图

2.2 PCM语音解码原理

  接收端实现PCM解码的原理框图如图2-3所示,其主要原理为逐次比较A/D转换。

图2-3 PCM解码原理框图

  在此图中,本地译码器的记忆电路得到输入c7值后,使恒流源产生为下次比较所需要的权值电流Iw。在编码器输出c8值后,对此抽样值的编码已经完成,所以比较器要等待下一个抽样值到达,暂不需要恒流源产生新的权值电流。在接收端的译码器中,仍保留本地译码器部分。

  由记忆电路接收发送来的码组。当记忆电路接收到码组的最后一位c8后,使恒流源再产生一个权值电流,它等于最后一个间隔的中间值。由于编码器中的比较器只是比较抽样的绝对值,本地译码器也只是产生正值权值电流,所以在接收端的译码器中,最后一步要根据接收码组的第一位c1值控制输出电流的正负极性。由此接收端可得到PCM的语音解码。


三.软件设计

3.1信号产生与采样

  信号产生与采样部分的代码如图3-1所示(正弦波),此处以正弦波为例是为了方便进行PCM编解码正确性的验证。由奈奎斯特采样定理可知该信号的采样频率要大于4000Hz。根据上述原理可知此处选取的信号采样频率为8000Hz,代码和信号采样前后对比如图3-2所示。max函数的作用是用来计算信号采样后各个幅度的极值,为之后PCM编码过程中的量化做准备。

图3-1 正弦波信号产生与采样代码

图3-2 正弦波信号采样前后对比图

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-4 PCM编码函数中采样信号的量化部分

图3-5 PCM编码函数中段落码判断部分

图3-6 PCM编码函数中段内码判断部分

图3-7 PCM编码程序调用

图3-8 正弦信号PCM编码结果

3.3 PCM解码

  根据PCM解码的相关原理,可以得到该部分的程序框图如图3-9所示,其中相对幅度即还原后抽样信号的幅值与所有抽样信号的幅值的最大值之比,从而可设计出PCM解码函数如图3-10所示,调用代码如图3-11所示,解码效果图如图3-12所示。

图3-9 PCM解码部分程序框图

图3-10 PCM解码函数

图3-11 PCM解码程序调用

图3-12 PCM解码输出与原输入对比图

  由PCM译码的波形和原始信号波形的对比可以看出,运用μ-15折线律作为压缩律对原始信号进行PCM编解码的还原度还是比较高的。

3.4 PCM编解码的Simulink实现

  由PCM编解码原理,可设计出如图3-13所示的PCM编解码系统。

图3-13 PCM编解码系统示意图

  在图3-13中,我们以一个非周期性正弦波chirp为例,先对该波进行量化,然后将量化后的信号通过对其进行编码,译码和解码,并设置其采样8位2进制编码和解码,随后将解码过后的信号通过一个低通滤波器,滤除其中的高频噪声,从而对原来量化过后的信号进行还原。

图3-14 PCM编解码系统输入设置示意图

  

图3-15 PCM编码模块设置示意图

  

图3-16 PCM解码模块设置示意图

  

图3-17 PCM编解码输出示意图

3.5 PCM编解码的GUI实现

  此处采用GUI界面操作完成语音输入,PCM编码,PCM解码,语音还原输出,界面如图3-18所示,该系统可以使用弹出式菜单分别进行三种不同种类语音:锣声,哈利路亚和笑声的输入,并通过PCM编解码对其进行还原输出,三种不同种类语音输入与语音还原输出后的对比图如图3-19,图3-20和图3-21所示。

图3-18 PCM通信系统的GUI设计界面

  

图3-19 锣声语音输入与PCM语音还原输出后的对比图

  

图3-20 哈利路亚语音输入与PCM语音还原输出后的对比图

  

图3-21 笑声语音输入与PCM语音还原输出后的对比图


四.性能分析

4.1 具体信号分析

   此处主要对正弦还原信号进行失真度分析的测试,如图4-1所示。可得到失真度的大小为0.002030(如图4-2所示),说明对应具体信号而言,PCM编解码后的输出信号还原度较高。

图4-1 信号失真度测试代码

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)

GUI设计网上教程很多,这里贴1张效果图。
完整工程文件后续会上传到博客资源当中。


以上是关于Matlab基于μ律15折线的PCM语音编解码系统(GUI设计simulink附完整代码)的主要内容,如果未能解决你的问题,请参考以下文章

Matlab基于μ律15折线的PCM语音编解码系统(GUI设计simulink附完整代码)

Matlab基于A律13折线的PCM语音编解码系统(GUI设计simulink附完整代码)

Matlab基于A律13折线的PCM语音编解码系统(GUI设计simulink附完整代码)

Matlab基于A律13折线的PCM语音编解码系统(GUI设计simulink附完整代码)

MATLAB教程案例39语音信号的PCM编解码matlab仿真学习

通信基于matlab语音信号仿真含Matlab源码 957期