天天看点

音频噪声抑制(4):普通最小均方误差(LMS)算法引言LMS滤波器基本原理举例:噪声抑制

引言

前面讲了基于Weiner滤波器的噪声抑制方法。

Reivew:用维纳滤波器实现噪声抑制

维纳滤波器有一些假设条件,比如信号平稳(这就导致解方程算滤波器系数的时候,自相关矩阵与绝对时间无关)、噪声和有用信号不相关…

其实,这些条件在实际中并不是那么容易满足的。

因此,用维纳滤波器来实现信号去噪,效果不是特别理想。

于是就有人提出自适应滤波器,“自动”去更新滤波器的系数,使它自己去“适应”信号的一些特性。

自适应滤波器有许多种,这里挑最简单的基于“最小均方误差”准则的自适应滤波器来讲了。

LMS滤波器基本原理

原理的话,每一本现代信号处理的书上都讲得很清楚了。 归根结底:这是一个需要“训练”(或者说“学习”)的滤波器,在“学习”的过程中,希望把滤波器的输出与期望信号(训练信号)之差,作为算法的反馈, 不断地更新滤波器的系数,以使得在某种意义下,实现最优滤波。 LMS,顾名思义,最小均方误差。 另外,利用梯度下降法,可以简单地求出目标函数(均方误差是关于滤波器系数w)的极值。 一系列简单推导,可得出LMS算法。

音频噪声抑制(4):普通最小均方误差(LMS)算法引言LMS滤波器基本原理举例:噪声抑制

w是滤波器系数, x是滤波器输入, d是训练信号, x和w的内积(滤波器与输入信号的卷积)是滤波器的输出, u是步长(1个正数)。

理论上,u越小,最终求出的极值点结果越精确,但所需要达到极值点的时间就变长了。 有最优的一个u,但其实吧,我感觉也就是理论上提供一种可能性,意思是, u在每一次迭代的过程中,在理论上都有个最优值。 但实际上,为了求最优值,又需要一大堆的已知条件,而这些条件其实并不是那么好“知道”; 就算是知道了,求最优的u,也会耗费大量的时间。 所以,自己看着办了…… 有资料建议,

音频噪声抑制(4):普通最小均方误差(LMS)算法引言LMS滤波器基本原理举例:噪声抑制

滤波器阶数,初值,自己设置了。有可能陷入局部极值。这不知道了。试,效果出来就OK了。 Tail & error。

举例:噪声抑制

1. LMS的训练过程。

%% LMS滤波去噪
% 作者:qcy
% 版本号:v1.0
% 版本说明:本M文件提供训练阶段。
% 时间:2016年10月29日19:02:44

% 好像提升并不是很明显啊!!
% why...?????? and 如何改进???
%【问】 是不是不应该用非语音段进行滤波???

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 = 5;                                % 设置信噪比
r2=randn(size(s));                      % 产生随机噪声
b=fir1(32,0.5);                         % 设计FIR滤波器,代替H
r21=filter(b,1,r2);                     % FIR滤波
[r1,r22]=add_noisedata(s,r21,fs,fs,SNR);% 产生带噪语音,信噪比为SNR 

%% 训练阶段
h_length = 100;
h = zeros(h_length,1); % 滤波器的初始化
miu = 1e-4;

y_out = zeros(size(s));
Ntimes = 3;
err2 = zeros(length(s)*Ntimes,1);
counter = 1;
% 开始滤波
for kk = 1:Ntimes
    for k = h_length : N
        idx = k: -1 :(k-h_length+1);
        r1_in_sub = r1(idx);
        filter_out = h.' * r1_in_sub;
        y_out(k) = filter_out;
        dk = s(k);
        err = dk - filter_out;
        err2(counter) = err^2;
        h = h + miu * err * r1_in_sub;
        counter = counter + 1;
    end
end


% sound(s,fs);
% sound(r1,fs);
% sound(y_out,fs);

%% 作图
figure
plot(err2);
grid on;
title('均方误差');

figure;
subplot 311; plot(time,s,'k'); ylabel('幅值') 
ylim([-1 1 ]); title('原始语音信号');
subplot 312; plot(time,r1,'k'); ylabel('幅值') 
ylim([-1 1 ]); title('带噪语音信号');
subplot 313; plot(time,y_out,'k'); 
ylim([-1 1 ]); title('LMS滤波输出语音信号');
xlabel('时间/s'); ylabel('幅值')
           

尽管听起来,似乎有一定的改良,但是去噪效果还是不明显! 我暂时不知道为什么。而且,很多书上都回避了普通LMS来去噪的例子。 连去噪前后信号波形图都没有给出。更不要说什么均方误差了。

我在想,是不是在训练的过程中,整个语音信号中,说话不能有停顿啊? 从我的均方误差的图中,似乎看得出来,似乎有一个逐渐变小的过程,但是突然又会变大。 假设,期望信号中,有非常微弱的部分(说话间隙),基本就是0了。 这时滤波器为了让均方误差最小,是不是系数要全为0啊? 那这样的训练过程…… 是不是最终导致去噪效果不佳的原因?

音频噪声抑制(4):普通最小均方误差(LMS)算法引言LMS滤波器基本原理举例:噪声抑制
音频噪声抑制(4):普通最小均方误差(LMS)算法引言LMS滤波器基本原理举例:噪声抑制

所以,是不是还需要做一个端点检测,把真正的语音段全部提取出来,以此作为训练信号呢?

继续阅读