欢迎光临
我们一直在努力

一句话讲透维纳滤波:从公式推导到语音降噪完整实现(附MATLAB代码)

文章目录

  • 前言
  • 一、维纳滤波推导
    • 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{(XHY)(XHY)} 展开:

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{XXX(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{X2}HE{XY}HE{YX}+H2E{Y2} 此时,定义功率谱:

  • S

    x

    x

    =

    E

    {

    X

    2

    }

    S_{xx}=E\\{|X|^2\\}

    Sxx=E{X2}

  • S

    y

    y

    =

    E

    {

    Y

    2

    }

    S_{yy}=E\\{|Y|^2\\}

    Syy=E{Y2}

  • 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{XY}

则上式为:

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=SxxHSxyHSyx+H2Syy

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

HJ=HSyySyx=[HSyySxy]=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{X2}+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+V2} 将互功率谱代入

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.物理意义

维纳滤波器本质是 按信噪比加权:

SNRH(ω)含义
很大 ≈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

EX^(ωk)2=H(ωk)EY(ω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_len1).*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_len1 <= length(noisy)

frame = noisy(ptr:ptr+frame_len1).*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+hop1) = overlap + enhanced(1:hop);
overlap = enhanced(hop+1:end);

ptr = ptr + hop;

end

out(ptr:ptr+hop1) = overlap;

audiowrite(outfile, out, fs);

end

2.结果

1)维纳滤波效果

在这里插入图片描述

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

2)与过减法比较

在这里插入图片描述

左图是经过维纳滤波后的语音,右图是经过过减法的语音,对比可以直观发现,在某些频点上,过减法会无差别进行减法处理,也就是会丧失了某些语音信息


总结

维纳滤波其实揭示了一个非常重要的思想:

语音增强本质上不是“去掉噪声”, 而是根据 信噪比重新分配频谱能量。

这也是为什么:

  • Wiener Filter
  • Ephraim-Malah
  • Log-MMSE
  • WebRTC NS

这些经典算法,本质上都围绕着 SNR估计 + 增益函数 展开。

理解了维纳滤波, 基本就理解了 一半语音降噪算法的核心思想。

如果本文对你理解维纳滤波器有所帮助,欢迎点赞、收藏或留言交流。

赞(0)
未经允许不得转载:171主机测评 » 一句话讲透维纳滤波:从公式推导到语音降噪完整实现(附MATLAB代码)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址