%% --通信原理大作业-- %%
clear;
clc;
close all;
filename='myspeech.wav'; % 填音频文件名
%% 信号预处理
Fs_low = 8e3; %降采样频率
[x,fs]=audioread(filename); %打开语音信号
x1 = x(:,2); %取单声道
Xn = resample(x1,Fs_low,fs); %降采样率
%% 预设参数
Eb_N0 = 1:10; %信道信噪比
Ts_low = 1/Fs_low; %降采样后的采样间隔
fc = 1e5; %载波频率
Fs = 4*fc; %总采样率
Ts = 1/Fs;
T_end = length(x1)/fs; %采样时间终点
Time = Ts:Ts:T_end; %传输总时间片
N_sample = length(Time); %总采样点数
sig_rate = length(Xn)*8/T_end;%信号传输速率设定
t_sig = 1/sig_rate;
%% 原始信号处理
PCM_code = PCMencoding(Xn); %抽样信号编码
PCM_code = int8(reshape(PCM_code,1,[])); %变换为向量
PCM_len = length(PCM_code);
%% 统一时间轴/对所有信号进行等采样率采样
msg_sample = zeros(1,N_sample);
carrier_sample = zeros(1,N_sample);
ASK_sig = zeros(1,N_sample);
idx1 = 1; %创建索引号
for i = 1:N_sample
idx1 = ceil(Time(i)/t_sig);
if(idx1>PCM_len)
idx1 = PCM_len;
end
msg_sample(i) = PCM_code(idx1);
carrier_sample(i) = cos(2*pi*fc*Time(i)); % 生成载波
ASK_sig(i) = msg_sample(i)*carrier_sample(i); % ASK调制
end
%% 信号在AWGN信道中传输后被接收、解调、译码
demodu_sig = zeros(1,N_sample);
bit_error = zeros(1,length(Eb_N0));
str_error = zeros(1,length(Eb_N0));
SNR = zeros(1,length(Eb_N0));
for indx = 1:length(Eb_N0)
%************信号通过AWGN信道*************%
transf_sig = awgn(ASK_sig,Eb_N0(indx),'measured'); %使信号在AWGN信道下传输
%************将接收的信号进行ASK解调*************%
%% 经过低通滤波器
fm=sig_rate;
at=transf_sig.*cos(2*pi*fc*Time); % 相干解调
s_lpf1=lpf_kasi(Fs,fm,2*fm);
demodu_sig=filtfilt(s_lpf1,1,at);
%*****************信号累加****************%
sum_Decode = sum_decode(demodu_sig,Time,t_sig,PCM_len);
%*****************抽样判决****************%
Judge_code = My_Judge(sum_Decode);
%*******************译码******************%
absolute_decode = Judge_code;
temp_decode = reshape(Judge_code,[],8); %矩阵变换便于PCM解码
PCM_decode = PCMdecoding(temp_decode); %PCM解码
Xn_decode = (PCM_decode/max(abs(PCM_decode)))'; %解码后归一化(数据还原)
%****BPSK调制信号在AWGN信道下的性能分析****%
SNR(indx) = mean(Xn.^2)/mean((Xn_decode-Xn).^2); %PCM量噪比
[error1,bit_error(indx)] = biterr(PCM_code,absolute_decode); %传输信号误比特率
end
snr = 10.^(Eb_N0/10); %%信噪比转换为线性值
bit_err_theo = 0.5.*erfc(sqrt(snr./4)); % 2ASK的理论误比特率
%% 语音播放
sound(x1,fs); %播放原始语音信号
pause(T_end);
sound(Xn_decode,Fs_low); %播放解码译码后的语音信号
%% ------------------------- 画图部分 ---------------------------- %%
%%
%----------------画原始音频信号图-------------%
figure;
[F1,M1]=My_FFT(x1,fs); %对原始信号做FFT变换
Ty = 1/fs;
Time_y = Ty:Ty:T_end;
subplot(2,1,1);
plot(Time_y,x1); %做原始语音信号的时域波形图
title('原始语音信号时域图');
xlabel('时间(t/s)');ylabel('幅值');
subplot(2,1,2);
plot(F1,M1);title('原始语音信号频谱'); %做原始语音信号的频谱图
xlabel('频率(f/Hz)');ylabel('幅度');
clear F1 M1;
%%
%----------画原始基带信号--------%
[F3,M3] = My_FFT(msg_sample,Fs);
[Am1,Freq1] = pwelch(msg_sample,[],[],[],Fs,'centered','power');
Am1_db = 10*log10(Am1);
figure;
subplot(311);
plot(Time,msg_sample);title('基带信号时域波形');
axis([0 1e-2 -2 2]);
xlabel('时间(t/s)');ylabel('幅值');
subplot(312);
plot(F3,M3);title('基带信号的频谱图');
xlabel('频率(f/Hz)');ylabel('幅度');
subplot(313);
plot(Freq1,Am1_db);
title('基带信号的功率谱');
xlabel('Frequency (Hz)');ylabel('Magnitude (dB)');grid;
clear F3 M3;
%%
%--------绘制2ASK已调信号的时域图和频谱图------%
[F6,M6] = My_FFT(ASK_sig,Fs);
[Am4,Freq4] = pwelch(ASK_sig,[],[],[],Fs,'centered','power');
Am4_db = 10*log10(Am4);
figure;
subplot(311);
plot(Time,ASK_sig);
axis([0 1e-2 -2 2]);title('2ASK调制后的信号时域图');
xlabel('时间(t/s)');ylabel('幅值');
subplot(312);
plot(F6,M6);title('2ASK调制后的信号的频谱');
xlabel('频率(f/Hz)');ylabel('幅度');
subplot(313);
plot(Freq4,Am4_db);
title('2ASK调制后的信号的功率谱');
xlabel('Frequency (Hz)');ylabel('Magnitude (dB)');grid;
clear F6 M6 Am4 Am4_db Freq4;
%%
%---------绘制单载波信号的时域图和频谱图--------%
[F7,M7] = My_FFT(carrier_sample,Fs);
[Am5,Freq5] = pwelch(carrier_sample,[],[],[],Fs,'centered','power');
Am5_db = 10*log10(Am5);
figure;
subplot(211);
plot(Time,carrier_sample);
axis([0 1e-3 -2 2]);title('单载波信号时域波形图');
xlabel('时间(t/s)');ylabel('幅值');
subplot(212);
plot(Freq5,Am5_db);
title('单载波信号的功率谱');
xlabel('Frequency (Hz)');ylabel('Magnitude (dB)');grid;
subplot(313);
plot(F7,M7);title('单载波信号的频谱');
xlabel('频率(f/Hz)');ylabel('幅度');
clear F7 M7 Am5_db Am5 Freq5;
%%
%---绘制叠加高斯白噪声的已调信号的时域图和频谱图---%
[F8,M8] = My_FFT(transf_sig,Fs);
[Am6,Freq6] = pwelch(transf_sig,[],[],[],Fs,'centered','power');
Am6_db = 10*log10(Am6);
figure;
subplot(311);
plot(Time,transf_sig);
axis([0 1e-2 -2 2]);title('叠加高斯白噪声的已调信号时域波形图');
xlabel('时间(t/s)');ylabel('幅值');
subplot(312);
plot(F8,M8);title('叠加高斯白噪声的已调信号的频谱');
xlabel('频率(f/Hz)');ylabel('幅度');
subplot(313);
plot(Freq6,Am6_db);
title('叠加高斯白噪声的已调信号的功率谱');
xlabel('Frequency (Hz)');ylabel('Magnitude (dB)');grid;
clear F8 M8 Am6_db Am6 Freq6;
%%
%--------绘制2ASK解调后信号的时域图和频谱图------%
[F9,M9] = My_FFT(demodu_sig,Fs);
[Am7,Freq7] = pwelch(demodu_sig,[],[],[],Fs,'centered','power');
Am7_db = 10*log10(Am7);
figure;
subplot(311);
plot(Time,demodu_sig);
axis([0 1e-2 -2 2]);title('2ASK解调后信号时域波形图');
xlabel('时间(t/s)');ylabel('幅值');
subplot(312);
plot(F9,M9);title('2ASK解调后信号的频谱');
xlabel('频率(f/Hz)');ylabel('幅度');
subplot(313);
plot(Freq7,Am7_db);
title('2ASK解调后信号的功率谱');
xlabel('Frequency (Hz)');ylabel('Magnitude (dB)');grid;
clear F9 M9 Freq7 Am7_db Am7;
%%
recover_sig = zeros(1,N_sample);
idx2 = 1; %创建索引号
for i = 1:N_sample
idx2 = ceil(Time(i)/t_sig);
if(idx2>PCM_len)
idx2 = PCM_len;
end
recover_sig(i) = Judge_code(idx2);
end
%----------解调、抽样判决后恢复信号--------%
[F4,M4] = My_FFT(recover_sig,Fs);
figure;
subplot(211);
plot(Time,recover_sig);title('抽样判决后恢复信号波形');
axis([0 1e-2 -2 2]);
xlabel('时间(t/s)');ylabel('幅值');
subplot(212);
plot(F4,M4);title('抽样判决后恢复信号的频谱图');
xlabel('频率(f/Hz)');ylabel('幅度');
clear F4 M4;
%%
%--------------数字通信系统性能分析-------------%
figure;
semilogy(Eb_N0,bit_error,'-k*',Eb_N0,bit_err_theo,'-bp');
title('2ASK载波调制信号在AWGN信道下的传输性能');
xlabel('信噪比Eb/N0'); ylabel('误比特率/误码率');
legend('仿真误比特率','理论误比特率');
%% 自定义函数
%%-------------自定义函数求fft便于画图-----------%%
function [f,m] = My_FFT(yt,fs)
Fw = abs(fft(yt));
if(iscolumn(yt) || isrow(yt))
Fw = reshape(Fw,1,[]); %变换为行向量便于处理
elseif(size(yt,1)>size(yt,2))
Fw = reshape(Fw,size(yt,2),[]);
end
n = length(yt); %采样点数
if(mod(n,2)==0)
m = [Fw(fix(length(Fw)/2):-1:1),Fw(1:fix(length(Fw)/2))]; %双边谱
else
m = [Fw(fix(length(Fw)/2):-1:1),Fw(1:fix(length(Fw)/2)+1)]; %双边谱
end
m = reshape(m,1,[]);
f = (-n/2:n/2-1)*(fs/n); % 频率范围
end
%% 累加译码函数
function out_code = sum_decode(demodule_sig,Time,bit_period,bit_len)
out_code = zeros(1,bit_len);
temp = 0;
idx_ex = 1;
N_sample = length(Time);
for k = 1:N_sample
idx = ceil(Time(k)/bit_period);
if(idx > bit_len)
idx = bit_len;
end
if(idx == 0)
idx = 1;
end
if(idx > idx_ex)
out_code(idx_ex) = temp;
temp = 0;
idx_ex = idx;
else
temp = temp + demodule_sig(k);
end
if(k == N_sample)
out_code(idx) = temp;
end
end
end
%% PCM编码函数(非均匀量化)
function code = PCMencoding(speech)
% PCM编码
speech1=speech./max(abs(speech)).*2048; %数据量化
speech2=speech1;
LengthOfSpeech=length(speech2);
code = zeros(LengthOfSpeech,8);
for i=1:LengthOfSpeech
if speech2(i)>0 %确定极性码
B1=1;
else
B1=0;
end
speech2(i)=abs(speech2(i));
C=[0 16 32 64 128 256 512 1024 2048];%A律13折现非均匀区间
for j=1:length(C)-1
if speech2(i)>=C(j)&&speech2(i)<=C(j+1)
L=j-1;
L1=dec2bin(L,3);
B2=L1(1);
B2=str2double(B2);
B3=L1(2);
B3=str2double(B3);
B4=L1(3);
B4=str2double(B4);
end
end
a=C(L+1);%确定段内码
b=C(L+2);
[B5,a1,b1]=judge(speech2(i),a,b);
[B6,a2,b2]=judge(speech2(i),a1,b1);
[B7,a3,b3]=judge(speech2(i),a2,b2);
[B8,~,~]=judge(speech2(i),a3,b3);
code(i,1)=B1;
code(i,2)=B2;
code(i,3)=B3;
code(i,4)=B4;
code(i,5)=B5;
code(i,6)=B6;
code(i,7)=B7;
code(i,8)=B8;
end
end
%%
function decode = PCMdecoding(code)
% PCM译码
C2=[0,16;16,32;32,64;64,128;128,256;256,512;512,1024;1024,2048];
step=[1,1,2,4,8,16,32,64];
LengthOfSpeech=size(code,1);
temp = zeros(LengthOfSpeech,3);
for i=1:LengthOfSpeech
temp(i,1)=code(i,1);
temp(i,2)=bin2dec(num2str(code(i,2:4)));
temp(i,3)=bin2dec(num2str(code(i,5:8)));
end
decode = zeros(1,LengthOfSpeech);
for i=1:LengthOfSpeech
decode(i)=C2(temp(i,2)+1,1)+(temp(i,3)+0.5)*step(temp(i,2)+1);
if temp(i,1)==0
decode(i)=-decode(i);
end
end
end
%% 抽样判决函数(硬判决)
function Judge_code = My_Judge(demodule_code)
Judge_code = zeros(1,length(demodule_code));
for i = 1:length(demodule_code)
if(demodule_code(i)>0.5)
Judge_code(i) = 1;
else
Judge_code(i) = 0;
end
end
end
%% PCM编码函数判决
function [B,m1,n1]=judge(I,m,n)
if I>=m&&I<(m+n)/2
B=0;
m1=m;
n1=(m+n)/2;
else
B=1;
m1=(m+n)/2;
n1=n;
end
end
%% Kaiser窗口低通滤波器设计
function lpf = lpf_kasi(fs,fpass,fstop)
fcuts = [fpass fstop]; % 低通,4个参数(结合mags来看):表示(0,1000)区间内通,(1000,1500)过度,(1500,fs/2)内阻;
mags = [1 0]; % 1/0表示通/阻
devs = [0.05 0.01]; % 表示各区段内纹波的波动;
[n,wn,beta,ftype] = kaiserord(fcuts,mags,devs,fs); % Kaiser窗口FIR滤波器设计估算参数
window=kaiser(n+1,beta); % 时域序列,在时域图像上加窗,而在频域上就是卷积了;
lpf = fir1(n,wn,ftype,window,'noscale'); % fir1用来生成滤波器,hh表示n阶滤波器多项式的系数,noscale表示不归一化滤波器的幅度响应;
end