基于MATLAB的简单语音通信系统

本文是关于通信工程学生使用MATLAB设计的一个基于PCM编码的语音信号通信系统,包括音频录制、PCM编码、码型变换、文件传输、抽样判决和PCM译码等步骤。系统通过创建共享文件夹在两个独立的计算机系统之间传输数据,并分析了设计过程和结果。
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

前言

一、设计任务

二、课程设计解决的主要问题

三、设计内容

四、结果分析

五、参考资料

总结


前言

本人是通信工程的本科生,这是本人在学习《通信原理》时,老师布置的课程设计,现已大致完成,本片文章是一个总结。由于本科阶段培养方案里没有一门系统学习MATLAB的课程,我是自己学习,掌握了一些MATLAB的知识,所以本文中讲的东西不一定都是对的,如果我有讲错的地方,欢迎指出,如果我的思路过于复杂,也希望评论区的大佬们不吝赐教。

一、设计任务

公共电话网(PSTN)的语音终端(电话)基本都是模拟的,然而 PSTN 传输的是数字信号,请参照公共电话网的方式设计一个语音信号通信系统,用数字传输方式,发送端和接收端需要分别将模拟语音信号 A/D、D/A 变换,可采用PCM 编码方式。

要求: (1)Matlab 编程实现; (2)自己录制音频数据; (3)发送、接收端须为独立的系统。

二、课程设计解决的主要问题

1、录制音频信号

2、PCM编码

3、码型变换

4、两独立系统间传输(采用创建共享文件夹的方式)

5、抽样判决

6、PCM译码

三、设计内容

1.整体设计方案

1)语音信号通信系统原理框图

图1  总系统框图

声音由系统A(电脑A)麦克风录入,转换成原始电信号,原始电信号经过采样后进行PCM编码,将编码生成的0/1二进制序列通过码型变换转换成双极性不归零码,将其以.mat文件形式保存至电脑A创建的共享文件夹内进行传输;在系统B(电脑B)上打开电脑A共享的文件,把其中接收到的双极性不归零码.mat文件导入,然后对数据进行抽样判决生成0/1二进制序列,最后PCM译码输出;由扬声器进行播放。

2)各个部分功能及作用

1)麦克风:充当信源,作用是把声音消息转换成原始电信号。

2)扬声器:充当信宿,作用是将复原的电信号转换成声音。

3)码型变换:将0/1二进制码转换成双极性不归零码。

4)信道:是允许基带信号通过的媒介,此处采用创建共享文件夹方式在两独立系统间进行传输。

5)抽样判决:在噪声背景下,在规定时刻(由位定时脉冲控制)对信道输出的基带信号进行抽样判决,以恢复或再生基带信号。

6)PCM编码:将模拟信号变换成二进制信号。对输入的模拟信号进行抽样、量化和编码;编码后的PCM信号是一个二进制数字序列,传输方式采用数字基带传输。接收端PCM信号经过译码后还原为量化值序列,得到重建的模拟信号。

①PCM系统原理方框图

图2  PCM系统原理框图

②抽样

是对模拟信号进行周期性扫描,把时间上连续的信号变成时间上离散的信号。该模拟信号经过抽样后还应当包含原信号中所有信息,也就是说能无失真的恢复原模拟信号。抽样速率的下限是由抽样定理确定的。

③量化

模拟信号的量化分为均匀量化和非均匀量化。由于均匀量化存在的主要缺点是:无论抽样值大小如何,量化噪声的均方根值都固定不变。因此实际中,往往采用非均匀量化。

非均匀量化的实际方法通常是将抽样值通过压缩再进行均匀量化。通常使用的压缩器中,大多采用对数式压缩。广泛采用的两种对数压缩律是μ压缩律和A压缩律。美国采用μ压缩律,我国和欧洲各国均采用A压缩律,因此,PCM编码方式采用的也是A压缩律。所谓A压缩律也就是压缩器具有如下特性的压缩律:

式中,x是归一化压缩器输入电压;y是归一化压缩器输出电压;A是压扩参数,表示压缩程度。实际应用中,采用近似于A律函数规律的13折线( A=87.6)的压缩特性。

把x轴的0~ 1分为8个不均匀段,其分法是将0~1之间一分为二,其中点为1/2, 取1/2~1之间作为第八段;剩余的0~1/2在一分为二,中点为1/4, 取1/4~1/2之间为第七段;再把剩余的0~1/4 一分为二,中点为1/8,取 1/8~1/4之间作为第六;依次下去,直到剩余最小的一段为0~1/128作为第一段。而y轴的0~1均匀的分为八段,与x轴的八段一一对应。这样,便可做出由八段直线构成的折线,折线除了一、二段外,其他各段折线的斜率都不相同,如表1所示。

表1  13折线分段时的各段折线的斜率

折线段号

1

2

3

4

5

6

7

8

斜  率

16

16

8

4

2

1

0.5

0.25

④PCM编码译码原理

抽样信号I按照13折线A律特性编成8位码组C1C2C3C4C5C6C7C8,其中C1为极性码,I为正时取1,I为负时取0。

C2C3C4为段落码,决定I被编码所在的码段。13折线A律PCM编码将0 ~ 2048不均等的分为8个编码段落[0,16]、 [16,32]、 [32, 64]、 [64,128]、 [128, 256]、[256, 1024]、 [1024, 2048]。各个段落的编号和起点电平如表2所示。

表2  编码段落

段落

1

2

3

4

5

6

7

8

起点电平

0

16

32

64

128

256

512

1024

均匀量化数

16

16

32

64

128

256

512

1024

量化间隔

1

1

2

4

8

16

32

64

C2C3C4

000

001

010

011

100

101

110

111

将每一个码段做16等分,每一份作为量化间隔,并用段内码C5C6C7C8来表示之。13折线中的第一、二段最短,只有动态范围的1/128,将其等分为16小段后,每一小段的长度为(1/128)x(1/16)= 1/2048,第八段归一化值为1/2,等分16小段后每一段的最小长度为1/32。显然,随着段落编号的增大,量化间隔越大,量化误差也越大。

编码时,先确定极性码;再采用逐次比较的办法,确定段落码;最后,由段落起点电平的差值来确定段内码。译码时,先由段落码确定编码所在段落,确定段落起点电平和量化间隔,由段落起点电平加上段内码与相应量化间隔的乘积之和,即得到了抽样信号的绝对值,再由极性码C1来确定抽样值的正负号。

2.设计内容

1)录制音频

利用“audiorecorder”函数录制音频数据。

(2)抽样

Xn = resample(x1,Fs,fs);利用“resample”函数重新采样。

3PCM编码

1)判断极性

通过if语句进行判断即可确定C1 ;代码如下:

if z(i)>0

       code(i,1)=1;

    elseif z(i)<0

       code(i,1)=0;

2)判断段落码

运用逐次比较法,确定段落码C2C3C4 ;代码如下:

if (Q(i)>=128)&&(Q(i)<=2048)

        code(i,2)=1;       

    end

    if (Q(i)>=32)&&(Q(i)<128)||(Q(i)>=512)&&(Q(i)<2048)

            code(i,3)=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;         

     end

3)判断段内码

由段落码确定相应的段落计算出电平所在的位置,进行编码。代码如下:

    N(i)=bin2dec(num2str(code(i,2:4)))+1;

    a=[0,16,32,64,128,256,512,1024];      

    b=[1,1,2,4,8,16,32,64];             

    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];                 

        else k=num2str(dec2bin(q-1,4));

4)码型变换

通过if判断语句将01二进制码转换成双极性不归零码,降低误码率。代码如下:

if pcm_encode(oo)>0.5

        pcm_encode2(oo)=1;

    else

        pcm_encode2(oo)=-1;

    end

5)文件传输

在系统A中创建共享文件夹

将系统A和系统B连接在同一个WIFI下

在系统A中运行程序

系统A运行获得的双极性不归零码以.mat文件形式保存在共享文件夹内

在系统B中打开共享文件夹获得.mat文件

6)抽样判决

同样是利用if判断语句将数据文件直接转换成01二进制码。代码如下:

if transf_sig(nn) >= 0

        transf_sig2(nn) = 1;

    else

        transf_sig2(nn) = 0;

    end

7PCM译码

1)判断极性

代码如下:

if x==0

        s(i)=-k(i);

     else

        s(i)=k(i);

2)计算电平

  通过8位二进制码判断出电平所在位置;利用公式计算即可得到量化电平值。代码如下:

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

8)播放语音信号

“sound”函数对语音信号进行播放。

代码如下:

sound(x,FS);               

pause(T_end+1);

9)画图

 “plot”函数进行画图,“fft”进行离散傅里叶变换的到频域图,“fftshift”移动频域范围。

四、结果分析

1、模拟信号的生成

语音实时录音,原始数据采用了44kHz采样率,为了减少数据量便于处理,本次实验仅提取了原始音频信号的单个声道作为原始数据进行处理。同时为了进一步减少处理数据量,还对单声道音频数据进行了降采样处理(8khz)。

2、模拟信号数字化

图3  原始语音信号

图4  采样后的语音信号

3、模拟信号还原

图5  译码恢复的语音信号

将传输后的数据抽样判决得到二进制序列,再将其进行PCM译码并归一化从而得到恢复后的音频模拟信号。如图5可以发现与采样后的语音信号时域图、频谱图几乎一致。

4、播放语音信号

播放原始语音信号、采样后的语音信号、译码恢复的语音信号。

五、参考资料

[1]《通信原理(第7版)》樊昌信,曹丽娜著.国防工业出版社,2012。

[2] 邢巨伟.模拟信号的数字化传输-PCM编码[J].黑龙江科技信息,2014

[3] 张毅勇.模拟信号PCM编码的实现[J].甘肃冶金,2007(06)

[4] 别志松,别红霞. 系统与通信系统仿真.北京:北京邮电大学出版社,2010.

[5] 樊昌信,宫锦文,刘忠成编著《通信原理及系统实验》[M]北京:电子工业出版社,2007

[6] 通信原理实验编写组编著.《通信原理实验》[M].上海:上海交通大学出版社,1987

[7] 曹志刚等编著《现代移动通信原理》[M].北京:清华大学出版社,1999

[8] 赵谦等.《通信系统中MATLAB基础与仿真应用》[M]西安:西安电子科技大学出版社,2010

[9] 张威.MATLAB基础与编程入门.西安电子科技大学出版社,2004.2

六、附录程序

系统A主程序

%%系统A%%
%%主程序:
clear;
clc;
close all;
%%声音录制%%
FS=44100; % 设置的采样频率是audiorecorder函数的参数之一
voice = audiorecorder(FS,8,2);
% audiorecorder函数:(采样频率,比特数,通道数)——创建录制音频对象,放入声明的voice数组变量中
disp('Start speaking.');
%disp函数——命令窗口中提示录音的开始
recordblocking(voice,5);
% recordblocking函数:(音频存放对象,录音时间/S)为实际控制录音的函数
disp('End speaking.'); 
%disp函数——命令窗口中提示录音的结束
MyRecording=getaudiodata(voice);
% getaudiodata函数——从音频存放对象中获取记录到的音频数据,存储到数值数组MyRecording
filename='D:\学习\通信原理课设尝试代码\尝试共享文件夹\通信课设录音.wav';
%以采样率 Fs 将数值数组MyRecording写入filename ,保存到指定路径下,命名为‘通信课设录音’
audiowrite(filename,MyRecording,44100);
% audiowrite函数——用于将音频数据作为文件存放到到你建立的文件夹中 
clear voice;
[x,fs]=audioread(filename);
% audioread函数——用于从音频文件中将数据读出来:x是音频数据,fs是采样频率,它们对应录音过程中你在audiowrite函数写入的MyRecording和44100
x1 = x(:,2);%取单声道
T=1/FS; %采样时间
TIME=T*length(x1); %计算音频长度,其中length(x1)计算变换的点数
tx1=T:T:TIME; %计算采样点,作为时域横坐标
X = fftshift(fft(x1./(length(x1)))); 
%用fft得出离散傅里叶变换,fftshift将零频分量移到频谱中心
% % 从-Fs/2到Fs/2,取length(Xn)个向量
f = linspace(-FS/2,FS/2-1,length(x1));
%频域横坐标:将[-FS/2,FS/2-1]进行length(Xn)-1等分
%奈奎斯特采样定理,原始信号最大频率<=采样频率的一半
% % 原始信号画图
Figure(’Name’,’原始声音信号’); %figure函数——创建图形窗口
subplot(2,1,1);plot(tx1,x1);title('原始声音信号(时域)');
xlabel(‘时间’);ylabel(‘振幅’);grid on;
subplot(2,1,2);plot(f,X);title('原始声音信号(频域)');
xlabel(‘F(Hz)’);ylabel(‘H(jw)’);grid on;
% % 以8000hz采样:人声频率在0~4000hz,根据奈奎斯特采样定理——采样频率应高于原始模拟信号最高频率两倍
Fs = 8e3;                     %设置目标采样频率
Xn = resample(x1,Fs,fs);      %降采样率,从fs降到Fs。重新取样。
Ts = 1/Fs;                  %采样间隔
T_end = length(Xn)/Fs;       %采样时间终点。length为矩阵最大长度
tx1 = Ts:Ts:T_end;  %计算采样点,作为抽样信号横坐标
X1 = fftshift(fft(Xn./(length(Xn))));
%用fft得出离散傅里叶变换,fftshift将零频分量移到频谱中心
f1 = linspace(-Fs/2,Fs/2-1,length(Xn));
%频域横坐标:将[-FS/2,FS/2-1]进行length(Xn)-1等分
% % 抽样信号画图
figure(’Name’,’抽样后原始声音信号’);
subplot(2,1,1);plot(tx1,Xn);title('原始信号抽样后(时域)');
xlabel(‘时间’);ylabel(‘振幅’);grid on;
subplot(2,1,2);plot(f1,X1);title('原始信号抽样后(频域)');
xlabel(‘F(Hz)’);ylabel(‘H(jw)’);grid on;
% % PCM编码
pcm_encode = PCMcoding(Xn);
% % 双极性不归零编码
pcm_encode2=zeros(length(pcm_encode),1);
%预设一个全零代码存储矩阵大小为length(pcm_encode)×1
for oo=1:length(pcm_encode)
    if pcm_encode(oo)>0.5
        pcm_encode2(oo)=1;
    else
        pcm_encode2(oo)=-1;
    end
end
save('D:\学习\通信原理课设尝试代码\尝试共享文件夹\保存的mat在这里');

系统A子程序——PCM编码

%%PCM编码
function [code ] = PCMcoding( S )
%UNTITLED3 此处显示有关此函数的摘要
%   此处显示详细说明
    z=sign(S); %判断S的正负
    MaxS=max(abs(S)); %求S的最大值 
    S=abs(S/MaxS); %归一化
    Q=2048*S;%量化
    code=zeros(length(S),8);                  %预设代码存储矩阵(全零)
    % 判断段落码程序
    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位于第几段
    end
    a=[0,16,32,64,128,256,512,1024];       %量化间隔
    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向上取整
        if q==0
            code(i,(5:8))=[0,0,0,0];                 %如果输入为零则输出"0"
        else k=num2str(dec2bin(q-1,4));%编码段内码为二进制。把q-1转换成二进制数
            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, []);%重塑数组为1xX
end

系统B主程序

%%系统B主程序
transf_sig = awgn(pcm_encode2,10,'measured');
% awgn函数——将高斯白噪声添加到pcm_encode2双极性不归零码中,10dB为snr,指定了每个采样点的信号与噪声的比率。measure则是测量了信号的能量。

% % 抽样判决,判决电平为0
transf_sig2=zeros(length(transf_sig),1);
%预设代码存储矩阵(全零)大小为length(transf_sig)×1
for nn=1:length(transf_sig)
    if transf_sig(nn) >= 0
        transf_sig2(nn) = 1;  % 大于判决电平为1
    else
        transf_sig2(nn) = 0;  % 小于判决电平为0
    end
end 
% % PCM解码
xmax = max(abs(Xn)); %求Xn的最大值
pcm_decode = PCMdecoding(transf_sig2,xmax);% PCM 译码
X2 = fftshift(fft(pcm_decode./(length(pcm_decode)))); 
%用fft得出离散傅里叶变换, fftshift将零频分量移到频谱中心
f2 = linspace(-Fs/2,Fs/2-1,length(pcm_decode));
%频域横坐标: 将[-FS/2,FS/2-1]进行length(pcm_decode)-1等分,注意奈奎斯特采样
% % 译码后信号画图
figure(‘Name’,’PCM译码后’);
subplot(2,1,1);plot(tx1, pcm_decode);title('PCM译码后(时域)');
xlabel(‘时间’);ylabel(‘振幅’);grid on;
subplot(2,1,2);plot(f2,X2 );title('PCM译码后(频域)');
xlabel(‘F(Hz)’);ylabel(‘H(jw)’);grid on;
% % 播放
sound(x,FS);                %播放原始语音信号
%sound函数——用于将音频数据播放出来:用采样频率fs来播放音频数据x
pause(T_end+1);
sound(Xn,Fs);               %播放降采样率之后的语音信号
pause(T_end+1);
sound(pcm_decode,Fs);       %播放解码译码后的语音信号
pause(T_end+1);

系统B子程序——PCM译码

%%PCM译码
function [ s ] = PCMdecoding( encode, max )
%UNTITLED6 此处显示有关此函数的摘要
%   此处显示详细说明
    encode=(reshape(encode',8,length(encode)/8))';%重排矩阵为8xX
    L=size(encode,1);%计算encode的行数
    a=[0,16,32,64,128,256,512,1024];
    b=[1 1 2 4 8 16 32 64];
    c=[0 1.5:15.5];%0 1.5 2.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


总结

共享文件夹那一块还需要各位再去根据自己的电脑配置一下,博主的两台电脑是有时能连上,有时连接不上。

  • 8
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值