文章目录
- 前言
- 一、维纳滤波推导
-
- 1.维纳滤波的介绍
-
- 1)目标
- 2)原理
- 2.公式推导
-
- 1)均方误差展开
- 2)函数求导
- 3)互功率谱代入
- 4)信号功率谱代入
- 5)最终维纳滤波器公式
- 3.SNR形式
- 4.物理意义
- 二、维纳滤波器的变种
-
- 1.平方根维纳滤波器
- 2.参变维纳滤波器
- 三、维纳滤波器实现
-
- 1.源码
-
- 1)整体流程
- 2)代码实现
- 2.结果
-
- 1)维纳滤波效果
- 2)与过减法比较
- 总结
前言
在语音降噪领域,有一个几乎所有算法都会用到的核心工具:维纳滤波(Wiener Filter)。例如:WebRTC降噪、Kaldi降噪、甚至很多深度学习模型的前端,本质上仍然使用维纳滤波思想。
但很多文章只给出一个公式:
H
(
ω
)
=
S
x
x
/
(
S
x
x
+
S
v
v
)
H(\\omega)=S_{xx}/(S_{xx}+S_{vv})
H(ω)=Sxx/(Sxx+Svv)
却很少有人真正讲清楚:
1 这个公式是怎么推导出来的 2 为什么要对
H
(
ω
)
H(\\omega)
H(ω) 求导 3 为什么最后会变成
S
N
R
/
(
1
+
S
N
R
)
SNR/(1+SNR)
SNR/(1+SNR) 4 工程代码到底怎么实现
这篇文章会完整回答这些问题: 从 数学推导 → 算法理解 → MATLAB实现 → 实际效果 一步步讲透维纳滤波。
一、维纳滤波推导
1.维纳滤波的介绍
1)目标
维纳滤波器(Wiener Filter)的目标是:从观测信号
y
[
n
]
y[n]
y[n]中恢复原始信号
x
[
n
]
x[n]
x[n]。
通常假设:
-
x
[
n
]
x[n]
x[n]:原始纯净信号 -
v
[
n
]
v[n]
v[n]:噪声 -
y
[
n
]
y[n]
y[n]:观测信号 - 噪声和信号不相关
目标是设计一个滤波器
H
(
ω
)
H(ω)
H(ω),使得输出:
x
^
[
n
]
=
h
[
n
]
∗
y
[
n
]
\\hat{x}[n]=h[n]*y[n]
x^[n]=h[n]∗y[n]
类似于如下:
x(n) —-\\
+—-> y(n) —-> Wiener Filter —-> x^(n)
v(n) —-/
2)原理
维纳滤波的核心思想是最小均方误差(MMSE):使得滤波器的实际输出与期望输出之间的均方误差最小。
J
=
E
{
∣
x
[
n
]
−
x
^
[
n
]
∣
2
}
J=E\\{|x[n]-\\hat{x}[n]|^2\\}
J=E{∣x[n]−x^[n]∣2} 转换到频域:
X
^
(
ω
k
)
=
H
(
ω
k
)
Y
(
ω
k
)
\\hat{X}(\\omega_k)=H(\\omega_k)Y(\\omega_k)
X^(ωk)=H(ωk)Y(ωk) 其中误差为(
e
e
e表示误差,
E
E
E表示期望):
e
(
ω
k
)
=
X
(
ω
k
)
−
H
(
ω
k
)
Y
(
ω
k
)
e(\\omega_k)=X(\\omega_k)-H(\\omega_k)Y(\\omega_k)
e(ωk)=X(ωk)−H(ωk)Y(ωk) 其优化公式:
J
=
E
{
∣
X
(
ω
k
)
−
H
(
ω
k
)
Y
(
ω
k
)
∣
2
}
J=E\\{|X(\\omega_k)-H(\\omega_k)Y(\\omega_k)|^2\\}
J=E{∣X(ωk)−H(ωk)Y(ωk)∣2} 如同下图:

2.公式推导
1)均方误差展开
由上文得到优化公式:
E
[
∣
e
(
ω
k
)
∣
2
]
=
E
{
∣
X
(
ω
k
)
−
H
(
ω
k
)
Y
(
ω
k
)
∣
2
}
E[|e(\\omega_k)|^2]=E\\{|X(\\omega_k)-H(\\omega_k)Y(\\omega_k)|^2\\}
E[∣e(ωk)∣2]=E{∣X(ωk)−H(ωk)Y(ωk)∣2} 为了方便起见,省去
ω
k
\\omega_k
ωk。并且展开为共轭形式:
J
=
E
{
(
X
−
H
Y
)
(
X
−
H
Y
)
∗
}
J=E\\{(X-HY)(X-HY)^*\\}
J=E{(X−HY)(X−HY)∗} 展开:
J
=
E
{
X
X
∗
−
X
(
H
Y
)
∗
−
H
Y
(
X
)
∗
+
H
Y
(
H
Y
)
∗
}
J=E\\{XX^*-X(HY)^*-HY(X)^*+HY(HY)^*\\}
J=E{XX∗−X(HY)∗−HY(X)∗+HY(HY)∗} 整理:
J
=
E
{
∣
X
∣
2
}
−
H
∗
E
{
X
Y
∗
}
−
H
E
{
Y
X
∗
}
+
∣
H
∣
2
E
{
∣
Y
∣
2
}
J=E\\{|X|^2\\}-H^*E\\{XY^*\\}-HE\\{YX^*\\}+|H|^2E\\{|Y|^2\\}
J=E{∣X∣2}−H∗E{XY∗}−HE{YX∗}+∣H∣2E{∣Y∣2} 此时,定义功率谱:
-
S
x
x
=
E
{
∣
X
∣
2
}
S_{xx}=E\\{|X|^2\\}
Sxx=E{∣X∣2} -
S
y
y
=
E
{
∣
Y
∣
2
}
S_{yy}=E\\{|Y|^2\\}
Syy=E{∣Y∣2} -
S
x
y
=
E
{
X
Y
∗
}
S_{xy}=E\\{XY^*\\}
Sxy=E{XY∗} -
S
y
x
=
E
{
X
∗
Y
}
S_{yx}=E\\{X^*Y\\}
Syx=E{X∗Y}
则上式为:
J
=
S
x
x
−
H
∗
S
x
y
−
H
S
y
x
+
∣
H
∣
2
S
y
y
J=S_{xx}-H^*S_{xy}-HS_{yx}+|H|^2S_{yy}
J=Sxx−H∗Sxy−HSyx+∣H∣2Syy
2)函数求导
已知我们需要最小均方误差函数
J
J
J的值最小,那么函数的变化趋势会“停止上升或下降”,此时导数也就是斜率应该为0,而我们最终需要的是
H
(
ω
k
)
H(\\omega_k)
H(ωk):
∂
J
∂
H
∗
=
H
∗
S
y
y
−
S
y
x
=
[
H
S
y
y
−
S
x
y
]
∗
=
0
\\frac{\\partial J}{\\partial H^*}=H^*S_{yy}-S_{yx}=[HS_{yy}-S_{xy}]^*=0
∂H∗∂J=H∗Syy−Syx=[HSyy−Sxy]∗=0 对其求解:
H
(
ω
k
)
=
S
x
y
(
ω
k
)
S
y
y
(
ω
k
)
H(\\omega_k)=\\frac{S_{xy}(\\omega_k)}{S_{yy}(\\omega_k)}
H(ωk)=Syy(ωk)Sxy(ωk)
3)互功率谱代入
展开
S
x
y
S_{xy}
Sxy
S
x
y
=
E
{
X
(
X
+
V
)
∗
}
=
E
{
∣
X
∣
2
}
+
E
{
X
V
∗
}
S_{xy}=E\\{X(X+V)^*\\}=E\\{|X|^2\\}+E\\{XV^*\\}
Sxy=E{X(X+V)∗}=E{∣X∣2}+E{XV∗} 由于假设噪声和信号不相关,即
E
{
X
V
∗
}
=
0
E\\{XV^*\\}=0
E{XV∗}=0,所以:
S
x
y
=
S
x
x
S_{xy}=S_{xx}
Sxy=Sxx
4)信号功率谱代入
由
S
y
y
=
E
{
∣
X
+
V
∣
2
}
S_{yy}=E\\{|X+V|^2\\}
Syy=E{∣X+V∣2} 将互功率谱代入
E
{
X
V
∗
}
=
0
E\\{XV^*\\}=0
E{XV∗}=0,展开得:
S
y
y
=
S
x
x
+
S
v
v
S_{yy}=S_{xx}+S_{vv}
Syy=Sxx+Svv
5)最终维纳滤波器公式
H
(
ω
k
)
=
S
x
x
(
ω
k
)
S
x
x
(
ω
k
)
+
S
v
v
(
ω
k
)
H(\\omega_k)=\\frac{S_{xx}(\\omega_k)}{S_{xx}(\\omega_k)+S_{vv}(\\omega_k)}
H(ωk)=Sxx(ωk)+Svv(ωk)Sxx(ωk)
3.SNR形式
定义信噪比:
S
N
R
(
ω
k
)
=
S
x
x
(
ω
k
)
S
v
v
(
ω
k
)
SNR(\\omega_k)=\\frac{S_{xx}(\\omega_k)}{S_{vv}(\\omega_k)}
SNR(ωk)=Svv(ωk)Sxx(ωk) 则上式为:
H
(
ω
k
)
=
S
N
R
1
+
S
N
R
H(\\omega_k)=\\frac{SNR}{1+SNR}
H(ωk)=1+SNRSNR
4.物理意义
维纳滤波器本质是 按信噪比加权:
| 很大 | ≈1 | 保留信号 |
| 很小 | ≈0 | 抑制噪声 |
所以它本质上是一个 自适应频谱抑制器。
二、维纳滤波器的变种
维纳滤波在语音增强中主要有三类:
| 经典 Wiener |
S N R / ( 1 + S N R ) SNR/(1+SNR) SNR/(1+SNR) |
| Square-root Wiener |
( S N R / ( 1 + S N R ) ) \\sqrt{(SNR/(1+SNR))} (SNR/(1+SNR)) |
| Parametric Wiener |
( S N R / ( α + S N R ) ) β (SNR/(α+SNR))^β (SNR/(α+SNR))β |
1.平方根维纳滤波器
顾名思义,对于维纳滤波器使用平方根:
X
^
(
ω
k
)
=
H
(
ω
k
)
Y
(
ω
k
)
\\hat{X}(\\omega_k)=\\sqrt{H(\\omega_k)}Y(\\omega_k)
X^(ωk)=H(ωk)
Y(ωk) 此时我们关注功率的表现:
E
∣
X
^
(
ω
k
)
∣
2
=
H
(
ω
k
)
E
∣
Y
(
ω
k
)
∣
2
E|\\hat{X}(\\omega_k)|^2=H(\\omega_k)E|Y(\\omega_k)|^2
E∣X^(ωk)∣2=H(ωk)E∣Y(ωk)∣2 即:
S
x
^
x
^
=
H
(
ω
k
)
S
y
y
(
ω
k
)
S_{\\hat{x}\\hat{x}}=H(\\omega_k)S_{yy}(\\omega_k)
Sx^x^=H(ωk)Syy(ωk) 将
H
(
ω
k
)
H(\\omega_k)
H(ωk)代入:
S
x
^
x
^
=
S
x
x
(
ω
k
)
S
x
x
(
ω
k
)
+
S
v
v
(
ω
k
)
S
y
y
(
ω
k
)
S_{\\hat{x}\\hat{x}}=\\frac{S_{xx}(\\omega_k)}{S_{xx}(\\omega_k)+S_{vv}(\\omega_k)}S_{yy}(\\omega_k)
Sx^x^=Sxx(ωk)+Svv(ωk)Sxx(ωk)Syy(ωk)
由于假设信号和噪声不相关,所以
S
y
y
(
ω
k
)
=
S
x
x
(
ω
k
)
+
S
v
v
(
ω
k
)
S_{yy}(\\omega_k)=S_{xx}(\\omega_k)+S_{vv}(\\omega_k)
Syy(ωk)=Sxx(ωk)+Svv(ωk),所以上式简化为:
S
x
^
x
^
=
S
x
x
(
ω
k
)
S
x
x
(
ω
k
)
+
S
v
v
(
ω
k
)
(
S
x
x
(
ω
k
)
+
S
v
v
(
ω
k
)
)
=
S
x
x
(
ω
k
)
S_{\\hat{x}\\hat{x}}=\\frac{S_{xx}(\\omega_k)}{S_{xx}(\\omega_k)+S_{vv}(\\omega_k)}(S_{xx}(\\omega_k)+S_{vv}(\\omega_k))=S_{xx}(\\omega_k)
Sx^x^=Sxx(ωk)+Svv(ωk)Sxx(ωk)(Sxx(ωk)+Svv(ωk))=Sxx(ωk)
所以我们得到了,平方根维纳滤波器的输出功率谱和纯净噪声功率谱相等,即
平方根维纳滤波器是一种无偏功率谱估计器。
2.参变维纳滤波器
在传统维纳滤波器公式的基础上,我们想更灵活一点
ξ
k
=
S
N
R
(
ω
k
)
\\xi_k=SNR(\\omega_k)
ξk=SNR(ωk):
H
(
ω
k
)
=
(
ξ
k
α
+
ξ
k
)
β
H(\\omega_k)=\\Big(\\frac{\\xi_k}{\\alpha+\\xi_k}\\Big)^\\beta
H(ωk)=(α+ξkξk)β 如果能在先验的情况下获得频带特征,例如噪声主要集中在哪些频带,这样就可以灵活的设置不同的衰减,或者设置对于整体能量的衰减程度,例如:
- 当
α
=
β
=
1
\\alpha=\\beta=1
α=β=1:传统滤波器 - 当
α
=
1
,
β
=
1
/
2
\\alpha=1,\\beta=1/2
α=1,β=1/2:平方根维纳滤波器
对于不同的
α
\\alpha
α和
β
\\beta
β对于
H
(
ω
)
H(\\omega)
H(ω)的影响如下: 
三、维纳滤波器实现
1.源码
1)整体流程

2)代码实现
function simple_wiener(noisyfile, outfile)
[noisy, fs] = audioread(noisyfile);
% 参数
frame_len = 256;
hop = frame_len/2;
win = hamming(frame_len);
% 前100ms作为噪声
noise_len = round(0.1 * fs);
noise = noisy(1:noise_len);
% 估计噪声功率谱
noise_ps = zeros(frame_len,1);
count = 0;
for i = 1:hop:length(noise)–frame_len
frame = noise(i:i+frame_len–1).*win;
spec = fft(frame);
noise_ps = noise_ps + abs(spec).^2;
count = count + 1;
end
noise_ps = noise_ps / count;
% 输出信号
out = zeros(size(noisy));
overlap = zeros(hop,1);
ptr = 1;
while ptr+frame_len–1 <= length(noisy)
frame = noisy(ptr:ptr+frame_len–1).*win;
spec = fft(frame);
noisy_ps = abs(spec).^2;
% 估计语音功率谱
speech_ps = noisy_ps – noise_ps;
speech_ps(speech_ps<0) = 0;
% Wiener滤波器
H = speech_ps ./ (speech_ps + noise_ps + 1e-10);
% 滤波
enhanced_spec = H .* spec;
enhanced = real(ifft(enhanced_spec));
% overlap-add
out(ptr:ptr+hop–1) = overlap + enhanced(1:hop);
overlap = enhanced(hop+1:end);
ptr = ptr + hop;
end
out(ptr:ptr+hop–1) = overlap;
audiowrite(outfile, out, fs);
end
2.结果
1)维纳滤波效果

左图为带噪语音,右图为维纳滤波后的语音,可以明显看到经过维纳滤波之后,各个频点的噪声能量被衰减
2)与过减法比较

左图是经过维纳滤波后的语音,右图是经过过减法的语音,对比可以直观发现,在某些频点上,过减法会无差别进行减法处理,也就是会丧失了某些语音信息
总结
维纳滤波其实揭示了一个非常重要的思想:
语音增强本质上不是“去掉噪声”, 而是根据 信噪比重新分配频谱能量。
这也是为什么:
- Wiener Filter
- Ephraim-Malah
- Log-MMSE
- WebRTC NS
这些经典算法,本质上都围绕着 SNR估计 + 增益函数 展开。
理解了维纳滤波, 基本就理解了 一半语音降噪算法的核心思想。
如果本文对你理解维纳滤波器有所帮助,欢迎点赞、收藏或留言交流。

