【通信系统仿真系列】基于ΔM增量调制的模拟信号通信系统仿真

【通信系统仿真系列】基于ΔM增量调制的模拟信号通信系统仿真

  • 前言
  • 原理
    • 程序流程图
    • 音频文件读取
    • ΔM调制
    • 随机误码
    • ΔM解调
    • 平滑处理&归一化处理
  • 实验结果
  • 源代码
    • 可以修改的参数
    • 下载地址
    • 主函数
    • 增量调制模块
    • 增量解调模块
    • 误码模块
  • 后语

前言

本文基于Matlab,通过对一个以flac无损格式的音频进行ΔM调制与解调,把解调结果通过扬声道输出,让实验者可以直观地感受到ΔM调制所谓的细节丢失,同时研究了在不同误码率下,声音的失真程度,并把实验结果通过主观体验展现出来。实验结果已经做成视频点我进入。

增量调制简称ΔM或增量脉码调制方式(DM),它是继PCM后出现的又一种模拟信号数字化的方法。1946年由法国工程师De Loraine提出,目的在于简化模拟信号的数字化方法。主要在军事通信和卫星通信中广泛使用,有时也作为高速大规模集成电路中的A/D转换器使用。

原理

程序流程图

载入&截取单声道
ΔM调制
随机误码
ΔM解调
平滑处理&归一化处理
无损音频
PCM量化结果
二进制调制结果
接收端接收结果
PCM量化结果
解调输出
播放

音频文件读取

音频文件通过Matlab函数(audioread)载入,得到音频文件的采样率以及PCM编码结果。为了减少处理过程的内存占用以及运行时间,对载入的音频截取一个声道以及截短。

ΔM调制

默认初始量化状态是0,调制增量为0.03。对于每一个PCM量化样点,如果比上一次量化状态要大,调制器输出1,量化状态更新为上一次状态加上调制增量;反之,调制器输出0,量化状态更新为上一次量化状态减去调制增量。
流程图如下图所示,对于每一个PCM量化值,执行以下操作。

Created with Raphaël 2.3.0 开始 量化状态=0 量化样点 大于量化状态? 输出1 新的量化状态=量化状态 + 调制增量 结束 输出0 新的量化状态=量化状态 - 调制增量 yes no

调制的结果是二进制数组。

随机误码

误码率可以进行调整,通过Matlab的(rand)函数为每一个二进制位生成随机数,当生成的随机数小于误码率时,对该调制结果的二进制位进行取反,从而模拟指定误码率的传输误码。

ΔM解调

默认初始解调输出为0,解调增量为0.03,注意解调增量与调制增量需要保持一致。读取每一个调制结果,如果为1,解调输出为上一次输出加上解调增量;反之,则解调输出为上一次输出减去解调增量。
解调流程如下图所示,对于调制结果的每一个二进制位,执行如下操作。

Created with Raphaël 2.3.0 开始 解调输出=0 调制结果点 等于1 新的解调输出 = 解调输出 + 解调增量 结束 新的解调输出 = 解调输出 - 解调增量 yes no

解调结果为粗PCM量化结果。

平滑处理&归一化处理

解调得到的粗PCM量化结果中有比较多的毛刺,所以需要对其进行平滑处理。平滑采用了Matlab的平滑化函数(smooth),采用了基于Savitzky-Golay算法的10点平滑算法,该算法如果感兴趣的话可以自行学习,此处不做介绍。
平滑处理后的量化值不在-1到1的范围内,而Matlab对音频信号的范围规定为-1到1,所以还要进行归一化处理,等比例地把型号缩放到-1到1的范围之内,避免发生幅度钳制。

实验结果

实验结果地址:https://www.bilibili.com/video/BV11f4y1y7Hg
从实验结果可以听出,随着误码率的上升,声音有效部分越来越小声,但只要调高音量,仍然能听到歌声。

源代码

可以修改的参数

  1. 调制增量:默认0.03,过大会导致量化误差增大,过小则容易导致过载
  2. 传输误码率:默认0

下载地址

Github:https://github.com/highskyno1/Delta-modulation-simulation
度盘:https://pan.baidu.com/s/1qqIrHu5IJ61SGPb40NYGGA
提取码:0ypg

主函数

main.m

clear sound
%定义调制增量
increase = 0.03;
%定义传输误码率
errorRate = 0;

%加载要量化的音频
[source,SampleRate] = audioread('./Alisa-All I Want.flac');
%转单声道&截断
source = source(1:3e6,2);

%增量编码
code_res = increEnCode(source,increase);
%人为地加入误码
code_res = errorCode(code_res,errorRate);

%解码
decode_res = increDeCode(code_res,increase);
%平滑处理
write = smooth(decode_res,10,'sgolay');
%归一化处理
write = mapminmax(write);
write = write./max(abs(write));
%播放解码结果
sound(write,SampleRate);
%把解码结果写入文件
audiowrite('./out.mp4',write,SampleRate);

增量调制模块

increEnCode.m

function code_res = increEnCode(source,increment)
%increEnCode 对输入的音频信号进行增量调制编码
%   source:需要编码的音频数组信号
%   increment:增量参数
%   res:编码后的二进制结果

%计算音频体积
source_size = length(source);
%M编码开始状态
state_encode = 0;
%编码结果数组
code_res = int8(zeros(1,source_size));
%开始编码
for i = 1:source_size
    if source(i) > state_encode
        code_res(i) = 1;
        state_encode = state_encode + increment;
    else
        code_res(i) = 0;
        state_encode = state_encode - increment;
    end
end
end

增量解调模块

increDeCode.m

function decode_res = increDeCode(code_res,increment)
%increDeCode 增量调制解调函数
%   source:需要编码的音频数组信号
%   increment:增量参数
%   res:解码后的音频信号

%计算音频体积
source_size = length(code_res);
%解码器初始状态
state_decode = 0;
%初始化解码结果
decode_res = zeros(1,source_size);
%开始解码
for i = 1:source_size
    if code_res(i) == 1
        decode_res(i) = state_decode + increment;
    else
        decode_res(i) = state_decode - increment;
    end
    state_decode = decode_res(i);
end
end

误码模块

errorCode.m

function source = errorCode(source,errorRate)
%errorCode 人为地给信号加入误码
%   source:原信号
%   errorRate:误码率
%   res:加入误码结果

%计算音频体积
source_size = length(source);
%加入随机误码
for i = 1:source_size
    if rand() <= errorRate
        source(i) = ~source(i);
    end
end
end

后语

因为最近在学ZYNQ开发以及IOS开发,所以其实代码写好很久了,但今天才整理成文章发出来。万万没想到,考研成功了!从此开始了3年的研究生生活。最终宿舍包括我有5个人考研,4个人考研成功。接下来需要在辅导员的授意下,去学校系统申请进入宿舍收拾东西,打包往家里搬,只有一天时间啊,整个疫情搞得一切计划全乱套了。毕业照,毕业晚会都没有了,毕业证直接往家里寄。

你可能感兴趣的:(仿真,数字通信,信号处理,数字信号处理)