音频进阶学习十九——逆系统(简单进行回声消除)

文章目录

  • 前言
  • 一、可逆系统
    • 1.定义
    • 2.解卷积
    • 3.逆系统恢复原始信号过程
    • 4.逆系统与原系统的零极点关系
  • 二、使用逆系统去除回声
    • 获取原信号的频谱
    • 原系统和逆系统幅频响应和相频响应
    • 使用逆系统恢复原始信号
    • 整体代码如下
  • 总结


前言

在上一篇音频进阶学习十八——幅频响应相同系统、全通系统、最小相位系统文章中,我们在最小相位系统中提到了逆系统:一个稳定因果的LTI系统,同时会有一个稳定因果的逆系统。

本文中将会介绍逆系统的含义,通过对于零极点的分析,来对比逆系统和原系统的关联。最后,将会使用逆系统来对于给定的近端信号和参考信号来进行回声消除。

|版本声明:山河君,未经博主允许,禁止转载


一、可逆系统

1.定义

如果一个系统的输入是 x [ n ] x[n] x[n],经过系统 H ( z ) H(z) H(z)后系统的输出是 y [ n ] y[n] y[n],那么将 y [ n ] y[n] y[n]通过系统 G ( z ) G(z) G(z)后输出的是 x [ n ] x[n] x[n],此时系统 G ( z ) G(z) G(z)是系统 H ( z ) H(z) H(z)的逆系统。

G ( z ) G(z) G(z) H ( z ) H(z) H(z)的关系:

  • 频域关系
    G ( z ) H ( z ) = 1 = > g [ n ] = h [ n ] G(z)H(z)=1=>g[n]=h[n] G(z)H(z)=1=>g[n]=h[n]
  • 时域关系
    对于系统 H H H的脉冲响应有: y [ n ] = x [ n ] ∗ h [ n ] y[n]=x[n]*h[n] y[n]=x[n]h[n]
    对于系统 G G G的脉冲响应有: x ′ [ n ] = y [ n ] ∗ g [ n ] = ( x [ n ] ∗ h [ n ] ) ∗ g [ n ] = x [ n ] ∗ ( h [ n ] ∗ g [ n ] ) x'[n]=y[n]*g[n]=(x[n]*h[n])*g[n]=x[n] *(h[n]*g[n]) x[n]=y[n]g[n]=(x[n]h[n])g[n]=x[n](h[n]g[n])
    如果想要 x ′ [ n ] = x [ n ] x'[n]=x[n] x[n]=x[n],那么 h [ n ] ∗ g [ n ] = δ n h[n]*g[n]=\delta n h[n]g[n]=δn

2.解卷积

对于给定的输入信号 x [ n ] x[n] x[n]和输出信号 y [ n ] y[n] y[n],我们知道通过系统有:
X ( f ) = F { x [ n ] } , Y ( f ) = F { x [ n ] } , H ( f ) = X ( f ) Y ( f ) X(f)=F\{x[n]\},Y(f)=F\{x[n]\},H(f)=\frac{X(f)}{Y(f)} X(f)=F{x[n]},Y(f)=F{x[n]},H(f)=Y(f)X(f)
通过逆变换, h [ n ] = F − 1 { H ( f ) } h[n]=F^{-1}\{H(f)\} h[n]=F1{H(f)}得到冲激响应的这一过程,叫做解卷积

3.逆系统恢复原始信号过程

首先结合具体场景,假设发射了一个信号 x [ n ] x[n] x[n],通过多条途径例如墙体、窗户的反射,导致接收的信号是 y [ n ] y[n] y[n],我们想通过 y [ n ] y[n] y[n]恢复为原始的 x [ n ] x[n] x[n],如下图:
在这里插入图片描述

  • 发射约定好的信号 T [ n ] T[n] T[n]
  • 接收 T ′ [ n ] = T [ n ] ∗ h [ n ] T'[n]=T[n]*h[n] T[n]=T[n]h[n]
  • 通过解卷积得到 h [ n ] h[n] h[n]
  • 构建逆系统 g [ n ] g[n] g[n]
  • 通过逆系统获得原始信号 x [ n ] = y [ n ] ∗ G [ n ] x[n]=y[n]*G[n] x[n]=y[n]G[n]

值得注意的是,在实际场景中,过程会比较复杂,例如不存在发射约定好的信号,或者场景变换导致冲激响应的变化等等,这就需要一个自适应滤波器不断的估计回声信号,当然这是以后的内容。

4.逆系统与原系统的零极点关系

对于Z变换的频率响应,它的逆系统
H ( z ) = ∏ m = 1 M ( 1 − c m z − 1 ) ∏ n = 1 N ( 1 − d n z − 1 ) , G ( z ) = ∏ n = 1 N ( 1 − d n z − 1 ) ∏ m = 1 M ( 1 − c m z − 1 ) H(z)=\frac{\prod_{m=1}^M(1-c_mz^{-1})}{\prod_{n=1}^N(1-d_nz^{-1})},G(z)=\frac{\prod_{n=1}^N(1-d_nz^{-1})}{\prod_{m=1}^M(1-c_mz^{-1})} H(z)=n=1N(1dnz1)m=1M(1cmz1),G(z)=m=1M(1cmz1)n=1N(1dnz1)
也就是原系统 H ( z ) H(z) H(z)和逆系统 G ( z ) G(z) G(z)的零极点是互换的,那么此时如果逆系统 G ( z ) G(z) G(z)是因果稳定的,那么逆系统 G ( z ) G(z) G(z)的零点和极点都在单位圆内,而此时原系统的 H ( z ) H(z) H(z)零点和极点同样都在单位圆内,此时都为最小相位系统。

这也是上一篇文章中最小相位系统提到的特性。

二、使用逆系统去除回声

现在使用matlab来设计一个逆系统,对于已知的输入信号和输出信号进行转换。

获取原信号的频谱

需要注意的是,这里的输入信号和输出信号是笔者自己通过pcm叠加转换的,所以频域上可能看不出特别大的区别,但是实际可以明显听到回声。

核心代码

%输入信号和输出信号频域图
H_in=fft(input_signal);
H_out=fft(output_signal);
R_in = abs(H_in);
R_out = abs(H_out);
freq=linspace(0,fs/2, floor(min_len/2));figure;
subplot(2,1,1);
plot(freq, R_in(1:floor(min_len/2)));
title("输入信号频域图");xlabel("频率H(z)");ylabel("幅度");grid on;
subplot(2,1,2);
plot(freq, R_out(1:floor(min_len/2)));
title("输出信号频域图");xlabel("频率H(z)");ylabel("幅度");grid on;

得到结果:
在这里插入图片描述

原系统和逆系统幅频响应和相频响应

通过图像幅频响应图像和相频响应的图像,可以很清楚的看到原系统和逆系统的幅频响应和相频响应是倒过来的。

同时值得注意的是:

  • 某些频率上幅值接近零(即原系统在这些频率上有很强的衰减),那么其倒数 H i n v H_{inv} Hinv可能会变得非常大,导致放大效应。
  • 在计算 H i n v H_{inv} Hinv浮点数精度问题可能会导致不稳定。
  • 幅度部分可能被正常恢复,但相位的误差会导致合成信号在时域上发生相干叠加,造成某些时刻的峰值更大,最终影响整体信号能量。

而这些问题需要结合窗口平滑来进行解决,这里是通过增加了一些阈值来减少极端值的出现。

代码如下:

H_c = H_in ./ (H_out + eps);
%H_inv= 1 ./ (H_c + eps);
%H_inv(abs(H_c) < 1e-3) = 0;
H_inv = 1 ./ (H_c + 0.01);
H_inv(abs(H_c) < 1e-2) = 0;
R_c=abs(H_c);
R_inv=abs(H_inv);figure;
subplot(2,2,1);
plot(freq, 20*log10(R_c(1:floor(min_len/2))));
title('原系统幅频响应');xlabel('频率 (Hz)'); ylabel('幅度 (dB)'); grid on;
subplot(2,2,2);
plot(freq, rad2deg(angle(H_c(1:floor(min_len/2)))));
title('原系统相频响应');xlabel('频率 (Hz)'); ylabel('相位(度)'); grid on;
subplot(2,2,3);
plot(freq, 20*log10(R_inv(1:floor(min_len/2))));
title('逆系统幅频响应');xlabel('频率 (Hz)'); ylabel('幅度 (dB)'); grid on;
subplot(2,2,4);
plot(freq, rad2deg(angle(H_inv(1:floor(min_len/2)))));
title('逆系统相频响应');xlabel('频率 (Hz)'); ylabel('相位(度)'); grid on;

得到
在这里插入图片描述

使用逆系统恢复原始信号

最后恢复的信号还是变大了,但是此时已经听不见回声了,这里在恢复时已经使用整体能量归一化来尽量减少能量放大的影响。

代码如下:

%还原后的信号频谱
restored_signal = real(ifft(fft(output_signal) .* H_inv));
restored_signal = restored_signal / norm(restored_signal) * norm(input_signal);restored_signal = int16(restored_signal);
fwrite(turn_file, restored_signal, 'int16');
fclose(turn_file);
H_restored = fft(restored_signal);
R_res = abs(H_restored);
figure;
subplot(1,1,1);
plot(freq, R_res(1:floor(min_len/2)));
title('还原信号的频域图');
xlabel('频率 (Hz)'); ylabel('幅度'); grid on;

得到
在这里插入图片描述

整体代码如下

fs=16000;
input_file=fopen("input.pcm",'rb');
output_file=fopen("output.pcm",'rb');
turn_file=fopen("turn.pcm",'wb+');input_signal=fread(input_file, inf, 'int16');
output_signal=fread(output_file, inf, 'int16');
fclose(input_file);
fclose(output_file);min_len=min(length(input_signal), length(output_signal));
input_signal=input_signal(1:min_len);
output_signal=output_signal(1:min_len);%输入信号和输出信号频域图
H_in=fft(input_signal);
H_out=fft(output_signal);
R_in = abs(H_in);
R_out = abs(H_out);
freq=linspace(0,fs/2, floor(min_len/2));figure;
subplot(2,1,1);
plot(freq, R_in(1:floor(min_len/2)));
title("输入信号频域图");xlabel("频率H(z)");ylabel("幅度");grid on;
subplot(2,1,2);
plot(freq, R_out(1:floor(min_len/2)));
title("输入信号相频响应");xlabel("频率H(z)");ylabel("幅度");grid on;%原系统和逆系统幅频响应和相频响应
H_c = H_in ./ (H_out + eps);
%H_inv= 1 ./ (H_c + eps);
%H_inv(abs(H_c) < 1e-3) = 0;
H_inv = 1 ./ (H_c + 0.01);
H_inv(abs(H_c) < 1e-2) = 0;
R_c=abs(H_c);
R_inv=abs(H_inv);figure;
subplot(2,2,1);
plot(freq, 20*log10(R_c(1:floor(min_len/2))));
title('原系统幅频响应');xlabel('频率 (Hz)'); ylabel('幅度 (dB)'); grid on;
subplot(2,2,2);
plot(freq, rad2deg(angle(H_c(1:floor(min_len/2)))));
title('原系统相频响应');xlabel('频率 (Hz)'); ylabel('相位(度)'); grid on;
subplot(2,2,3);
plot(freq, 20*log10(R_inv(1:floor(min_len/2))));
title('逆系统幅频响应');xlabel('频率 (Hz)'); ylabel('幅度 (dB)'); grid on;
subplot(2,2,4);
plot(freq, rad2deg(angle(H_inv(1:floor(min_len/2)))));
title('逆系统相频响应');xlabel('频率 (Hz)'); ylabel('相位(度)'); grid on;%还原后的信号频谱
restored_signal = real(ifft(fft(output_signal) .* H_inv));
restored_signal = restored_signal / norm(restored_signal) * norm(input_signal);restored_signal = int16(restored_signal);
fwrite(turn_file, restored_signal, 'int16');
fclose(turn_file);
H_restored = fft(restored_signal);
R_res = abs(H_restored);
figure;
subplot(1,1,1);
plot(freq, R_res(1:floor(min_len/2)));
title('还原信号的频域图');
xlabel('频率 (Hz)'); ylabel('幅度'); grid on;

总结

本文中所使用的逆系统是基于原系统是一个最小相位系统来构建的。那如果原系统不是最小相位系统是存在一个不会发散的逆系统呢?其实答案已经在上一篇文章中给出了,那就是使用全通分解,去除零极点在单位圆外的影响。只使用全通分解中对于最小相位系统的部分。

其次,值得注意的是,本文中的例子是给定了参考信号来进行回声消除,但在实际环境中,对于参考信号如何辨别是否是回声,这需要使用自适应滤波器来进行回声建模。

反正收藏也不会看,不如点个赞吧!

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

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

相关文章

vue3 使用sass变量

1. 在<style>中使用scss定义的变量和css变量 1. 在/style/variables.scss文件中定义scss变量 // scss变量 $menuText: #bfcbd9; $menuActiveText: #409eff; $menuBg: #304156; // css变量 :root {--el-menu-active-color: $menuActiveText; // 活动菜单项的文本颜色--el…

gbase8s rss集群通信流程

什么是rss RSS是一种将数据从主服务器复制到备服务器的方法 实例级别的复制 (所有启用日志记录功能的数据库) 基于逻辑日志的复制技术&#xff0c;需要传输大量的逻辑日志,数据库需启用日志模式 通过网络持续将数据复制到备节点 如果主服务器发生故障&#xff0c;那么备用服务…

熵与交叉熵详解

前言 本文隶属于专栏《机器学习数学通关指南》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见《机器学习数学通关指南》 ima 知识库 知识库广场搜索&#…

程序化广告行业(3/89):深度剖析行业知识与数据处理实践

程序化广告行业&#xff08;3/89&#xff09;&#xff1a;深度剖析行业知识与数据处理实践 大家好&#xff01;一直以来&#xff0c;我都希望能和各位技术爱好者一起在学习的道路上共同进步&#xff0c;分享知识、交流经验。今天&#xff0c;咱们聚焦在程序化广告这个充满挑战…

探索在生成扩散模型中基于RAG增强生成的实现与未来

概述 像 Stable Diffusion、Flux 这样的生成扩散模型&#xff0c;以及 Hunyuan 等视频模型&#xff0c;都依赖于在单一、资源密集型的训练过程中通过固定数据集获取的知识。任何在训练之后引入的概念——被称为 知识截止——除非通过 微调 或外部适应技术&#xff08;如 低秩适…

DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加列宽调整功能,示例Table14基础固定表头示例

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

取反符号~

取反符号 ~ 用于对整数进行按位取反操作。它会将二进制表示中的每一位取反&#xff0c;即 0 变 1&#xff0c;1 变 0。 示例 a 5 # 二进制表示为 0000 0101 b ~a # 按位取反&#xff0c;结果为 1111 1010&#xff08;补码表示&#xff09; print(b) # 输出 -6解释 5 的二…

论文阅读分享——UMDF(AAAI-24)

概述 题目&#xff1a;A Unified Self-Distillation Framework for Multimodal Sentiment Analysis with Uncertain Missing Modalities 发表&#xff1a;The Thirty-Eighth AAAI Conference on Artificial Intelligence (AAAI-24) 年份&#xff1a;2024 Github&#xff1a;暂…

WBC已形成“东亚-美洲双中心”格局·棒球1号位

世界棒球经典赛&#xff08;WBC&#xff09;作为全球最高水平的国家队棒球赛事&#xff0c;参赛队伍按实力、地域和历史表现可分为多个“阵营”。以下是基于历届赛事&#xff08;截至2023年&#xff09;的阵营划分及代表性队伍分析&#xff1a; 第一阵营&#xff1a;传统豪强&a…

django中路由配置规则的详细说明

在 Django 中,路由配置是将 URL 映射到视图函数或类视图的关键步骤,它决定了用户请求的 URL 会触发哪个视图进行处理。以下将详细介绍 Django 中路由配置的规则、高级使用方法以及多个应用配置的规则。 基本路由配置规则 1. 项目级路由配置 在 Django 项目中,根路由配置文…

【报错】微信小程序预览报错”60001“

1.问题描述 我在微信开发者工具写小程序时&#xff0c;使用http://localhost:8080是可以请求成功的&#xff0c;数据全都可以无报错&#xff0c;但是点击【预览】&#xff0c;用手机扫描二维码浏览时&#xff0c;发现前端图片无返回且报错60001&#xff08;打开开发者模式查看日…

栅格裁剪(Python)

在地理数据处理中&#xff0c;矢量裁剪栅格是一个非常重要的操作&#xff0c;它可以帮助我们提取感兴趣的区域并获得更精确的分析结果。其重要性包括&#xff1a; 区域限定&#xff1a;地球科学研究通常需要关注特定的地理区域。通过矢量裁剪栅格&#xff0c;我们可以将栅格数…

【无人机路径规划】基于麻雀搜索算法(SSA)的无人机路径规划(Matlab)

效果一览 代码获取私信博主基于麻雀搜索算法&#xff08;SSA&#xff09;的无人机路径规划&#xff08;Matlab&#xff09; 一、算法背景与核心思想 麻雀搜索算法&#xff08;Sparrow Search Algorithm, SSA&#xff09;是一种受麻雀群体觅食行为启发的元启发式算法&#xff0…

MySQL数据库安装及基础用法

安装数据库 第一步&#xff1a;下载并解压mysql-8.4.3-winx64文件夹 链接: https://pan.baidu.com/s/1lD6XNNSMhPF29I2_HBAvXw?pwd8888 提取码: 8888 第二步&#xff1a;打开文件中的my.ini文件 [mysqld]# 设置3306端口port3306# 自定义设置mysql的安装目录&#xff0c;即解…

软件工程:软件开发之需求分析

物有本末&#xff0c;事有终始。知所先后&#xff0c;则近道矣。对软件开发而言&#xff0c;软件需求乃重中之重。必先之事重千钧&#xff0c;不可或缺如日辰。 汽车行业由于有方法论和各种标准约束&#xff0c;对软件开发有严苛的要求。ASPICE指导如何审核软件开发&#xff0…

正则表达式,idea,插件anyrule

​​​​package lx;import java.util.regex.Pattern;public class lxx {public static void main(String[] args) {//正则表达式//写一个电话号码的正则表达式String regex "1[3-9]\\d{9}";//第一个数字是1&#xff0c;第二个数字是3-9&#xff0c;后面跟着9个数字…

RISC-V医疗芯片工程师复合型转型的路径与策略

从RISC-V到医疗芯片:工程师复合型转型的路径与策略 一、引言 1.1 研究背景 在科技快速发展的当下,芯片技术已然成为推动各行业进步的核心驱动力之一。其中,RISC-V 架构作为芯片领域的新兴力量,正以其独特的优势迅速崛起,对整个芯片产业的格局产生着深远影响。RISC-V 架…

【设计模式】掌握建造者模式:如何优雅地解决复杂对象创建难题?

概述 将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 分离了部件的构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于&#xff1a;某个对象的构建过程复杂的情况。 由于实现了构建和装配的解耦。…

量子计算对区块链技术的影响:革新与挑战

量子计算对区块链技术的影响&#xff1a;革新与挑战 大家好&#xff0c;我是你们的技术伙伴Echo_Wish。今天我们来探讨一个颇具前沿性的话题——量子计算对区块链技术的影响。量子计算作为新一代计算技术&#xff0c;其强大的计算能力为各个领域带来了革新。然而&#xff0c;量…

【Java代码审计 | 第八篇】文件操作漏洞成因及防范

未经许可&#xff0c;不得转载。 文章目录 文件操作漏洞文件读取漏洞基于 InputStream 的读取基于 FileReader 的读取 文件下载漏洞文件删除漏洞防范 文件操作漏洞 分为文件读取漏洞、文件下载漏洞与文件删除漏洞。 文件读取漏洞 在Java中&#xff0c;文件读取通常有两种常见…