自适应滤波器更新算法-EP1

news2024/10/1 3:23:29

自适应滤波器更新算法-EP1

  自适应滤波器是回声消除系统中非常重要的一个功能模块,而对于自适应滤波器来说,如果更新滤波器系数则是关键所在。本文将介绍几种现有的滤波器更新算法,并附上Matlab测试代码。

1、LMS算法

1.1算法原理

  LMS算法即最小均方算法(Least Mean Square),它是由Widrow和Hoff在1960年提出的。将LMS算法应用在滤波器上的结构中,其包含两个主要的部分,第一个部分是LMS算法的部分,另一个部分是常用的滤波器结构即横向有限冲击响应结构,假设n时刻的输入信号向量表达式为
X ( n ) = [ x ( n ) , x ( n − 1 ) , . . . , x ( n − M + 1 ) ] X(n) = [x(n),x(n-1),...,x(n-M+1)] X(n)=[x(n),x(n1),...,x(nM+1)]
其中,M表示滤波器的阶数,是一个固定值,其根据实际需求而定。滤波器的权向量的表达式为

在这里插入图片描述

其中,i是滤波器权向量的下标,即表示 w i ( n ) w_i(n) wi(n) 为第几个滤波器权向量,其取值范围为0~M-1,如 w 0 ( n ) w_0(n) w0(n) 表示的是 x ( n ) x(n) x(n) 所对应的权向量。滤波器输出信号表达式为:

在这里插入图片描述

n时刻期望信号 d ( n ) d(n) d(n) 与算法实际输出信号之间的差值表示为:

在这里插入图片描述

其中误差信号 e ( n ) e(n) e(n) 进入LMS算法的函数模型中,通过该函数模型控制着LMS算法的步长参数,随着每一次迭代系数向量 W ( n ) W(n) W(n) 发生改变,最终 W ( n ) W(n) W(n) 趋近于其最有解,从而使实际输出信号 y ( n ) y(n) y(n) 与期望信号 d ( n ) d(n) d(n) 的差值无限接近与0。

  传统LMS算法的具体步骤如下:

  1. 初始化参数。将自适应滤波器权系数的初始值 W ( 0 ) W(0) W(0) 设置为0,将自适应滤波器的阶数设置为M,选择合适的变化的步长值 μ \mu μ ,为了使算法收敛,步长 μ \mu μ 的取值应为:
    0 < μ < 1 / λ m a x 0<\mu<1/\lambda_{max} 0<μ<1/λmax
    其中 λ m a x \lambda_{max} λmax 表示输入信号 X ( n ) X(n) X(n) 的自相关矩阵的最大特征值。

  2. 计算滤波器的实际输出信号为 : y ( n ) = W T ( n ) X ( n ) y(n) = W^T(n) X(n) y(n)=WT(n)X(n)

  3. 计算自适应滤波器的误差为 : e ( n ) = d ( n ) − y ( n ) = d ( n ) − W T ( n ) X ( n ) e(n) = d(n) - y(n) = d(n) - W^T(n) X(n) e(n)=d(n)y(n)=d(n)WT(n)X(n)

  4. 更新滤波器权系数的值为: W ( n + 1 ) = W ( n ) + μ X ( n ) e ( n ) W(n+1) = W(n) + \mu X(n)e(n) W(n+1)=W(n)+μX(n)e(n)

重复上述步骤2~4,直到滤波器权系数逼近最佳滤波为止。

1.2 算法代码

function [e, y, w] = LMS(d, x, mu, M)
% Inputs:
% d  - 麦克风语音
% x  - 远端语音
% mu - 步长,0.05
% M  - 滤波器阶数,也称为抽头数
%
% Outputs:
% e - 输出误差,近端语音估计
% y  - 输出系数,远端回声估计
% w - 滤波器参数

    d_length = length(d);
    if (d_length <= M)  
        print('error: 信号长度小于滤波器阶数!');
        return; 
    end
    if (d_length ~= length(x))  
        print('error: 输入信号和参考信号长度不同!');
        return; 
    end

    xx = zeros(M,1);
    w1 = zeros(M,1);    % 滤波器权重
    y = zeros(d_length,1);  % 远端回声估计
    e = zeros(d_length,1);  % 近端语音估计

    for n = M:d_length
        xx = x(n:-1:n-M+1);    % 纵向拼接  (40~1)-->(41~2)-->(42~3)....
        y(n) = w1' * xx;        % 远端回声估计 (40,1)'*(40,1)=1; (73113,1)
        e(n) = d(n) - y(n);     % 近端语音估计
        w1 = w1 + mu * e(n) * xx;   % (40,1)
        w(:,n) = w1;        % (40, 73113)
    end
end

1.3 算法分析

  LMS算法是一种随机梯度下降算法,随着迭代次数的增加,更新出的权重值无法精确收敛,但是其算法简单,易于实现,算法复杂度也较低。但是算法中的 μ \mu μ 为步长因子,其对于算法的收敛速度、时变系统的跟踪速度和稳态误差这些特征起到关键的影响作用,较小的步长因子 μ \mu μ 会获得较小的稳态误差从而提高算法的精度,同时也会获得较小的收敛速度,使算法收敛的很慢,对于时变系统来说较小的步长因子也会导致跟踪速度的减小。反之,较大的步长因子 μ \mu μ 会带来较大的收敛速度使得算法收敛的很快,同时对于时变系统来说,会提高其跟踪速度,但是会带来较大的稳态误差,降低算法的精度。因此 μ \mu μ 的选取很关键。

2、NLMS算法

2.1算法原理

  归一化最小均方(Normalized Least Mean Squares,NLMS)算法是改进的变步长的LMS算法,对于较大的输入 X ( n ) X(n) X(n) ,会导致梯度噪声的放大,因此需要用输入向量的平方范数进行归一化。根据原LMS算法中误差信号与远端输入信号的乘积,对远端输入信号的平方(功率)进行归一化处理,将固定步长因子的LMS算法变为根据输入信号时变的变步长LMS算法,算法具体针对 μ \mu μ 改进为函数 μ ( n ) \mu(n) μ(n) 如下:
μ ( n ) = μ X T ( n ) X ( n ) + δ \mu(n) = \frac{\mu}{X^T(n)X(n)+\delta} μ(n)=XT(n)X(n)+δμ
其中, μ \mu μ 为自适应常量,取值为0~2, δ \delta δ 为一个较小的正常数,是为了防止输入信号 X ( n ) X(n) X(n) 过小导致分母趋近于0进而带来的算法不稳定性。则滤波器权系数更新公式为:
W ( n + 1 ) = W ( n ) + μ ( n ) X ( n ) e ( n ) W(n+1) = W(n) + \mu(n) X(n)e(n) W(n+1)=W(n)+μ(n)X(n)e(n)
  具体的实现步骤,除了 μ ( n ) \mu(n) μ(n) 的计算外,其他同LMS算法步骤相同。

2.2 算法代码

function[e,y,w] = NLMS(d,x,M)
    % 输入:
    % d  - 麦克风语音
    % x  - 远端语音
    % M  - 滤波器阶数
    %
    % 输出:
    % e - 近端语音估计
    % y - 远端回声估计
    % w - 滤波器参数
    d_length = length(d);
    if (d_length <= M)
        print('error: 信号长度小于滤波器阶数!');
        return; 
    end
    if (d_length ~= length(x))  
        print('error: 输入信号和参考信号长度不同!');
        return; 
    end
    
    xx = zeros(M,1);
    w1 = zeros(M,1);  %滤波器权重
    y = zeros(d_length,1); %近端语音
    e = zeros(d_length,1); %误差
    
    for n = 1:d_length
        %在输入信号x前补上M-1个0,使输出y与输入具有相同长度
        xx = [xx(2:M);x(n)]; %(39,1) +(1,1) = (40,1)
        y(n) = w1' *xx;
        mu = 1/(xx'*xx); %步长,这里简化了mu的计算,没有防止x(n)过小的情况
        e(n) = d(n) - y(n);  %误差
        w1 = w1 + mu * e(n) * xx;
        w(:,n) = w1;
    end
end

1.3 算法分析

  NLMS算法相对与LMS算法有着更快的收敛速度,同时保留了算法简洁、计算量小、易于实现的优点;但是NLMS算法没有考虑到滤波器阶数增长的问题。随着采样率的提升,滤波器的阶数已经达到千阶,算法复杂度也成倍增长。因此NLMS 算法仅适用于对处理精度和能力要求不是很高的一般场合。

3、PBFDAF算法

3.1 算法原理

参考文献一中对该算法的介绍:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.2 算法代码

function [en, yk, W] = myFDAF(d,x,mu,mu_unconst, M, select)
% 参数:
% d                输入信号(麦克风语音)
% x                远端语音
% mu                约束 FDAF的步长
% mu_unconst        不受约束的 FDAF的步长
% M                 滤波器阶数
% select;            选择有约束或无约束FDAF算法


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
 % 参考:https://github.com/CharlesThaCat/acoustic-interference-cancellation    

3.3 算法分析

  该算法利用FFT可快速实现卷积运算的特点,在频域进行滤波器的更新,同时使用逐块更新来代替逐点更新,从而大大降低了算法的计算复杂度。但同时其步长因子 μ \mu μ 是由自适应常量和远端信号决定的,是固定的无法根据不同复杂的场景进行变换,该算法应用在WebRTC的AEC算法中。在AEC算法中,其用了延时估计模块来对齐语音信号,并采用了语音检测等模块来去除噪声和无用语音的影响,以提高滤波器更新算法的效果。

续:本文先介绍几种比较经典的自适应滤波器算法,后续将介绍读者阅读论文总结并复现的滤波器算法!!!

参考文献

[1] 葛世超,吕强。《实时语音处理实践指南》。

[2] Soo J S , Pang K K . Multidelay block frequency domain adaptive filter[J]. Acoustics Speech & Signal Processing IEEE Transactions on, 1990, 38(2):373-376.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/54840.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Matplotlib绘制图像大全】(二十二):Matplotlib绘制气泡图

前言 大家好,我是阿光。 本专栏整理了《Matplotlib绘制图像大全》,内包含了各种常见的绘图方法,以及Matplotlib各种内置函数的使用方法,帮助我们快速便捷的绘制出数据图像。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmMatp…

变电站远程监控维护,工程师不用出差跑断腿

电力的稳定产出和供应是社会生产、人民生活的重要保障之一。电力监控系统的作用是对变电站设备和变配电系统的运行状态进行监控和管理&#xff0c;保证安全稳定生产&#xff0c;使得终端用户的用电更加安全&#xff0c;同时企业自身的智能化管理水平也能有所提升。 随着经济和城…

TLS版本及CipherSuites确认及设置

在使用Https&#xff08;AS2、RosettaNet等协议&#xff09;传输协议进行数据传输中&#xff0c;有时会遇到下面这些报错信息&#xff1a; ①276–Error during handshake:接收到的消息异常&#xff0c;或格式不正确。 ②13003&#xff1a;Connot conclude ssl handshake.Caus…

苹果电脑误删文件怎么找回?苹果电脑删了文件能恢复吗?苹果电脑文件删除怎么恢复

现如今&#xff0c;使用苹果电脑的用户越来越多&#xff0c;因为其系统流畅&#xff0c;加上小巧便携&#xff0c;成为了不少用户的不二选择&#xff0c;当然&#xff0c;这些用户也经常会遇到一些问题&#xff0c;比如刚刚一位小伙伴就在给小编吐槽他不小心把苹果电脑上面一些…

【golang】1769. 移动所有球到每个盒子所需的最小操作数---时间复杂度O(N)

有 n 个盒子。给你一个长度为 n 的二进制字符串 boxes &#xff0c;其中 boxes[i] 的值为 ‘0’ 表示第 i 个盒子是 空 的&#xff0c;而 boxes[i] 的值为 ‘1’ 表示盒子里有 一个 小球。 在一步操作中&#xff0c;你可以将 一个 小球从某个盒子移动到一个与之相邻的盒子中。…

微信小程序|使用小程序制作一个世界杯球员识别工具

一、前言二、实现流程三、功能开发四、代码块一、前言 四年一次的世界杯正在卡塔尔进行着&#xff0c;不同的社交圈也在疯狂的刷着世界杯的动态&#xff0c;来自全球各地的三十二支队伍的球员是否让你看的眼花缭乱呢&#xff1f; 当朋友跟你聊起昨晚那场比赛某某某球员的精彩表…

WPS中配置MathType及mathtype实现论文公式一键改大小

目录 0 概述 1 WPS中配置MathType 1.1 步骤1&#xff1a; 1.2 步骤2&#xff1a; 1.3 步骤3&#xff1a; 1.4 步骤4&#xff1a; 1.5 步骤5&#xff1a; 2 mathtype实现论文公式一键改大小 2.1 步骤1&#xff1a; 2.2 步骤2&#xff1a; 2.3 步骤3&#xff1a; 2.4…

大数定律与中心极限定理

给大家讲个有趣的故事 明天概统小测哦可惜了 我的智商还停留在小学时代可惜了&#xff0c;我需要努力学习Physice Doctor in FutureChebyshev 不等式 &#xff08;弱&#xff09;大数定律 Markov 大数定律 Chebyshev 大数定律 独立同分布大数定律 Bernoulli 大数定律 Khinchin …

npm打包整个过程

将自己写的代码包上传到npm&#xff0c; 方便后续下载安装&#xff0c; 步骤如下&#xff1a; 上传 打开npm官方网站&#xff1a; www.npmjs.com; 进行注册 注册需要用户名&#xff0c;密码和邮箱&#xff0c; 当注册完成后需打开邮箱进行验证&#xff08;邮箱不验证无法上传&…

JUC系列(九) CAS 与锁的理解

&#x1f4e3; &#x1f4e3; &#x1f4e3; &#x1f4e2;&#x1f4e2;&#x1f4e2; ☀️☀️你好啊&#xff01;小伙伴&#xff0c;我是小冷。是一个兴趣驱动自学练习两年半的的Java工程师。 &#x1f4d2; 一位十分喜欢将知识分享出来的Java博主⭐️⭐️⭐️&#xff0c;擅…

DZ-51/220【中间继电器】

系列型号 DZ-51中间继电器; DZ-52中间继电器; DZ-53中间继电器; DZ-54中间继电器; JY-16A中间继电器; 一、用途 DZ-51/220;DZ-51/400中间继电器​ (以下简称继电器)用于自动控制装置中&#xff0c;以扩大被控制的电路和提高接通能力。 二、主要技术参数 额定电压&#xff1a;D…

Spring(存储Bean对象五大类注解,获取Bean对象三种注入方式)

目录 1. 先进行配置扫描路径 2. 存储 Bean 对象 ( 添加注解存储 Bean 对象) 2.1 Controller [控制器存储] 2.2 Service [服务存储] 2.3 Repository [仓库存储] 2.4 Configuration [配置存储] 2.5 Component [组件存储] 2.6 五大类注解的作用和关系 2.7 Bean的命名规则…

基于文化算法优化的神经网络预测研究(Matlab代码实现)

目录 1 文化优化算法 2 人工神经网络 3 基于文化算法优化的神经网络预测研究&#xff08;Matlab代码实现&#xff09;运行结果 4 参考文献 5 Matlab代码实现 1 文化优化算法 大自然里的各种生物在生存环境中相互竞争&#xff0c;优胜劣汰&#xff0c;不断进化&#xff0…

股票编程交易接口怎样自动设置止损?

目前随着国内二级股市已处于相对较高的水平&#xff0c;但是对于高净值的用户来说&#xff0c;在量化投资市场上使用股票编程交易接口系统上具有低波动性和自动交易的定量对冲投资模型体系&#xff0c;包括了一些高性价比、大型基金和长期投资的资产品种&#xff0c;所以大家在…

瑞吉外卖-B站最火的新手入门SpringBoot+Mybatis+Redis项目详细教程来了

&#x1f531;项目介绍 项目地址 GitHub&#xff1a;https://github.com/codermast/Takeout-food 对你有用的话&#xff0c;希望能给项目点个Star&#xff0c;非常感谢。 对于项目的任何问题&#xff0c;或者你在本地部署时遇到的无法解决的问题&#xff0c;都可以提交issues…

迭代器模式

文章目录思考迭代器模式1.迭代器模式的本质2.何时选用迭代器模式3.优缺点4.实现手动实现迭代器模式java迭代器模式思考迭代器模式 迭代器模式(Iterator Pattern)是常用的设计模式&#xff0c;属于行为型模式。如果我们的集合元素是用不同的方式实现的&#xff0c;有数组&#…

利用EasyDL制作一个简单的图片识别小项目

主要是利用EasyDL制作一个简单的傻瓜式猫狗图片识别&#xff0c;利用EasyDL&#xff0c;只需要几步简单的点击即可 *主要的步骤&#xff1a; 1.准备数据 2.训练模型 3.部署 4.H5 * 1.首先创建两个文件夹cat和dog分别搜集至少20张以上的猫和狗的图片&#xff08;如果不足20张&…

【High 翻天】Higer-order Networks with Battiston Federico (1)

目录前言高阶网络的表示高阶相互作用的初等表示表示之间的关系总结前言 Ginestra Bianconi 的一篇综述1和一本书2展开的故事。 书还没有开始看&#xff0c;先看看综述吧。综述提供了一个关于超越成对交互的网络新兴领域的概述。 讨论了高阶网络的表示&#xff0c;主要是其中…

HBase Shell 基本操作

首先确保你的hbase集群已经开启 进入 HBase 客户端命令行 namespace 使用help查看命令用法&#xff0c;并创建命名空间 查看所有命名空间 DDL 在 bigdata 命名空间中创建表格 student&#xff0c;两个列族。info 列族数据维护的版本数为 5 个&#xff0c; 如果 VERSIONS …

Arduino UNO通过SPI串行方式驱动LCD12864液晶屏

LCD12864液晶屏简介 LCD12864带中文字库图形点阵式液晶显示器&#xff0c;可配合各种单片机可完成中文汉字、英文字符和图形显示&#xff0c;可构成全中文人机交互图形界面&#xff0c;模块具有功耗低、显示内容丰富等特点而应用广泛。它是利用液晶经过处理后能改变光线的传播…