FFT太慢太死板?滑动DFT让计算飞起来!-转

引言:

本栏目旨在和大家分享电子设计中的各种技巧。这里是DSP、Electronic、Embedded以及FPGA共同构成的“四维世界”。这里没有长篇大论,助你“修炼成仙”的功法,只有一针见血,将问题“斩于马下”的“秘技”。这里面的“秘技”虽说不能独步天下,但足以给各位大侠的“修炼之路”提供借鉴。

简介

在许多应用中信号在频域中检测或处理比在时域中有优势。有时优势就只是一个比较简单或概念直白的算法,但频域最大的难点往往是包含在快速傅里叶变换中的复杂度或延迟。如果在一个实时应用中频域数据经常更新,FFT的复杂性和延迟会成为实现系统目标和保持低成本、低功耗的一个主要障碍。许多现实应用,比如医学成像、雷达、触屏感应以及通信系统,都使用频域算法来检测和处理信号。在许多实现中复杂性或功耗必须要低,同时要最小化延迟,在上述方面滑动DFT比FFT的频域计算性能更好。

数学理论基础

滑动DFT的推导是相当简单的,并且和DFT完全等价。也就是说,滑动DFT算法相比传统DFT或FFT算法没有信息丢失或失真。下面有完整的推导过程,没有兴趣的读者可以跳过这一节,因为它容易让人想睡觉。使用滑动DFT的基本前提是很长一段时域数据流在一个长度为N的比较短的转换窗口里。以一幅频谱图为例,频谱图是对很长一段或连续的时域采样数据流按照一定的间隔实施到长度为N的窗口的频域转换。

 

对于滑动DFT的推导,我们首先假设变换使用的是非常新的时域采样,这样的话一个长度为N的变换窗口将保持与时域数据流的每一次采样同步。输入采样流用Xk表示,(其中k的范围比N要广)在每个K采样输入时都能实现长度为N的变换。按照DFT的传统定义我们可以得到下面的第K个采样的变换,其中f表示频率,n表示长度为N的窗口中的标度:

滑动序列的下一次变换是第K+1个采样,可以表示为:

 

 

下一步我们要做的是设p=n+1,用p代替等式二中的n+1,这样p的范围就是从1到n,而不是0到n-1。接下来计算和前面是一样的,只是下标的范围发生了变化。

 


第N个式子可以从总和中独立出来表示。同时引入p=0的式子,只要在最后减去。这样看上去虽然很不优美,但是很有用:

 

上式可以被表示成:

 

 

在等式5中,由于f是整数值,所以Xk+N项的指数的值有且只有可能是1+j0,所以此项的值可化简为Xk+N。
而方括号中的和式正是第K个采样值的DFT,只是下标由n变为p。因此,等式5可以表示为:

 

算法实现

等式6就是推导后得出的滑动DFT的表达式。第K+1变换的频域值Xf,k+1可以从第k个变换的频域值Xf,k递归计算而来。第K+1个采样的频域值可以用前一个采样(第K个)的频域值加上最新输入的时域采样值中的Xk+N与第K个采样值中的Xk的差,再乘以就可以得到最新的输出。

 

相比于使用FFT,滑动DFT的优势是非常明显的。滑动DFT避免了很多不必要的运算,降低计算复杂性,节省了很多的计算资源,从而降低功耗。图1表示了实现等式6的信号流程图,它的初始延迟和相加是所有计算共用的,复数递归乘法以及累加在每个频率值计算的时候被重复。

 


图1 等式6的信号流程图

 

滑动DFT的另一个优点是如果不需要对每个输入采样进行变换的话,它可减少不必要的计算。例如,一个变换只需要M个采样输入,当所有的计算完成时,滑动DFT的计算复杂性是N×M,而FFT完成相同的工作的计算复杂性却是N×log2(N)。

 

初始化

滑动DFT算法的递归性意味着需要一些初始化方法。要想输出的Xf,k+1有效,那么Xf,k也必须是有效的。且每个输出依赖于前N采样输入。有两种常用的算法初始化方法:

1、在循环采样数据之前,先使用0来刷新延迟线。类似地,如果缓冲寄存器复位,在循环数据之前,要重置信号路径存储器为0,完成刷新。当N个数据采样完成循环,输出是有效的。

2、第一种方法中N个循环的初始化延迟可以通过前N个输入采样的FFT初始化Xf,k来避免。在一些系统中,特别是离线应用,这个方法很有优势。