一. 实验要求及目的
1、要求1
(1)利用MATLAB编程实现对外界输入的二进制序列信息进行(7,4)汉明码的编、译码;比较其编译码后的信息序列是否一致;
(2)在此基础上,在汉明码加错(1位、2位)后,研究对输入序列的影响,进而对汉明码的性能进行分析。
2、要求2
(1)利用MATLAB编程实现对外界输入的语音或音频进行(7,4)汉明码的编、译码;比较其编译码后的语音波形是否一致或通过听编译码前后的声音/音频判断编译码的效果;
(2)在此基础上,在汉明码加错(1位、2位)后,研究对输入语音或音频的影响,进而对汉明码的性能进行分析。
3、实验目的
通过该综合实验掌握汉明码编译码原理在纠错通信系统实际应用中的方法。
二.问题描述
利用MATLAB录制一段语音信号,对语音信号进行脉冲编码调制(采样、量化、编码)、汉明码编码、加噪、汉明码译码、PCM译码,对比编译码前后的音频并绘制其编译码后的语音波形,实验框图如图1所示。
三、实现方法
1.录制音频并存储
(1)思路
通过audiorecorder()函数录制一段语音,时间为不宜太长,过长为导致处理过慢。录音结束时通过getaudiodata()获取录音数据,通过audiowrite()函数存储语音信号至指定位置。
(2)代码
recObj = audiorecorder;
Fs = 44100 ;
nBits = 16 ;
nChannels = 1 ; %单通道
ID = -1; % default audio input device
T = 2;%录音时长
recObj = audiorecorder(Fs,nBits,nChannels,ID);
disp('Start speaking.')
recordblocking(recObj,T);
disp('End of Recording.');
% 获取录音数据
Recording = getaudiodata(recObj);
%存储语音信号
filename = 'D:\2019to2023\Tools\Code and Decode\TASK3\data1.wav';
audiowrite(filename,Recording,Fs);
2.采样
(1)思路
以8000的采样率对录制的语音进行采样,即每隔Fs/fs向下取整个点采样一次。
(2)代码
%读取文件,音频数据audio
[audio,~] = audioread('D:\2019to2023\Tools\Code and Decode\TASK3\data1.wav');
fs = 8000; %采样音频采样率
sampling = zeros(fs*T,1);
for i=1:fs*T
sampling(i)=audio(floor(i*Fs/fs)); %生成采样音频
end
3.量化
(1)思路
求出采样点的最大值,并对采样值进行归一化,即将采样值的范围变成0~1,在将采样值量化,即乘以2048,量化后的值范围是0-2048。
(2)代码
MaxS=max(abs(S)); %求S的最大值
S=abs(S/MaxS); %归一化
Q=2048*S; %量化
4.PCM编码
(1)思路
首先根据正负确定极性码,再根据大小范围确定三位段落码,如表1所示。最后根据量化值-段落起始电平段落量化间隔向下取整的值确定四位段内码。
(2)代码
z=sign(S); %判断S的正负
code=sparse(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=sparse(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))); %求出在段内的位置
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, []);
5.汉明码编译码
(1)思路
通过MATLAB库函数里,函数hammgen可产生汉明码的生成矩阵与校验矩阵,调用MATLAB库函数中的encode函数、decode函数实现汉明码的编码和解码,通过产生随机数实现随机加错。
(2)代码
function [HMcode,newmsg] = hammgen74(pcm_encode)
m = 3; %给定m=3的汉明码,m = n-k
[h,g,n,k] = hammgen(m);
row = (length(pcm_encode))/4;
msg = reshape(pcm_encode,row,4);
HMcode = zeros(row,n);
newmsg = zeros(row,k);
for i=1:row
HMcode(i,:) = encode(msg(i,:),n,k,'hamming/binary'); %编码
j = ceil(rand*7);
HMcode(i,j) = ~HMcode(i,j);
j = ceil(rand*7);
HMcode(i,j) = ~HMcode(i,j);
end
for i=1:row
newmsg(i,:) = decode(HMcode(i,:),n,k,'hamming/binary'); %解码
end
end
6.PCM译码
(1)思路
将汉明码译码的矩阵重构成8列,逐行判断第一位(符号位),根据段落码(第2到4位)得到段落起始值,根据段内码(第5到8位)得到段内值。译码时,为减小最大误码误差,需要在译码电平上加上段内码的平均值。
(2)代码
function s=PCMdecoding(encode, max)
k=size(encode',1);
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:k %门限判决,模拟ADC还原数字信号
if encode(i)<0.5
encode(i)=0;
elseif encode(i)>=0.5
encode(i)=1;
end
end
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
四、实验结果及分析
1.以8000Hz采样率采样,能够恢复原声,图2为原始信号和采样信号时域波形图。
2.加错一位时,能够实现纠错,编译码前后音频一致;加错两位,无法实现纠错,编译码后音频失真。图3为加错一位时域波形图,图4为加错两位时域波形图。
五、实验中出现的问题及难点
1.采用率为8000Hz的原因
PCM早些时候一般用于电话语音传输,电话语音的频率范围是从300Hz-3.4kHz,根据奈奎斯特采样,只要高于最高频率的两倍,就可以实现声音不失真的还原,故只要采样率大于3.4k*2,即可还原电话语音.采用8000Hz只是一种ITU(国际电信联盟)规定,实际上只要大于6.8kHz,都可以实现采样。
2.矩阵维度
矩阵维度变化是实验过程中容易出错的地方,同时根据控制台的报错信息很容易改正。图5 为矩阵维度变化。