以前有类似主题的文章。
Review:普通LMS对噪声的抑制
Review:有辅助数据的维纳滤波噪声消除
这一篇讲的是,如果有辅助数据,用LMS算法对信号滤波去噪的一个应用示例。
注意,现在的信噪比已经只有-40dB了!噪声功率是信号功率的1万倍!
模型还是这样的。v2是在离噪声源很近的地方,采集到的噪声(因此可以假设它就是v)。
v1是因为噪声源发出的噪声v,经过了一段信道传输以后,发生了一些变化,因此变成了v1。
%% 基于LMS算法,有辅助数据的噪声消除
% 作者:qcy
% 版本:v1.0
% 时间:2016年10月30日15:39:25
%%
close all;clear; clc;
%% 导入音频
filedir=[]; % 设置路径
filename='bluesky1.wav'; % 设置文件名
fle=[filedir filename]; % 构成完整的路径和文件名
[s, fs] = audioread(fle); % 读入数据文件
s=s-mean(s); % 消除直流分量
s=s/max(abs(s)); % 幅值归一
N=length(s); % 语音长度
time=(0:N-1)/fs; % 设置时间刻度
%% 生成噪声
SNR = -40; % 设置信噪比
r2=randn(size(s)); % 产生随机噪声
b=fir1(31,0.5); % 设计FIR滤波器,代替H
r21=filter(b,1,r2); % FIR滤波
[r1,r22]=add_noisedata(s,r21,fs,fs,SNR);% 产生带噪语音,信噪比为SNR
%% LMS滤波
h_length = 35;
h = zeros(h_length,1); % 滤波器的初始化
miu = 8e-4;
v1_hat = zeros(size(s));
err2 = zeros(size(s));
y_output = r1;
% 开始滤波
for kk = 1:1 % 这里设置滤波过程需要重复几次。
for k = h_length : N
idx = k: -1 :(k-h_length+1);
r2_in_sub = r2(idx); % 参考噪声 --> 原始噪声
v1_hat_out = h.' * r2_in_sub; % 由 原始噪声估计的 --> 信号中的噪声
v1_hat(k) = v1_hat_out;
dk = r1(k); % 观察到的含噪语音,是参考信号
err = dk - v1_hat_out;
err2(k) = err^2;
h = h + miu * err * r2_in_sub;
y_output(k) = y_output(k) - v1_hat_out;
end
end
% 误差平方
figure;
plot(err2);
%% 滤波器的幅频特性
[H,w] = freqz(h,1,1e4);
figure;
plot(w/2/pi*fs,20*log10(abs(H)/max(abs(H))+eps));
xlabel('频率(Hz)');
%% 计算信噪比的提升
snr1=SNR_singlech(s,r1); % 计算初始信噪比
snr2=SNR_singlech(s,y_output); % 计算滤波后的信噪比
snr=snr2-snr1;
SN1=snr1; SN2=snr2; SN3=snr;
%% 打印SNR
fprintf('[LMS]\n',snr1);
fprintf('滤波前 SNR = %f [dB] \n',snr1);
fprintf('滤波后 SNR = %f [dB] \n',snr2);
fprintf('提升 %f [dB] \n',snr);
%% 听效果
% sound(s,fs); % 干净的语音
% sound(r1,fs); % 含噪的语音
sound(y_output,fs); % 滤波后的语音
%% 作图
figure;
subplot 311; plot(time,s); ylabel('幅值')
ylim([-1 1 ]); title('原始语音信号');
subplot 312; plot(time,r1); ylabel('幅值')
ylim([-100 100]); title('带噪语音信号');
subplot 313; plot(time,y_output);
ylim([-1 1 ]); title('LMS滤波输出语音信号');
xlabel('时间/s'); ylabel('幅值');
可以看出,原始语音信号已经完全淹没在噪声中了。在这么恶劣的条件下,竟然能分辨出微弱的有用信号,
在以前简直是不可想象的。感谢伟大的科学家与工程师们。
LMS算法对滤波器进行更新,当滤波器系数收敛(基本不变)后,
可以看看这个滤波器的幅频特性。
由于有用信号是语音信号(300 Hz - 3400 Hz),我们的最优滤波器也很符合逻辑地显示出其低通特性。
听一听效果,真是不错。
但,还是以前说的,
1. 需要另外增加一个信号采集装置,增加成本;
2. 这个额外的信号采集装置还要能很好地接收到基本纯净的噪声或通过一定线性信道(我们用的FIR滤波器)的噪声;
这两个因素,能不能实现,就要具体情况具体分析了。