背景
在做调制信号经过小波降噪的时候,发现经过余弦滚降后的调制信号有一部分接近于0,并且小波降噪且解调之后的误码率非常高,经常40%左右,所以进行纠错,发现是群延迟导致误码率升高。
使用filter函数
BPSK信号调制
clc, clear, close all;
% 设置参数
M = 2; % BPSK 调制阶数
oversampling_factor = 16; % 上采样倍数
SNR_dB = -5; % 信噪比 (dB)
% 生成数据并调制
data = [1,0,0,1,1,0,0,1,0,0,1,0,0,0,1,1];
txSig = pskmod(data, M); % BPSK调制
根升余弦滤波器(filter在这里使用)
% 应用根升余弦滤波器(脉冲成形)
span = 6; % 滤波器跨度
rolloff = 0.35; % 滚降因子
rctfilt = rcosdesign(rolloff, span, oversampling_factor, 'sqrt');
% 先上采样再滤波
txSig_upsampled = upsample(real(txSig), oversampling_factor); % 上采样
txSig_shaped = filter(rctfilt, 1, txSig_upsampled); % 应用根升余弦滤波器
% 添加噪声以达到指定的信噪比
rxSig_noisy = awgn(txSig_shaped, SNR_dB, 'measured');
小波降噪
% 使用 wpdencmp 函数进行小波包去噪
[thr,sorh,keepapp,crit] = ddencmp('den','wp',rxSig_noisy);
% thr = thselect(rxSig_noisy,'heursure');
[xd3, perf0_3, perfl2_3] = wpdencmp(rxSig_noisy, 's', 4, 'sym8', 'sure', thr, 1);
[xd6, perf0_6, perfl2_6] = wpdencmp(rxSig_noisy, 's', 6, 'sym8', 'sure', thr, 1);
结果可视化
% 可视化结果
figure;
subplot(5, 1, 1);
stem((0:length(data) - 1), data, 'filled');
title('原始基带数据');
xlabel('符号序号');
ylabel('幅度');
subplot(5, 1, 2);
plot(txSig_shaped);
title('原始调制信号(经过脉冲成形)');
xlabel('样本点');
ylabel('幅度');
subplot(5, 1, 3);
plot(rxSig_noisy);
title(['含噪声信号(信噪比 ', num2str(SNR_dB), ' dB)']);
xlabel('样本点');
ylabel('幅度');
subplot(5, 1, 4);
plot(xd3);
title('3层小波包去噪后的信号');
xlabel('样本点');
ylabel('幅度');
subplot(5, 1, 5);
plot(xd6);
title('6层小波包去噪后的信号');
xlabel('样本点');
ylabel('幅度');
解调并计算误码率
% 解调信号前先降采样和匹配滤波
xd3_matched = filter(rctfilt, 1, xd3);
xd6_matched = filter(rctfilt, 1, xd6);
% 降采样回原始符号速率
xd3_downsampled = downsample(xd3_matched, oversampling_factor);
xd6_downsampled = downsample(xd6_matched, oversampling_factor);
% 解调信号
dataOut_3 = pskdemod(xd3_downsampled, M);
dataOut_6 = pskdemod(xd6_downsampled, M);
% 计算误码率
[~, ber_3] = symerr(data, dataOut_3);
[~, ber_6] = symerr(data, dataOut_6);
disp(['3层小波包去噪后误码率: ', num2str(ber_3)]);
disp(['6层小波包去噪后误码率: ', num2str(ber_6)]);
代码运行结果
可以发现,“原始调制信号(经过脉冲成型)”这个图像,在前35个点都非常接近于0。
尽管此时3层小波去噪信号与原始调制信号比较相像,但是经过解调之后,计算误码率为0.5,误码率较高。
使用conv函数
代码格式与上面相似,将filter更改为conv。
代码片段1
clc, clear, close all;
% 设置参数
M = 2; % BPSK 调制阶数
oversampling_factor = 16; % 上采样倍数
SNR_dB = -5; % 信噪比 (dB)
% 生成数据并调制
data = [1,0,0,1,1,0,0,1,0,0,1,0,0,0,1,1];
txSig = pskmod(data, M); % BPSK调制
% 应用根升余弦滤波器(脉冲成形)
span = 6; % 滤波器跨度
rolloff = 0.35; % 滚降因子
rctfilt = rcosdesign(rolloff, span, oversampling_factor, 'sqrt');
根升余弦滤波器(conv在这里使用)
% 先上采样再滤波
txSig_upsampled = upsample(real(txSig), oversampling_factor); % 上采样
% txSig_shaped = filter(rctfilt, 1, txSig_upsampled); % 应用根升余弦滤波器
txSig_shaped = conv(txSig_upsampled, rctfilt);
delay = round(mean(grpdelay(rctfilt))); % 计算系统群延迟
txSig = txSig_shaped(delay + 1:end - delay); % 去除滤波器引入的延迟
代码片段2
figure;
subplot(6, 1, 1);
stem(data, 'filled'); % 原始基带数据
title('data');
xlabel('样本点');
ylabel('Amplitude');
subplot(6, 1, 2);
plot(0:length(txSig) - 1,txSig); % 原始调制信号
title('modulated signal');
xlabel('样本点');
ylabel('Amplitude');
xlim([0,255]);
grid on;
% 添加噪声以达到指定的信噪比
rxSig_noisy = awgn(txSig, SNR_dB, 'measured');
% 使用 wpdencmp 函数进行小波包去噪
% 参数解释:
% 's' 表示软阈值处理。
% 'wp' 表示使用wavelet packets
% 'sym8' 是所选的小波基。
% 3 和 6 分别表示分解的层数。
[thr,sorh,keepapp,crit] = ddencmp('den','wp',rxSig_noisy);
% thr = thselect(rxSig_noisy,'heursure');
[xd3, perf0_3, perfl2_3] = wpdencmp(rxSig_noisy, 's', 4, 'sym8', 'sure', thr, 1);
[xd6, perf0_6, perfl2_6] = wpdencmp(rxSig_noisy, 's', 6, 'sym8', 'sure', thr, 1);
subplot(6, 1, 3);
plot(rxSig_noisy);
title(['含噪声信号(信噪比 ', num2str(SNR_dB), ' dB)']);
xlabel('样本点');
ylabel('幅度');
xlim([0,255]);
subplot(6, 1, 4);
plot(xd3);
title('3层小波包去噪后的信号');
xlabel('样本点');
ylabel('幅度');
xlim([0,255]);
subplot(6, 1, 5);
plot(xd6);
title('6层小波包去噪后的信号');
xlabel('样本点');
ylabel('幅度');
xlim([0,255]);
匹配滤波 (conv在这里使用)
% 解调信号前先降采样和匹配滤波
% xd3_matched = filter(rctfilt, 1, xd3);
% xd6_matched = filter(rctfilt, 1, xd6);
% rxSig_noisy = filter(rctfilt, 1, rxSig_noisy);
xd3_matched = conv(rctfilt,xd3);
xd6_matched = conv(rctfilt,xd6);
rxSig_noisy = conv(rctfilt, rxSig_noisy);
xd3_matched = xd3_matched(1 + delay:end - delay);
xd6_matched = xd6_matched(1 + delay:end - delay);
rxSig_noisy = rxSig_noisy(1 + delay:end - delay);
代码片段3
% 降采样回原始符号速率
xd3_downsampled = downsample(xd3_matched, oversampling_factor);
xd6_downsampled = downsample(xd6_matched, oversampling_factor);
% rxSig_noisy1 = downsample(rxSig_noisy1 ,oversampling_factor);
txSig_shaped = downsample(rxSig_noisy, oversampling_factor);
% 解调信号
dataOut_3 = pskdemod(xd3_downsampled, M);
dataOut_6 = pskdemod(xd6_downsampled, M);
dataOut_txSig = pskdemod(txSig_shaped, M);
% 计算误码率
[numErrs_3, ber_3] = symerr(data, dataOut_3);
[numErrs_6, ber_6] = symerr(data, dataOut_6);
subplot(6, 1, 6);
stem(dataOut_3, 'filled');
xlabel('样本点');
ylabel('Amplitude');
title('3层小波降噪解调');
disp(['3层小波包去噪后误码率: ', num2str(ber_3)]);
disp(['6层小波包去噪后误码率: ', num2str(ber_6)]);
代码运行结果
运行以上代码可以发现,基带已调信号的前35个点不再趋近于0,且此时3层小波降噪误码率为0。
filter与conv结果不同的原因
前提
在以上代码片段中,是通过根升余弦滤波器(rcosdesign函数)进行成型滤波的。并且,在matlab里面,rcosdesign函数是自带线性相位的(我验证并且通义千问的结果是这样的)。
对于线性相位滤波器,他的群延迟是(N-1)/2,其中N是滤波器阶数。上面这个例子中N=97,所以群延迟为48。
对于filter
filter:
- 返回与输入信号相同长度的输出:输入信号txSig_upsampled与输出结果txSig_shaped的length都是1x256。
- 隐含地考虑了群延迟,但边界样本可能受边界效应影响。(通义千问说考虑了群延迟,但是该代码背景中仍然需要裁剪)
但是因为群延迟为48,所以前面48个数据是不可用的,需要删掉。因此有用数据大小为256-48=208。
因为包含不可用数据,所以会影响BPSK解调,进而提高误码率。
对于conv
conv:
- 返回一个比输入信号长的结果(长度为 N+M−1),其中 NN是输入信号长度,M 是滤波器长度。xd3为1x256,经过conv之后xd3_matched的大小是97+256-1=352。
- 需要手动裁剪以匹配滤波器的群延迟效果。
但是因为群延迟,前面48与最后面48个数据点不可用,需要删除。
因此有用数据大小为256。此时全部是有用数据,因此误码率降低。
filter更加详细讲解
在matlab官方文档中给出范例
openExample('signal/CompensateForTheDelayIntroducedByAFilterExample')
经过filter,但是未补偿群延迟,可以发现滤波信号与原始信号之间有明显的延迟。图像如下:
打开该文档之后,我们关注最后一个代码块,即:
plot(tt,sn)
hold on, plot(tt,sf,'-r','linewidth',1.5), hold off
title 'Electrocardiogram'
xlabel('Time (s)'), legend('Original Signal','Filtered Shifted Signal')
补偿群延迟后图像:
可以看出,tt与sf的length都为465,是因为把前面35个无用数据删掉了。
当我们把Original Signal绘制完整,也就是把tt更改为tn,sn更改为xn。此时图像如下:
可以发现filter有用信号只有[1+delay:end]
plot(tn,xn)
hold on, plot(tt,sf,'-r','linewidth',1.5), hold off
title 'Electrocardiogram'
xlabel('Time (s)'), legend('Original Signal','Filtered Shifted Signal')