信号系统之FFT卷积

1 Overlap-Add 方法

在许多 DSP 应用中,长信号必须分段过滤。例如,高保真数字音频需要大约 5 MB/min 的数据速率,而数字视频需要大约 500 MB/min 的数据速率。在数据速率如此之高的情况下,计算机通常没有足够的内存来同时保存要处理的整个信号。还有一些系统可以逐段处理,因为它们是实时运行的。例如,电话信号的延迟不能超过几百毫秒,从而限制了在任何一个时刻可供处理的数据量。在其他应用中,处理可能需要对信号进行分段,一个例子是FFT卷积。

Overlap-Add 方法基于 DSP 中的基本技术:

  • 将信号分解为简单的分量
  • 以某种有用的方式处理每个分量
  • 将处理后的分量重新组合成最终信号

图 18-1 显示了如何对 overlap-add 方法执行此操作的示例:

  • 图(a)是要滤波的信号。
  • 图(b)显示了要使用的滤波器内核,即windowed-sinc低通滤波器。
  • 跳到图的底部,(i)显示了滤波后的信号,即(a)的平滑版本。这种方法的关键是卷积如何影响这些信号的长度。当 N 个样本信号与** M 个样本滤波器内核** 卷积时,输出信号长度为 N+M-1 个样本。例如,输入信号(a)为 300 个样本(从 0 到 299 个样本),滤波器内核(b)为 101 个样本(从 0 到 100 个样本),输出信号(i)为 400 个样本(从 0 到 399 个样本)。

换句话说,当 N 个样本信号被滤波时,它将向右扩展 M-1 点。(这是假设筛选器内核从索引 0 到 M 运行。如果在过滤器内核中使用负索引,则扩展也将在左侧)。在(a)中,在样本300和399之间的信号中添加了零,以说明这种扩展将发生的位置。不要被输出信号两端的小值(i)所迷惑。这仅仅是 windowed-sinc 滤波器内核在其末端附近具有较小值的结果。(i)中的所有 400 个样本都是非零的,即使其中一些样本太小而无法在图中看到。

图(c)、(d)和(e)显示了Overlap-Add中使用的分解:

  • 信号被分成多个段,每个段有 100 个来自原始信号的样本。此外,每个段的右侧添加了 100 个零
  • 在下一步中,通过将每个段与过滤器内核卷积来单独过滤。这将产生(f)、(g)和(h)中所示的输出段。由于每个输入段的长度为 100 个样本,而过滤器内核的长度为 101 个样本,因此每个输出段的长度为 200 个样本。需要理解的重要一点是,将 100 个零添加到每个输入段,以允许在卷积期间进行扩展。

注意,扩展会导致输出段相互重叠。将这些重叠的输出段相加以提供输出信号(i)。例如,通过将(g)和(h)中的相应样本相加,可以找到(i)中的样本200至299。Overlap-Add产生的输出信号与直接卷积完全相同。缺点是跟踪重叠样本的程序复杂性要高得多。

2 FFT 卷积

FFT卷积使用的原理是频域中的乘法对应于时域中的卷积。输入信号使用DFT转换为频域,乘以滤波器的频率响应,然后使用逆DFT转换回时域。这种基本技术自傅立叶时代以来就广为人知。然而,没有人真正关心。这是因为计算 DFT 所需的时间比直接计算卷积所需的时间长。1965 年,随着快速傅里叶变换(FFT)的发展,这种情况发生了变化。通过使用 FFT 算法计算 DFT,通过频域卷积可以比直接卷积时域信号更快。最终结果是一样的,只有计算次数被更有效的算法改变了。因此,FFT卷积也称为高速卷积

FFT卷积采用图18-1所示的Overlap-Add,仅更改了将输入段转换为输出段的方式。图 18-2 显示了如何通过 FFT 卷积将输入段转换为输出段的示例:

  • 首先,通过使用FFT获取滤波器内核的DFT来找到滤波器的频率响应。例如,(a)显示了一个示例滤波器内核,即一个窗口化 sinc 带通滤波器。FFT将其转换为频率响应的实部和虚部,如(b)和(c)所示。这些频域信号可能看起来不像带通滤波器,因为它们是矩形的。请记住,极性形式通常最适合人类理解频域,而矩形形式通常最适合数学计算。这些实部和虚部都存储在计算机中,以便在计算每个段时使用。
  • 图(d)显示了要处理的输入段。FFT用于查找其频谱,如(e)和(f)所示。然后,通过将滤波器的频率响应(b)和(c)乘以输入段的频谱(e)和(f)来找到输出段(h)和(i)的频谱。
  • 然后使用反 FFT 从其频谱(h)和(i)中找到输出段 (g)。重要的是要认识到,该输出段与输入段(d)和滤波器核(a)的直接卷积所获得的输出段完全相同。

FFT 必须足够长,不会发生循环卷积。这意味着 FFT 的长度应与输出段(g)相同。例如,在图 18-2 的示例中,滤波器核包含 129 个点,每个段包含 128 个点,使输出段长 256 个点。这需要使用 256 点 FFT。这意味着过滤器内核(a)必须填充 127 个零,才能使其总长度为 256 个点。同样,每个输入段(d)必须填充 128 个零。再举一个例子,假设需要用一个具有 600 个样本的滤波器内核对一个非常长的信号进行卷积。一种替代方法是使用 425 点和 1024 点 FFT 的段。另一种选择是使用 1449 点和 2048 点 FFT 的段。

表 18-1 显示了执行 FFT 卷积的示例程序。该程序通过使用 400 点滤波器内核卷积来过滤 1000 万点信号。这是通过将输入信号分成 16000 个段来完成的,每个段有 625 个点。当这些段中的每一个都与滤波器核卷积时,会产生 625+400-1=1024 点的输出段。因此,使用了 1024 点 FFT。定义并初始化所有阵列(第 130 至 230 行)后,第一步是计算并存储滤波器的频率响应(第 250 至 310 行)。第 260 行调用一个神话般的子例程,该子例程将过滤器内核加载到 XX[0] 到 XX[399] 中,并将 XX[400] 到 XX[1023] 设置为零值。第 270 行中的子程序是 FFT,将 XX[ ] 中保存的 1024 个样本转换为 REX[ ] 和 IMX[ ] 中保存的 513 个样本,实数和频率响应的虚部。这些值被传输到数组REFR[ ]和IMFR[ ](用于:REal和IMaginary Frequency Response)中,以便在程序的后面使用。

第 340 行和第 580 行之间的 FOR-NEXT 循环控制 16000 段的处理方式。在第 360 行中,子例程将要处理的下一段加载到 XX[0] 到 XX[624] 中,并将 XX[625] 到 XX[1023] 设置为零值。在第 370 行中,FFT 子程序用于查找该段的频谱,实部放置在 REX[] 的 513 个点中,虚部放置在 IMX[] 的 513 个点中。第 390 行至第 430 行显示了以 REX[] 和 IMX[] 保存的段频谱与以 REFR[] 和 IMFR[] 保存的滤波器频率响应的乘法。乘法的结果存储在 REX[] 和 IMX[] 中,覆盖之前的数据。由于这现在是输出段的频谱,因此可以使用IFFT来查找输出段。这是由第 450 行中神话般的 IFFT 子程序完成的,该子程序将 REX[] 和 IMX[] 中保存的 513 个点转换为输出段 XX[] 中保存的 1024 个点。

第 470 行到第 550 行处理段的重叠。每个输出段分为两个部分。前 625 个点(0 到 624)需要与前一个输出段的重叠相结合,然后写入输出信号。需要保存最后 399 个点(625 到 1023),以便它们可以与下一个输出段重叠。

要理解这一点,请回头看图 18-1。(g)中样本 100 至 199 需要与前一个输出段(f)的重叠组合,然后可以移动到输出信号(i)。相比之下,需要保存(g)中的样本 200 到 299,以便它们可以与下一个输出段(h)组合。

现在回到程序。数组 OLAP[] 用于保存从一个段到下一个段重叠的 399 个样本。在第 470 行到第 490 行中,此数组中的 399 个值(来自前一个输出段)被添加到当前正在处理的输出段中,保存在 XX[] 中。然后,第 550 行中的神话子程序将 XX[0] 到 XX[624] 中的 625 个样本输出到保存输出信号的文件中。然后,需要保留到下一个输出段的当前输出段的 399 个样本存储在 OLAP[] 的第 510 行到 530 行中。

处理完所有 0 到 15999 个段后,数组 OLAP[ ] 将包含段 15999 中的 399 个样本,这些样本应与段 16000 重叠。由于段 16000 不存在(或可以看作是包含所有零),因此 399 个样本被写入第 600 行的输出信号。这使得输出信号点的长度。这与输入信号的长度加上滤波器内核的长度减去 1 相匹配。

3 速度改进

FFT 卷积何时比标准卷积快?答案取决于过滤器内核的长度,如图 18-3 所示。时间过滤器内核。当过滤器内核有大约 40 到 80 个样本时(取决于使用的特定硬件),就会发生交叉。

重要思想是:短于大约 60 个点的滤波器内核可以通过标准卷积更快地实现,并且执行时间与内核长度成正比。使用 FFT 卷积可以更快地实现更长的滤波器内核。使用 FFT 卷积,过滤器内核可以随心所欲地制作,执行时间几乎没有损失。例如,一个 16,000 点的过滤器内核只需要大约两倍的时间来执行64个点。

卷积的速度也决定了计算的精度。这是因为输出信号中的舍入误差取决于计算总数,而计算总数与计算时间成正比。如果输出信号计算得更快,那么计算也会更精确。例如,想象一下,使用具有单精度浮点的 1000 点滤波器内核对信号进行卷积。使用标准卷积,典型的舍入噪声预计约为 20,000 分之一(来自第 4 章中的指南)。相比之下,FFT卷积可以预期要快一个数量级,精度要高一个数量级(即200,000分之一)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【程序员英语】【美语从头学】初级篇(入门)(笔记)Lesson 16 At the Shoe Store 在鞋店

《美语从头学初级入门篇》 注意:被 删除线 划掉的不一定不正确,只是不是标准答案。 文章目录 Lesson 16 At the Shoe Store 在鞋店对话A对话B笔记会话A会话B替换 Lesson 16 At the Shoe Store 在鞋店 对话A A: Do you have these shoes in size 8? B:…

SQLlabs46关

看看源码 最终我们的id是放到order by后面了 如果我们直接用列去排序 ?sortusername/password username: passward 可以看到顺序是不同的,当然第一列第二列第三列也可以,基本上都是这个原理,那怎么去实现注入呢,我…

Qt程序设计-钟表自定义控件实例

本文讲解Qt钟表自定义控件实例。 效果如下: 创建钟表类 #ifndef TIMEPIECE_H #define TIMEPIECE_H#include <QWidget> #include <QPropertyAnimation> #include <QDebug> #include <QPainter> #include <QtMath>#include <QTimer>#incl…

leetcode hot100 买卖股票的最佳时机1

本题之前采用贪心算法来解决&#xff0c;现在可以采用动态规划来解决&#xff0c;通过dp数组记录每次的状态从而获取到最大的利润。 这里dp数组定义为二维数组 dp[price.length][2]&#xff0c;其中price.length表示第i天&#xff0c;[2]其中有0/1两种状态&#xff0c;[0]表示…

设计模式(五)-观察者模式

前言 实际业务开发过程中&#xff0c;业务逻辑可能非常复杂&#xff0c;核心业务 N 个子业务。如果都放到一块儿去做&#xff0c;代码可能会很长&#xff0c;耦合度不断攀升&#xff0c;维护起来也麻烦&#xff0c;甚至头疼。还有一些业务场景不需要在一次请求中同步完成&…

【LeetCode】【滑动窗口长度不固定】978 最长湍流子数组

1794.【软件认证】最长的指定瑕疵度的元音子串 这个例题&#xff0c;是滑动窗口中长度不定求最大的题目&#xff0c;在看题之前可以先看一下【leetcode每日一题】【滑动窗口长度不固定】案例。 题目描述 定义&#xff1a;开头和结尾都是元音字母&#xff08;aeiouAEIOU&…

python 基础知识点(蓝桥杯python科目个人复习计划51)

今日复习计划&#xff1a;做复习题 例题1&#xff1a;大石头的搬运工 问题描述&#xff1a; 在一款名为“大石头的搬运工”的游戏中&#xff0c;玩家需要 操作一排n堆石头&#xff0c;进行n - 1轮游戏。 每一轮&#xff0c;玩家可以选择一堆石头&#xff0c;并将其移动到任…

【自然语言处理四-从矩阵操作角度看 自注意self attention】

自然语言处理四-从矩阵操作角度看 自注意self attention 从矩阵角度看self attention获取Q K V矩阵注意力分数softmax注意力的输出再来分析整体的attention的矩阵操作过程从矩阵操作角度看&#xff0c;self attention如何解决问题的&#xff1f;W^q^ W^k^ W^v^这三个矩阵怎么获…

安装使用zookeeper

先去官网下载zookeeper&#xff1a;Apache ZooKeeper 直接进入bin目录&#xff0c;使用powerShell打开。 输入: ./zkServer.cmd 命令&#xff0c;启动zookeeper。 zookeeper一般需要配合Dubbo一起使用&#xff0c;作为注册中心使用&#xff0c;可以参考另一篇博客&#xf…

从零开始掌握Docek的基础知识与应用技巧

目录 前言 一.docekr简介 二.docker的环境搭建 查看内核 更新yum源为最新 ​编辑 安装Docker所需要的工具包 设置yum源 下载docker ​编辑 启动Docker并且设置开机自启动 配置镜像仓库 三.docker命令 1.基本命令 2.常用命令 3.docker容器常用命令 Docker创建并启动…

Java中使用Graphics2D实现图片添加文字/图片水印

场景 java实现给图片添加水印实现步骤&#xff1a; 获取原图片对象信息&#xff08;本地图片或网络图片&#xff09; 添加水印&#xff08;设置水印颜色、字体、坐标等&#xff09; 处理输出目标图片。 注&#xff1a; 博客&#xff1a;霸道流氓气质-CSDN博客 实现 1、…

Parquet 文件生成和读取

文章目录 一、什么是 Parquet二、实现 Java 读写 Parquet 的流程方式一&#xff1a;遇到的坑&#xff1a;坑1&#xff1a;ClassNotFoundException: com.fasterxml.jackson.annotation.JsonMerge坑2&#xff1a;No FileSystem for scheme "file"坑3&#xff1a;与 spa…

020—pandas 根据历史高考分段推断当前位次的分数

前言 每年各省都会公布高考「一分一段」表&#xff0c;它是是以「一分」为单位&#xff0c;统计考得该分数的考生人数和累计人数&#xff0c;每一个分数段上有多少人一目了然。考生通过分数分布表可以查询到相关成绩在全市的排名位次&#xff0c;方便对自己进行定位。本例中&a…

嵌入式学习 Day 25

1.线程分离属性: 线程结束后,自动回收线程空间 pthread_attr_init int pthread_attr_init(pthread_attr_t *attr); 功能: 线程属性初始化 pthread_attr_destroy int pthread_attr_destroy(pthread_attr_t *attr); 功能: 线程属性销毁 pthread_attr…

计算机网络实验一 ENSP模拟器使用

实验一 eNSP模拟器的使用 学习目标&#xff1a; 1&#xff09;掌握eNSP模拟器的基本设置方法 2&#xff09;掌握使用eNSP搭建简单的端到端&#xff08;主机&#xff09;网络的方法 3&#xff09;掌握在eNSP中使用wireshark捕获IP报文的方法 4&#xff09;掌握设备的基本配置方…

内网穿透的应用-如何在群晖配置WebDAV实现云同步Zotero科研文献与笔记【内网穿透】

文章目录 前言1. Docker 部署 Trfɪk2. 本地访问traefik测试3. Linux 安装cpolar4. 配置Traefik公网访问地址5. 公网远程访问Traefik6. 固定Traefik公网地址 前言 Trfɪk 是一个云原生的新型的 HTTP 反向代理、负载均衡软件&#xff0c;能轻易的部署微服务。它支持多种后端 (D…

C++基础知识(四:类的学习)

类 类指的就是对同一类对象&#xff0c;把所有的属性都封装起来&#xff0c;你也可以把类看成一个高级版的结构体。 【1】定义 class 类名 { 访问权限:成员属性; 访问权限:成员方法; }访问权限&#xff1a; public:共有的&#xff0c;类内、类外和子类中都可以访问 private:私有…

运维的利器–监控–zabbix–grafana

运维的利器–监控–zabbix–grafana 一、介绍 Grafana 是一个跨平台的开源的度量分析和可视化工具 , 可以通过将采集的数据查询然后可视化的展示 。zabbix可以作为数据源&#xff0c;为grafana提供数据&#xff0c;然后grafana将数据以图表或者其他形式展示出来。zabbix和gra…

AI:142-开发一种智能家居系统,通过语音识别和情感分析实现智能互动

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带关键代码,详细讲解供大家学习,希望…

【c++】 STL的组件简介与容器的使用时机

STL六大组件简介 STL提供了六大组件&#xff0c;彼此之间可以组合套用&#xff0c;这六大组件分别是:容器、算法、迭代器、仿函数、适配器&#xff08;配接器&#xff09;、空间配置器。 容器&#xff1a;各种数据结构&#xff0c;如vector、list、deque、set、map等,用来存放…
最新文章