自适应滤波器原理——频域分块LMS算法(FDAF)

在讲频域分块LMS之前建议大家回顾一个时域分块LMS算法

时域分块LMS:

 Block  LMS的误差计算 和 权重更新公式中,

y(n+m)=X^{T}(n+m)w(n):输出信号是输入信号与滤波器系数的线性卷积

\hat{\triangledown }(k)=-\sum_{i=0}^{L-1}X(kL+i)e(kL+i):更新梯度是误差信号与输入信号的线性相关

对于线性卷积和线性相关的运算量较大,特别是在当回声路径很长且复杂,并且回声延迟较高时,时域自适应滤波算法中的线性卷积线性相关运算量较大,导致计算复杂度升高,我们更愿意把这两个信号变换到频域,通过频域相乘的方式来取代时域复杂度相当高的卷积或相关运算。所以我们把时域自适应滤波算法,衍生到频域自适应滤波算法。

预备知识:线性卷积(相关)和圆周(循环)卷积(相关)之间的关系

  1. 一般的,如果两个有限长序列的长度为N1和N2,且满足N1≥N2,则有圆周卷积 N1−N2+1个点,与线性卷积的结果一致。
  2. 一般的,如果两个有限长序列的长度为N1和N2,且满足N1≥N2,则有圆周相关 N1−N2+1个点,与线性相关的结果一致。
  3. 时域中的圆周卷积对应于其离散傅里叶变换的乘积
  4. 时域中的圆周相关对应于其离散傅里叶变换共轭谱的乘积
  5. 在利用循环卷积计算线性卷积时,为了防止混叠,首先要将输入信号长度N1和滤波器系数长度N2,补零至长度大于等于L(L=N1−N2+1) 

因此我们需要将分块LMS自适应滤波算法中的线性卷积线性相关 通过快速傅里叶变换(FFT)转换到频域来实现。这样实现的分块LMS自适应滤波算法称为频域块LMS自适应滤波算法(FDAF,Frequency-Domain Block Least Mean Square Adaptive Filter)。FDAF算法将长度为L的自适应滤波器分成FFT长度的整数倍个子块,对输入信号的每个子块进行频域内的LMS算法。

第一步:计算线性卷积

利用FFT计算线性卷积的方法有:

  • 重叠存储法(overlap save method,更常用)
  • 重叠相加法(overlap add method)

我们这里以overlap save method为例,为了确保能得到N个点的线性卷积输出信号,我们至少要保证有N个点的线性卷积和圆周卷积的结果一致(预备知识)

由于N1≥N2 (输入信号长度N1通常大于滤波器的阶数N2),且N2=N (滤波器的阶数为N),那么要求每次参与运算的输入信号长度N1至少为2N−1(N1=N+N2-1=2N+1),为了计算FFT方便,我们令输入信号的长度为:N1=2N,那么我们FFT的长度也为2N

为了构造长度为2N的数据,我们需要在每个N阶滤波器后面N补零

要求线性卷积(预备知识1),我们就需要求圆周卷积后N1−N2+1个点,根据预备知识3,我们只需要求离散傅里叶变换的乘积就能得到圆周卷积的结果,接下来我们分别计算输入信号向量和滤波器系数向量的FFT:

 第二步:计算线性相关

根据预备知识2,4可知,需要求线性相关,我们可以通过获得圆周相关来获得。因此我们需要求输入信号的共轭谱与误差信号谱的乘积

输入信号X(k)在上一步处理卷积运算是已经求得。

 

 第三步:滤波器系数更新

注意:

  • 第一,滤波器系数直接在频域更新,所以需要将梯度向量再次变换到频域;
  • 第二,由于滤波器系数向量后面补了N 个零 ,为了保证结果的正确性梯度向量也需要在后面补 N 个零。

  • 优点
    • 降低了时域自适应滤波器的计算复杂度
    • 提高了收敛速度
  • 缺点
    • 增加了延迟(需要通过频域滤波器延迟期望信号)
    • 增加了内存需求(需要同时存储激励信号和期望信号)

如前所述,回声消除等应用回波路径较长,会导致较大的延迟和存储需求。该缺点可以通过诸如多延迟自适应滤波器之类的方法来克服。在这种方法中,块大小可以小于所需的时域自适应滤波器,并且可以应用每个频点中的自适应滤波器来代替单个系数。因此,可以减轻FDAF的缺点,同时保持降低的计算复杂性和提高的收敛速度。

MATLAB代码如下:

% 参考:https://github.com/CharlesThaCat/acoustic-interference-cancellation
function [en, yk, W] = myFDAF(d,x,mu,mu_unconst, M, select)
% 参数:
% d                输入信号(麦克风语音)
% x                远端语音
% mu                约束 FDAF的步长
% mu_unconst        不受约束的 FDAF的步长
% M                 滤波器阶数
% select;            选择有约束或无约束FDAF算法
%
% 参考:        
% S. Haykin, Adaptive Filter Theory, 4th Ed, 2002, Prentice Hall
% by Lee, Gan, and Kuo, 2008
% Subband Adaptive Filtering: Theory and Implementation
% Publisher: John Wiley and Sons, Ltd

x_new = zeros(M,1);     % 将新块的M个样本初始化为0
x_old = zeros(M,1);     % 将旧块的M个样本初始化为0

AdaptStart = 2*M;       % 在获得2M个样本块后开始自适应
W = zeros(2*M,1);       % 将2M个滤波器权重初始化为0
d_block = zeros(M,1);   % 将期望信号的M个样本初始化为0

power_alpha = 0.5;        % 常数以更新每个frequency bin的功率
power = zeros(2*M,1);   % 将每个bin的平均功率初始化为0
d_length = length(d);             % 输入序列的长度
en = [];                       % 误差向量
window_save_first_M = [ones(1,M), zeros(1,M)]';  % 设置向量以提取前M个元素 (2M,1)

for k = 1:d_length
    x_new = [x_new(2:end); x(k)];         % 开始的输入信号块 (2M,1)
    d_block = [d_block(2:end); d(k)];     % 开始的期望信号快 (M,1)
    if mod(k,M)==0                        % If iteration == block length, 
        x_blocks = [x_old; x_new];        % 2M样本的输入信号样本块 (2M,1)
        x_old = x_new;
        if k >= AdaptStart                % 频域自适应滤波器

            % 将参考信号转换到频域
            Xk = fft(x_blocks);     % (2M,1)
            % FFT[old block; new block]
            % Old block 包含M个先前的输入样本 (u_old)
            % New 包含M个新的输入样本 (u_new)

            % 计算滤波器估计信号
            Yk = Xk.*W;                  % 输入和权重向量的乘积(2M,1)*(2M,1)=(2M,1)
            temp = real(ifft(Yk));            % IFFT 输出的实部 (2M,1)
            yk = temp(M+1:2*M);               % 抛弃前M个元素,保留后M个元素 (M,1)

            % 计算误差信号
            error = d_block-yk;              % 误差信号块 (M,1)
            Ek = fft([zeros(1,M),error']');   % 在FFT之前插入零块以形成2M块(2M,1)

            % 更新信号功率估算
            power = (power_alpha.*power) + (1 - power_alpha).*(abs(Xk).^2); % (2M,1)

            % 计算频域中的梯度和权重更新
            if select == 1
                gradient = real(ifft((1./power).*conj(Xk).* Ek));   % (2M,1)
                gradient = gradient.*window_save_first_M;   % 去除后一个数据块,并且补零 (2M,1)
                W = W + mu.*(fft(gradient));    % 权重是频域的 (2M,1)
            else
                gradient = conj(Xk).* Ek;   %  (2M,1)
                W = W + mu_unconst.*gradient;    % (2M,1)
            end
            
            en = [en; error];             % 更新误差块
        end
    end
end

学习速率如何选取 

我们在推导频域自适应滤波方法的时候,为了简化问题,将每一个frequency bin 上的学习速率均设为常数μ。

在实际工程应用中,用的更多的一种方法是,对第m个 frequency bin ,利用输入信号在这个频点的功率 对学习速率Pm(k)进行归一化:

 频点功率Pm(k)通常采用迭代的方式求得:

参考链接:

https://www.cnblogs.com/LXP-Never/p/11773190.html

猜你喜欢

转载自blog.csdn.net/qq_42233059/article/details/131343926