WebRtc AEC核心算法之一:频域自适应滤波

本文探讨了WebRtcAEC中的频域自适应滤波技术,对比时域方法,频域方法通过分块处理降低了计算复杂度,利用FFT提高了算法效率。文中详细介绍了块自适应滤波和频域块LMS算法的原理与实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

WebRtc AEC核心算法之一:频域自适应滤波

WebRtc和Speex作为目前开源的语音增强平台,给非科班出身的工程师一探究竟的机会,本文接下来以WebRtc的Aec模块为主线,研究一下比较核心的算法和实现。
一直以来在心目中AEC就是利用自适应滤波器求解梯度的迭代过程,时域的LMS/RLS经典算法在教科书和主流文章中都有介绍,但频域的介绍的就不多了,恰恰两个流行的平台都选用了频域自适应滤波器,首先是因为频域方法避免了时域FIR滤波器抽头太多,计算复杂度较大的缺点,另外就是最近二三十年频域滤波的发展迅速,很多优秀的算法已经产品化,只是我们接触的少不知道而已。在《Acoustic MIMO Signal Processing》第五章 Frequency-Domain Adaptive Filters,有以下介绍:相比于时域方法,频域分块处理的计算复杂度显著的降低了。FFT的运用,令输入信号的时移属性非常适合Toeplitz矩阵结构,意味着设计一个频域自适应滤波算法仅仅是通过被显式的Toeplitz和循环矩阵重写时域的误差尺度而已。(说的真轻松!)据这本书介绍,最早是1978年Dentino等在《Adaptive filtering in the frequency domain》提出了频域滤波器,紧接着Ferrara在1980年的《Fast implementations of LMS adaptive filters》提出了频域最小均方差方法使得频域地维纳解实现了快速收敛。Mansour和Gray在1982年提出了《Unconstrained frequency-domain adaptive filter》,以及后来MDF(Multi delay filter is selected by speex)的提出和应用,这些基本奠定了频域自适应滤波器的基础。《An adaptive filtering algorithm using an orthogonal projection to an affine subspace and its properties》还介绍了 affine project方法,也是热门的话题。

自适应滤波器-从时域到频域

经典的LMS自适应滤波器是采用时域实现的,标准的权重因子w(n)w(n)w(n)迭代表达如下:
y(n)=wH(n)u(n)e(n)=d(n)−y(n)w(n+1)=w(n)+μu(n)e(n) y(n)=w^H(n)u(n)\\ e(n)=d(n)-y(n)\\ w(n+1)=w(n)+\mu u(n)e(n) y(n)=wH(n)u(n)e(n)=d(n)y(n)w(n+1)=w(n)+μu(n)e(n)
u(n)u(n)u(n)是输入矢量,d(n)d(n)d(n)是期望的相应,w(n)w(n)w(n)是FIR滤波器抽头,μ\muμ是收敛因子。普通LMS的收敛因子是常数,而NLMS是对μ\muμ做了归一化处理,加速收敛速度的变形。但是实际实现过程遇到了两个挑战:

  1. 应用于回声消除等延时比较敏感的场景下,FIR的抽头(阶数)数量可观,意味需要较大的存储空间来存放权重因子,更为烦恼的是高阶卷积的运算量巨大,算法复杂度、稳定性等等都会遇到极大的挑战
  2. 收敛速度和稳定性一直是自适应滤波器需要追求的一种平衡,能否在频域发现更加优秀的算法取得收敛速度和稳定性的统一考量。
    因此,频域自适应滤波(FDAF)、正交自适应滤波和子带自适应滤波被提出来,有书中归纳为块自适应滤波,因为输入信号序列u(n)u(n)u(n)被分成LLL点的数据块来处理,自适应过程是以块为单位来更新,这区别原始的以采样点为更新基础的算法。
    在进行分块自适应讨论之前,我们先将上面的式子展开,便于理解,假设滤波器抽头为N:
    [w0(k+1)w1(k+1)....wN−1(k+1)]=[w0(k)w1(k)....wN−1(k)]+μ[u(k)u(k−1)....u(k−N+1)]e(n)=[w0(k)w1(k)....wN−1(k)]+μ[u(k)u(k−1)....u(k−N+1)][d(n)−y(n)] \begin{aligned} \begin{bmatrix} w_0(k+1) \\ w_1(k+1)\\ ....\\ w_{N-1}(k+1)\\ \end{bmatrix}&=\begin{bmatrix} w_0(k) \\ w_1(k)\\ ....\\ w_{N-1}(k)\\ \end{bmatrix}+\mu\begin{bmatrix} u(k) \\ u(k-1)\\ ....\\ u(k-N+1)\\ \end{bmatrix}e(n)\\ &=\begin{bmatrix} w_0(k) \\ w_1(k)\\ ....\\ w_{N-1}(k)\\ \end{bmatrix}+\mu\begin{bmatrix} u(k) \\ u(k-1)\\ ....\\ u(k-N+1)\\ \end{bmatrix}[d(n)-y(n)]\\ \end{aligned} w0(k+1)w1(k+1)....wN1(k+1)=w0(k)w1(k)....wN1(k)+μu(k)u(k1)....u(kN+1)e(n)=w0(k)w1(k)....wN1(k)+μu(k)u(k1)....u(kN+1)[d(n)y(n)]
    从这个公式很容易得出,每计算出一个滤波器输出y(n)y(n)y(n),都需要更新权重因子,如果处理一帧数据是L个samples,那么随着输出更新L次,权重因子也更新L次,计算量是客观的。

块自适应滤波-block adaptive filtering[5]

假设输入数据块为向量表达:
u(n)=[u(n),u(n−1),...,u(n−N+1)]T u(n)=[u(n),u(n-1),...,u(n-N+1)]^T u(n)=[u(n),u(n1),...,u(nN+1)]T
此时的权重因子向量为:
w^(n)=[w0^(n),w1^(n),...,w^M−1(n)]T \hat{w}(n)=[\hat{w_0}(n),\hat{w_1}(n),...,\hat{w}_{M-1}(n)]^T w^(n)=[w0^(n),w1^(n),...,w^M1(n)]T
对于nnn进一步的用如下定义来分解:
n=kL+i,i=0,1,...L−1,k=1,2,..., \begin{aligned} n=kL+i,\quad &i=0,1,...L-1,\\ &k=1,2,..., \end{aligned} n=kL+i,i=0,1,...L1,k=1,2,...,
LLL表示块长度,这样对于输入数据第kkk块,可以定义为:
AT(k)=u(kL+i)i=0L−1=[u(kL),u(kL+1),...,u(kL+L−1)] \begin{aligned} \bold{A}^T(k)&={u(kL+i)}_{i=0}^{L-1}\\ &=[u(kL),u(kL+1),...,u(kL+L-1)] \end{aligned} AT(k)=u(kL+i)i=0L1=[u(kL),u(kL+1),...,u(kL+L1)]
这个时候容易瞢,回头看看u(n)u(n)u(n)可是MMM维数组,所以A(k)A(k)A(k)是一个矩阵,假设M=6,L=4M=6,L=4M=6L=4,矩阵的格式如下
在这里插入图片描述再举一例,由此我们得到y(n)y(n)y(n)的更新过程如下图(M=3,L=3)(M=3,L=3)(M=3L=3)
在这里插入图片描述这里很明显的看出A(k)A(k)A(k)是Toeplitz矩阵,主对角线以及平行主对角线的元素均相等。
block adaptive filtering权重因子更新算法是显著区别于经典算法的,下面只列出结果,有兴趣的同学可以参考[4][5]文献的介绍。
w(k+1)=w(k)+μ∑i=0L−1u(kL+i)e(kL+i)=w(k)+AT(k)e(k) \begin{aligned} w(k+1)&=w(k)+\mu \sum_{i=0}^{L-1}\bold{u}(kL+i)e(kL+i)\\ &=w(k)+\bold{A}^T(k)e(k) \\ \end{aligned} w(k+1)=w(k)+μi=0L1u(kL+i)e(kL+i)=w(k)+AT(k)e(k)
这里的k是表示第k*L个模块,和之前时域的k不一样了。也就是每个L个samples算一次,我们可以把上式得矩阵表示进一步展开:
[w0(k+1)w1(k+1)....wN−1(k+1)]=[w0(k)w1(k)....wN−1(k)]+μ[u(kL)x(kL−1)....x(kL−N+1)]e(kL)+μ[u(kL+1)x(kL)....x(kL−N+2)+]e(kL+1)+...+μ[u(kL+L−1)x(kL+L−2)....x(kL−N+L)]e(kL+L−1) \begin{aligned} \begin{bmatrix} w_0(k+1) \\ w_1(k+1)\\ ....\\ w_{N-1}(k+1)\\ \end{bmatrix}&=\begin{bmatrix} w_0(k) \\ w_1(k)\\ ....\\ w_{N-1}(k)\\ \end{bmatrix}+\mu\begin{bmatrix} u(kL) \\ x(kL-1)\\ ....\\ x(kL-N+1)\\ \end{bmatrix}e(kL)+\mu\begin{bmatrix} u(kL+1) \\ x(kL)\\ ....\\ x(kL-N+2)\\ +\end{bmatrix}e(kL+1)+\\&...+\mu\begin{bmatrix} u(kL+L-1) \\ x(kL+L-2)\\ ....\\ x(kL-N+L)\\ \end{bmatrix}e(kL+L-1) \end{aligned} w0(k+1)w1(k+1)....wN1(k+1)=w0(k)w1(k)....wN1(k)+μu(kL)x(kL1)....x(kLN+1)e(kL)+μu(kL+1)x(kL)....x(kLN+2)+e(kL+1)+...+μu(kL+L1)x(kL+L2)....x(kLN+L)e(kL+L1)
这样只需每个块L算一次,并且对这个块内的e(n)做了平滑处理。最后提一下,实际应用中往往采用M(N)=L,这是综合考量计算复杂度等因素,对理解算法也有帮助,上文的第二个例子就说明了当M(N)=L之后,很容易设计出A(k)A(k)A(k)的Toeplitz矩阵形式,尤其下面引入频域和傅立叶变换之后。

Fast Block LMS Algorithm & FDAF

回顾上一节的滤波器输出,用公式来表示:
y(kL+i)=w^T(k)u(kL+i)=∑j=0M−1w^j(k)u(kL+i−j),i=0,1,..,L−1. \begin{aligned} y(kL+i)&=\hat{w}^T(k)\bold{u}(kL+i)\\ &=\sum_{j=0}^{M-1}\hat{w}_j(k)u(kL+i-j), \quad i=0,1,..,L-1. \end{aligned} y(kL+i)=w^T(k)u(kL+i)=j=0M1w^j(k)u(kL+ij),i=0,1,..,L1.
以及ϕ(k)\phi(k)ϕ(k)的定义:
ϕ(k)=∑i=0L−1u(kL+i)e(kL+i)=AT(k)e(k) \begin{aligned} \phi(k)&=\sum_{i=0}^{L-1}\bold{u}(kL+i)e(kL+i)\\ &=\bold{A}^T(k)e(k) \end{aligned} ϕ(k)=i=0L1u(kL+i)e(kL+i)=AT(k)e(k)
这两个公式可以用线性卷积结构实现,而FFT经过特殊的处理就可以满足线性卷积的处理需求,即50%重叠存储法,如果M个抽头的滤波器,补充M个0,构建一个N=2M长度的FFT:
W^(k)=FFT[w^(k)0] \hat{W}(k)=FFT\begin{bmatrix} \hat{w}(k) \\ 0 \\ \end{bmatrix} W^(k)=FFT[w^(k)0]
构建频域对角阵
U(k)=diag{FFT[u(kM−M),...,u(kM−1),⎵(k−1)thblocku(kM),...,u(kM+M−1),⎵(k)thblock]} \bold{U}(k)=diag\lbrace FFT[\underbrace{u(kM-M),...,u(kM-1),}_{(k-1)th\quad block}\underbrace{u(kM),...,u(kM+M-1),}_{(k)th\quad block}]\rbrace U(k)=diag{FFT[(k1)thblocku(kMM),...,u(kM1),(k)thblocku(kM),...,u(kM+M1),]}
最后可以得到:
yT=[y(kM),y(kM+1),...,y(kM+M−1)]=last M elements of IFFT[U(k)W^(k)] \begin{aligned} y^T&=[y(kM),y(kM+1),...,y(kM+M-1)]\\ &=last\space M\space elements\space of\space IFFT [\bold{U}(k)\hat{\bold{W}}(k)] \end{aligned} yT=[y(kM),y(kM+1),...,y(kM+M1)]=last M elements of IFFT[U(k)W^(k)]
而前M个元素被扔掉了。
定义一维期望信号向量和误差向量为:
d(k)=[d(kM),d(kM+1),...,d(kM+M−1)]Te(k)=[e(kM),e(kM+1),...,e(kM+M−1)]T=d(k)−y(k) \begin{aligned} d(k)&=[d(kM),d(kM+1),...,d(kM+M-1)]^T\\ e(k)&=[e(kM),e(kM+1),...,e(kM+M-1)]^T\\ &=\bold{d}(k)-\bold{y}(k) \end{aligned} d(k)e(k)=[d(kM),d(kM+1),...,d(kM+M1)]T=[e(kM),e(kM+1),...,e(kM+M1)]T=d(k)y(k)
与输出向量的定义过程类似,定义一个2M维向量,但前M个用0填充:
E(k)=FFT[0e(k)] E(k)=FFT\begin{bmatrix} 0 \\ \bold{e}(k) \\ \end{bmatrix} E(k)=FFT[0e(k)]
将重叠保存的方法应用于线性相关,求得ϕ(k)\phi(k)ϕ(k)
ϕ(k)=first M elements of IFFT[UH(k)E(k)] \phi(k)=first\space M\space elements\space of\space IFFT[U^H(k)E(k)] ϕ(k)=first M elements of IFFT[UH(k)E(k)]
而权重因子的频域更新公式如下:
W^(k+1)=W^(k)+μFFT[ϕ(k)0] \hat{W}(k+1)=\hat{W}(k) + \mu FFT \begin{bmatrix} \phi(k) \\ 0 \\ \end{bmatrix} W^(k+1)=W^(k)+μFFT[ϕ(k)0]
频域实现的基本数学过程大致如此。相比较Ns算法中利用谱减规则对频域功率谱分析的侧重点,此处FFT更多的是为了算法效率上的考虑。

参考文献

[1]:《Acoustic MIMO Signal Processing》Yiteng Huang etc. Springer
[2]:《频域自适应滤波算法及应用》华南理工大学-本科毕业设计
[3]:《频域块 LMS 自适应滤波算法的研究》田超 西安理工大学 - 硕士毕业论文
[4]:《Frequency Domain and MutiRate Adaptive Filtering》 John J. shynk. IEEE Digital Signal Process Magzine.
[5]:《Adaptive Filter Theory》Fifth Edition Simon Haykin.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值