FFT算法原理

FFT算法原理
FFT算法原理

2010-10-07 21:10:09| 分类:数字信号处理 | 标签:fft dft |字号订阅

在数字信号处理中常常需要用到离散傅立叶变换(DFT),以获取信号的频域特征。尽管传统的DFT算法能够获取信号频域特征,但是算法计算量大,耗时长,不利于计算机实时对信号进行处理。因此至DFT被发现以来,在很长的一段时间内都不能被应用到实际的工程项目中,直到一种快速的离散傅立叶计算方法——FFT,被发现,离散是傅立叶变换才在实际的工程中得到广泛应用。需要强调的是,FFT并不是一种新的频域特征获取方式,而是DFT的一种快速实现算法。本文就FFT的原理以及具体实现过程进行详尽讲解。

DFT计算公式

本文不加推导地直接给出DFT的计算公式:

其中x(n)表示输入的离散数字信号序列,WN为旋转因子,X(k)一组N点组成的频率成分的相对幅度。一般情况下,假设x(n)来自于低通采样,采样频率为fs,那么X(k)表示了从-fs/2率开始,频率间隔为fs/N,到fs/2-fs/N截至的N个频率点的相对幅度。因为DFT 计算得到的一组离散频率幅度只实际上是在频率轴上从成周期变化的,即X(k+N)=X(k)。因此任意取N个点均可以表示DFT的计算效果,负频率成分比较抽象,难于理解,根据X(k)的周期特性,于是我们又可以认为X(k)表示了从零频率开始,频率间隔为fs/N,到fs-fs/N截至的N个频率点的相对幅度。

N点DFT的计算量

根据(1)式给出的DFT计算公式,我们可以知道每计算一个频率点X(k)均需要进行N次复数乘法和N-1次复数加法,计算N各点的X(k)共需要N^2次复数乘法和N*(N-1)次复数加法。当x(n)为实数的情况下,计算N点的DFT需要2*N^2次实数乘法,2*N*(N-1)次实数加法。

旋转因子WN的特性

1.WN的对称性

2.WN的周期性

3.WN的可约性

根据以上这些性质,我们可以得到式(5)的一些列有用结果

基-2 FFT算法推导

假设采样序列点数为N=2^L,L为整数,如果不满足这个条件可以人为地添加若干个0以使采样序列点数满足这一要求。首先我们将序列x(n)按照奇偶分为两组如下:

于是根据DFT计算公式(1)有:

至此,我们将一个N点的DFT转化为了式(7)的形式,此时k的取值为0到N-1,现在分为两段来讨论,当k为0~N/2-1的时候,因为x1(r),x2(r)为N/2点的序列,因此,此时式(7)可以写为:

而当k取值为N/2~N-1时,k用k’+N/2取代,k’取值为0~N/2-1。对式(7)化简可得:

综合以上推导我们可以得到如下结论:一个N点的DFT变换过程可以用两个N/2点的DFT变换过程来表示,其具体公式如式(10)所示DFT快速算法的迭代公式:

上式中X'(k’)为偶数项分支的离散傅立叶变换,X''(k’’)为奇数项分支的离散傅立叶变换。式(10)的计算过程可以用图1的蝶形算法流图直观地表示出来。

图1 时间抽取法蝶形运算流

在图1中,输入为两个N/2点的DFT输出为一个N点的DFT结果,输入输出点数一致。运用这种表示方法,8点的DFT可以用图2来表示:

图2 8点DFT的4点分解

根据公式(10),一个N点的DFT可以由两个N/2点的DFT运算构成,再结合图1的蝶形信号流图可以得到图2的8点DFT的第一次分解。该分解可以用以下几个步骤来描述:

1.将N点的输入序列按奇偶分为2组分别为N/2点的序列

2.分别对1中的每组序列进行DFT变换得到两组点数为N/2的DFT变换值X1和X2

3.按照蝶形信号流图将2的结果组合为一个N点的DFT变换结果

根据式(10)我们可以对图2中的4点DFT进一步分解,得到图3的结果,分解步骤和前面一致。

图3 8点DFT的2点分解

最后对2点DFT进一步分解得到最终的8点FFT信号计算流图:

图4 8点DFT的全分解

从图2到图4的过程中关于旋转系数的变化规律需要说明一下。看起来似乎向前推一级,在奇数分组部分的旋转系数因子增量似乎就要变大,其实不是这样。事实上奇数分组部分的旋转因子指数每次增量固定为1,只是因为每向前推进一次,该分组序列的数据个数变少了,为了统一使用以原数据N为基的旋转因子就进行了变换导致的。每一次分组奇数部分的系数WN,这里的N均为本次分组前的序列点数。以上边的8点DFT为例,第一次分组N=8,第二次分组N为4,为了统一根据式(4)进行了变换将N变为了8,但指数相应的需要乘以2。

N点基-2 FFT算法的计算量

从图4可以看到N点DFT的FFT变换可以转为log2(N)级级联的蝶形运算,每一级均包含有N/2次蝶形计算。而每一个蝶形运算包含了1次复数乘法,2次复数加法。因此N点FFT计算的总计算量为:复数乘法——N/2×log2(N) 复数加法——N×log2(N)。假设被采样的序列为实数序列,那么也只有第一级的计算为实数与复数的混合计算,经过一次迭代后来的计算均变为复数计算,在这一点上和直接的DFT计算不一致。因此对于输入序列是复数还是实数对FFT算法的效率影响较小。一次复数乘法包含了4次实数乘法,2次实数加法,一次复数加法包含了2次复数加法。因此对于N点的FFT计算需要总共的实数乘法数量为:2×N×log2(N);总的复数加法次数为:

2xNxlog2(N)。

N点基-2 FFT算法的实现方法

从图4我们可以总结出对于点数为N=2^L的DFT快速计算方法的流程:

1.对于输入数据序列进行倒位序变换。

该变换的目的是使输出能够得到X(0)~X(N-1)的顺序序列,同样以8点DFT为例,该变换将顺序输入序列x(0)~x(7)变为如图4的

x(0),x(4),x(2),x(6),x(1),x(5),x(3),x(7)序列。其实现方法是:假设顺序输入序列一次存在A(0)~A(N-1)的数组元素中,首先我们将数组下标进行二进制化(例:对于点数为8的序列只需要LOG2(8) = 3位二进制序列表示,序号6就表示为110)。二进制化以后就是将二进制序列进行倒位,倒位的过程就是将原序列从右到左书写一次构成新的序列,例如序号为6的二进制表示为110,倒位后变为了011,即使十进制的3。第三步就是将倒位前和倒位后的序号对应的数据互换。依然以序号6为例,其互换过程如下:

temp = A(6);

A(6) = A(3);

A(3) = A(6);

实际上考虑到执行效率,如果对于每一次输入的数据都需要这个处理过程是非常浪费时间的。我们可以采用指向指针的指针来实现该过程,或者是采用指针数组来实现该过程。

2.蝶形运算的循环结构。

从图4中我们可以看到对于点数为N = 2^L的fft运算,可以分解为L阶蝶形图级联,每一阶蝶形图内又分为M个蝶形组,每个蝶形组内包含K个蝶形。根据这一点我们就可以构造三阶循环来实现蝶形运算。编程过程需要注意旋转因子与蝶形阶数和蝶形分组内的蝶形个数存在关联。

3.浮点到定点转换需要注意的关键问题

上边的分析都是基于浮点运算来得到的结论,事实上大多数嵌入式系统对浮点运算支持甚微,因此在嵌入式系统中进行离散傅里叶变换一般都应该采用定点方式。对于简单的DFT运算从浮点到定点显得非常容易。根据式(1),假设输入x(n)是经过AD采样的数字序列,AD 位数为12位,则输入信号范围为0~4096。为了进行定点运算我们将旋转因子实部虚部同时扩大2^12倍,取整数部分代表旋转因子。之后,我们可以按照(1)式计算,得到的结果与原结果成比例关系,新的结果比原结果的2^12倍。但是,对于使用蝶形运算的fft我们不能采用这种简单的放大旋转因子转为整数计算的方式。因为fft是一个非对称迭代过程,假设我们对旋转因子进行了放大,根据蝶形流图我们可以发现其最终的结果是,不同的输入被放大了不同的倍数,对于第一个输入x(0)永远也不会放大。举一个更加形象的例子,还是以图4为例。从图中可以看出右侧的X(0)可以直接用下式表示:

从上式我们可以看到不同输入项所乘的旋转因子个数(注意这里是个数,就算是wn^0,也被考虑进去了,因为在没有放大时wn^0等于1,放大后所有旋转因子指数模均不为1,因此需要考虑)。这就导致输入不平衡,运算结果不正确。经查阅相关资料,比较妥善的做法是,首先对所有旋转因子都放大2^Q倍,Q必须要大于等于L,以保证不同旋转因子的差异化。旋转因子放大,为了保证其模为1,在每一次蝶形运算的乘积运算中我们需要将结果右移Q位来抵消这个放大,从而得到正确的结果。之所以采用放大倍数必须是2的整数次幂的原因也在于此,我们之后可以通过简单的右移位运算将之前的放大抵消,而右移位又代替了除法运算,大大节省了时间。

快速傅里叶变换(FFT)原理及源程序

创作编号: GB8878185555334563BT9125XW 创作者: 凤呜大王* 《测试信号分析及处理》课程作业 快速傅里叶变换 一、程序设计思路 快速傅里叶变换的目的是减少运算量,其用到的方法是分级进行运算。全部计算分解为M 级,其中N M 2log =;在输入序列()i x 中是按码位倒序排列的,输出序列()k X 是按顺序排列;每级包含 2N 个蝶形单元,第i 级有i N 2 个群,每个群有12-i 个蝶形单元; 每个蝶形单元都包含乘r N W 和r N W -系数 的运算,每个蝶形单元数据的间隔为12-i ,i 为第i 级; 同一级中各个群的系数W 分布规律完全相同。 将输入序列()i x 按码位倒序排列时,用到的是倒序算法——雷德算法。 自然序排列的二进制数,其下面一个数总比上面的数大1,而倒序二进制数的下面一个数是上面一个数在最高位加1并由高位向低位仅为而得到的。 若已知某数的倒序数是J ,求下一个倒序数,应先判断J 的最高位是 否为0,与2 N k =进行比较即可得到结果。如果J k >,说明最高位为0, 应把其变成1,即2 N J +,这样就得到倒序数了。如果J k ≤,即J 的最高 位为1,将最高位化为0,即2N J -,再判断次高位;与4N k =进行比较, 若为0,将其变位1,即4 N J +,即得到倒序数,如果次高位为1,将其化 为0,再判断下一位……即从高位到低位依次判断其是否为1,为1将其变位0,若这一位为0,将其变位1,即可得到倒序数。若倒序数小于顺序数,进行换位,否则不变,防治重复交换,变回原数。

注:因为0的倒序数为0,所以可从1开始进行求解。 二、程序设计框图 (1)倒序算法——雷德算法流程图 (2)FFT算法流程

FFT 算法详解

2.3 快速傅立叶变换问题 1) 问题背景 在数值电路的传输中,为了避免信号干扰,需要把一个连续信号 x(t)先通过取样离散化为一列数值脉冲信号x(0), x(1), …… ,然后再通过编码送到传输电路中。如果取样间隔很小,而连续信号的时间段又很长,则所得到的数值脉冲序列将非常庞大。因此,传输这个编码信号就需要长时间的占用传输电路,相应地也需要付出昂贵的电路费用。 那么能否经过适当处理是使上述的数值脉冲序列变短,而同时又不会丧失有用的信息?的经过研究,人们发现,如果对上述数值脉冲序列作如下的变换处理: ∑-=--=-== 1 /21 ,1,...,1,0,)()(N k N nki i N n e k x n X π (1) 则所得到的新序列X(0), X(1) , ……将非常有序,其值比较大的点往往集中在某一很狭窄的序列段内,这将非常有利于编码和存储,从而达到压缩信息的目的。 公式(1)就是所谓的离散傅立叶变换,简称DFT 。现在我们来分析一下计算DFT 所需要的工作量。如果我们不考虑公式(7.1)中指数项的运算,那么计算其每一个点X (n) 需要N 次复数乘法和N-1次的复数加法。显然当N 很大时,这个工作量也非常巨大。正是由于这个原因,使得DFT 的应用范围在过去很长的时间里受到了严格的限制。注意到公式(1)是非常有规律性的,那么能否利用这种规律性来降低DFT 的计算时间? 1965年,凯莱和塔柯的提出了一种用于计算DFT 的数学方法,大大减少了DFT 的计算时间,同时又特别适用于硬件处理,这就是所谓的快速傅里叶变换,简称FFT 。鉴于DFT 的数据结构可以通过傅立叶变换的离散化获得,亦可通过三角插值得到,而本质上又同连续傅里叶分析有着极为密切的关系。下面我们从傅立叶级数级数和傅立叶积分入手,导出DFT 结构的来源和FFT 的工作原理。 2) 傅立叶变换 如果x(t)是定义在整个实轴上的实值或复值函数,则其傅立叶变换可由下式给出: ? ∞ ∞ ---== 1 ,)()(/2i dt e t x f X T nift (2)

FFT算法的意义

FFT是离散傅立叶变换的快速算法,可以将一个信号变换 到频域。有些信号在时域上是很难看出什么特征的,但是如 果变换到频域之后,就很容易看出特征了。这就是很多信号 分析采用FFT变换的原因。另外,FFT可以将一个信号的频谱 提取出来,这在频谱分析方面也是经常用的。 虽然很多人都知道FFT是什么,可以用来做什么,怎么去 做,但是却不知道FFT之后的结果是什意思、如何决定要使用 多少点来做FFT。 现在圈圈就根据实际经验来说说FFT结果的具体物理意义。 一个模拟信号,经过ADC采样之后,就变成了数字信号。采样 定理告诉我们,采样频率要大于信号频率的两倍,这些我就 不在此罗嗦了。 采样得到的数字信号,就可以做FFT变换了。N个采样点, 经过FFT之后,就可以得到N个点的FFT结果。为了方便进行FFT 运算,通常N取2的整数次方。 假设采样频率为Fs,信号频率F,采样点数为N。那么FFT 之后结果就是一个为N点的复数。每一个点就对应着一个频率 点。这个点的模值,就是该频率值下的幅度特性。具体跟原始 信号的幅度有什么关系呢?假设原始信号的峰值为A,那么FFT 的结果的每个点(除了第一个点直流分量之外)的模值就是A 的N/2倍。而第一个点就是直流分量,它的模值就是直流分量 的N倍。而每个点的相位呢,就是在该频率下的信号的相位。 第一个点表示直流分量(即0Hz),而最后一个点N的再下一个 点(实际上这个点是不存在的,这里是假设的第N+1个点,也 可以看做是将第一个点分做两半分,另一半移到最后)则表示 采样频率Fs,这中间被N-1个点平均分成N等份,每个点的频率 依次增加。例如某点n所表示的频率为:Fn=(n-1)*Fs/N。 由上面的公式可以看出,Fn所能分辨到频率为为Fs/N,如果 采样频率Fs为1024Hz,采样点数为1024点,则可以分辨到1Hz。1024Hz的采样率采样1024点,刚好是1秒,也就是说,采样1秒时间的信号并做FFT,则结果可以分析到1Hz,如果采样2秒时 间的信号并做FFT,则结果可以分析到0.5Hz。如果要提高频率

按时间抽取的基2FFT算法分析及MATLAB实现

按时间抽取的基2FFT 算法分析及MATLAB 实现 一、DIT-FFT 算法的基本原理 基2FFT 算法的基本思想是把原始的N 点序列依次分解成一系列短序列,充分利用旋转因子的周期性和对称性,分别求出这些短序列对应的DFT ,再进行适当的组合,得到原N 点序列的DFT ,最终达到减少运算次数,提高运算速度的目的。 按时间抽取的基2FFT 算法,先是将N 点输入序列x(n)在时域按奇偶次序分解成2个N/2点序列x1(n)和x2(n),再分别进行DFT 运算,求出与之对应的X1(k)和X2(k),然后利用图1所示的运算流程进行蝶形运算,得到原N 点序列的DFT 。只要N 是2的整数次幂,这种分解就可一直进行下去,直到其DFT 就是本身的1点时域序列。 图1 DIT-FFT 蝶形运算流图 二、DIT-FFT 算法的运算规律及编程思想 1.原位计算 [ 对N=M 2点的FFT 共进行M 级运算,每级由N/2个蝶形运算组成。在同一级中,每个蝶的输入数据只对本蝶有用,且输出节点与输入节点在同一水平线上,这就意味着每算完一个蝶后,所得数据可立即存入原输入数据所占用的数组元素(存储单元),经过M 级运算后,原来存放输入序列数据的N 个存储单元中可依次存放X(k)的N 个值,这种原位(址)计算的方法可节省大量内存。 2.旋转因子的变化规律 N 点DIT ―FFT 运算流图中,每个蝶形都要乘以旋转因子p W N ,p 称为旋转因子的指数。例如N =8 =3 2 时各级的旋转因子: 第一级:L=1, 有1个旋转因子:p W N =J /4W N =J 2L W J=0

第二级:L=2,有2个旋转因子:p W N =J /2W N =J 2L W J=0,1 第三级:L=3,有4个旋转因子:p W N =J W N =J 2L W J=0,1,2,3 对于N =M 2的一般情况,第L 级共有1-L 2个不同的旋转因子: p W N =J 2L W J=0,1,2,… ,1-L 2 -1 L 2=M 2×M -L 2= N ·M -L 2 故: 按照上面两式可以确定第L 级运算的旋转因子 \ 3、同一级中,同一旋转因子对应蝶形数目 第L 级FFT 运算中,同一旋转因子用在L -M 2 个蝶形中; 4、同一级中,蝶形运算使用相同旋转因子之间相隔的“距离” 第L 级中,蝶距:D=L 2; 5、同一蝶形运算两输入数据的距离 在输入倒序,输出原序的FFT 变换中,第L 级的每一个蝶形的2个输入数据相距:B=1 -L 2。 6、码位颠倒 输入序列x(n)经过M 级时域奇、偶抽选后,输出序列X(k)的顺序和输入序列的顺序关系为倒位关系。 '

FFT相关原理及使用注意事项

FFT相关原理及使用注意事项 在信号分析与处理中,频谱分析是重要的工具。FFT(Fast Fourier Transform,快速傅立叶变换)可以将时域信号转换至频域,以获得信号的频率结构、幅度、相位等信息。该算法在理工科课程中都有介绍,众多的仪器或软件亦集成此功能。FFT实用且高效,相关原理与使用注意事项也值得好好学习。 一、何为FFT 对于模拟信号的频谱分析,首先得使用ADC(模拟数字转换器)进行采样,转换为有限序列,其非零值长度为N,经DFT(离散傅立叶变换)即可转化为频域。DFT变换式为: 在上式中,N点序列的DFT需要进行N2次复数乘法和次复数加法,运算量大。 FFT是DFT的快速算法,利用DFT运算中的对称性与周期性,将长序列DFT分解为短序列DFT 之和。最终运算量明显减少,使得FFT应用更加广泛。 FFT基于一个基本理论:任何连续的波形,都可以分解为不同频率的正弦波形的叠加。FFT将采样得到的原始信号,转化此信号所包含的正弦波信号的频率、幅度、相位,为信号分析提供一个创新视觉。 例如在日常生活中有使用到的AM(Amplitude Modulation,幅度调制)广播,其原理是将人的声音(频率约20Hz至20kHz,称为调制波)调制到500kHz~1500kHz正弦波上(称为载波)中,载波的幅度随调制波的幅度变化。声音经这样调制后,可以传播得更远。在AM的时域波形(波形电压随时间的变化曲线),载波与调制波特征不易体现,而在FFT后的幅频曲线中则一目了然。如下图为1000kHz载波、10kHz调制波的AM调制信号,时域信号经FFT后其频率能量出现在990kHz、1.01MHz频率处,符合理论计算。 图 1 调制波10kHz、载波1000kHz的AM时域与频域曲线 二、FFT相关知识 现实生活中的模拟信号,大多都是连续复杂的,其频谱分量十分丰富。正如在数学中常量π,其真实值是个无理数。当用3.14来替代π时,计算值与真实值就会有偏差。在使用FFT这个工具时,受限于采样时的频率Fs、采样点长度N、ADC的分辨率n bit等因素的制约,所得到的信息会有所缺失与混淆。 1.奈奎斯特区与波形混叠 FFT分析结果中,存在一个那奈奎斯特区的概念,其宽度为采样率的一半Fs/2,信号频

按时间抽取的基2FFT算法分析

第四章 快速傅里叶变换 有限长序列可以通过离散傅里叶变换(DFT)将其频域也离散化成有限长序列.但其计算量太大,很难实时地处理问题,因此引出了快速傅里叶变换(FFT). 1965年,Cooley 和Tukey 提出了计算离散傅里叶变换(DFT )的快速算法,将DFT 的运算量减少了几个数量级。从此,对快速傅里叶变换(FFT )算法的研究便不断深入,数字信号处理这门新兴学科也随FFT 的出现和发展而迅速发展。根据对序列分解与选取方法的不同而产生了FFT 的多种算法,基本算法是基2DIT 和基2DIF 。FFT 在离散傅里叶反变换、线性卷积和线性相关等方面也有重要应用。 快速傅里叶变换(FFT )是计算离散傅里叶变换(DFT )的快速算法。 DFT 的定义式为 )(k X =)()(1 0k R W n x N N n kn N ∑-= 在所有复指数值kn N W 的值全部已算好的情况下,要计算一个)(k X 需要N 次复数乘法和N -1次复数加法。算出全部N 点)(k X 共需2 N 次复数乘法和)1(-N N 次复数加法。即计算量是与2 N 成正比的。 FFT 的基本思想:将大点数的DFT 分解为若干个小点数DFT 的组合,从而减少运算量。 N W 因子具有以下两个特性,可使DFT 运算量尽量分解为小点数的DFT 运算: (1) 周期性:k N n N kn N n N k N W W W )()(++== (2) 对称性:k N N k N W W -=+) 2/(

利用这两个性质,可以使DFT 运算中有些项合并,以减少乘法次数。例子:求当N =4时,X(2)的值 ) ()]3()1([)]2()0([)()]3()1([)]2()0([)3()2()1()0()()2(0 424046 44424043 24对称性-=周期性W x x x x W x x W x x W x W x W x W x W n x X n n +++++=+++==∑= 通过合并,使乘法次数由4次减少到1次,运算量减少。 FFT 的算法形式有很多种,但基本上可以分为两大类:按时间抽取(DIT )和按频率抽取(DIF )。 4.1 按时间抽取(DIT )的FTT 为了将大点数的DFT 分解为小点数的DFT 运算,要求序列的长度N 为复合数,最常用的是M N 2=的情况(M 为正整数)。该情况下的变换称为基2FFT 。下面讨论基2情况的算法。 先将序列x(n)按奇偶项分解为两组 ?? ?=+=) ()12()()2(21r x r x r x r x 12,,1,0-=N r Λ 将DFT 运算也相应分为两组 = =)]([)(n x DFT k X ∑-=1 )(N n kn N W n x ∑∑-=-== 1 n 0 1 0)()(N n kn N N n n kn N W n x W n x 为奇数为偶数+ ∑∑-=+-=++ 1 2/0 )12(1 2/0 2)12()2(N r k r N N r rk N W r x W r x =

FFT-C快速傅里叶变换超级详细的原代码

快速傅立叶变换(FFT)的C++实现收藏 标准的离散傅立叶DFT 变换形式如: y k=Σj=0n-1a jωn-kj = A (ωn-k). (ωn k为复数1 的第k 个n 次方根,且定义多项式A (x)=Σj=0n-1a j x j) 而离散傅立叶逆变换IDFT (Inverse DFT)形式如:a j=(Σk=0n-1y kωn kj)/n . yk=Σj=0n-1 ajωn-kj = A (ωn-k). (ωnk 为复数1 的第k 个n 次方根,且定义多项式 A (x) = Σj=0n-1 ajxj ) 而离散傅立叶逆变换IDFT (Inverse DFT)形式如:aj=(Σk=0n-1 ykωnkj)/n . 以下不同颜色内容为引用并加以修正: 快速傅立叶变换(Fast Fourier Transform,FFT)是离散傅立叶变换(Discrete Fourier transform,DFT)的快速算法,它是根据离散傅立叶变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。它对傅立叶变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。 设Xn 为N 项的复数序列,由DFT 变换,任一Xi 的计算都需要N 次复数乘法和N -1 次复数加法,而一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实数加法,即使把一次复数乘法和一次复数加法定义成一次“运算”(四次实数乘法和四次实数加法),那么求出N 项复数序列的Xi ,即N 点DFT 变换大约就需要N2 次运算。当N =1024 点甚至更多的时候,需要N2 = 1048576 次运算,在FFT 中,利用ωn 的周期性和对称性,把一个N 项序列(设N 为偶数),分为两个N / 2 项的子序列,每个N / 2点DFT 变换需要(N / 2)2 次运算,再用N 次运算把两个N / 2点的DFT 变换组合成一个N 点的DFT 变换。这样变换以后,总的运算次数就变成N + 2 * (N / 2)2 = N + N2 / 2。继续上面的例子,N =1024 时,总的运算次数就变成了525312 次,节省了大约50% 的运算量。而如果我们将这种“一分为二”的思想不断进行下去,直到分成两两一组的DFT 运算单元,那么N 点的DFT 变换就只需要N * log2N 次的运算,N = 1024 点时,运算量仅有10240 次,是先前的直接算法的1% ,点数越多,运算量的节约就越大,这就是FFT 的优越性。 FFT 的实现可以自顶而下,采用递归,但是对于硬件实现成本高,对于软件实现都不够高效,改用迭代较好,自底而上地解决问题。感觉和归并排序的迭代版很类似,不过先要采用“位反转置换”的方法把Xi 放到合适的位置,设i 和j 互为s = log2N 位二进制的回文数,假设s = 3, i = (110)2 = 6, j = (011)2 = 3, 如果i ≠j , 那么Xi 和Xj 应该互换位置。(关于这个回文数的生成,是很有趣而且是很基本的操作,想当初偶初学C++ 的时候就有这样的习题。)当“位反转置换”完成后,先将每一个Xi 看作是独立的多项式,然后两个两个地将它们合并成一个多项式(每个多项式有2 项),合并实际上是“蝶形运算”(Butterfly Operation, 参考《算法导论》吧^_^),继续合并(第二次的每个多项式有4 项),直到只剩

实验八 快速傅立叶变换(FFT)实验

实验七 快速傅立叶变换(FFT )实验 一 实验目的 1. 熟悉CCS 集成开发环境; 2. 了解FFT 的算法原理和基本性质; 3. 熟悉DSP 中cmd 文件的作用及对它的修改; 4. 学习用FFT 对连续信号和时域信号进行频谱分析的方法; 5. 利用DSPLIB 中现有的库函数; 6. 了解DSP 处理FFT 算法的特殊寻址方式; 7. 熟悉对FFT 的调试方法。 二 实验内容 本实验要求使用FFT 变换对一个时域信号进行频谱分析,同时进行IFFT 。这里用到时域信号可以是来源于信号发生器输入到CODEC 输入端,也可以是通过其他工具计算获取的数据表。本实验使用Matlab 语言实现对FFT 算法的仿真,然后将结果和DSP 分析的结果进行比较,其中原始数据也直接来自Matlab 。 三 实验原理 一个N 点序列][k x 的DFT ][m X ,以及IDFT 分别定义为: 1,,1,0,][][1 0-==∑-=N m W k x m X km N N k 1,,1,0,][1 ][1 -== --=∑ N k W m X N k x km N N m 如果利用上式直接计算DFT,对于每一个固定的m,需要计算N 次复数乘法,N-1次加法,对于N 个不同的m,共需计算N 的2次方复数乘法,N*(N-1)次复数加法.显然,随着N 的增加,运算量将急剧增加, 快速傅里叶算法有效提高计算速度(本例使用基2 FFT 快速算法),利用FFT 算法只需(N/2)logN 次运算。 四 知识要点 . 1、 CMD 文件的功能及编写 2、 一种特殊的寻址方式:间接寻址 间接寻址是按照存放在某个辅助寄存器的16位地址寻址的。C54x 的8个辅助寄存器 (AR0—AR7)都可以用来寻址64K 字数据存储空间中的任何一个存储单元。 3、 TMS320C54x DSPLIB 中关于FFT 变换的一些函数的调用(SPRA480B.pdf ) 利用DSPLIB 库时,在主程序中要包含头文件:54xdsp.lib 4、 FFT 在CCS 集成开发环境下的相关头文件 #include //定义数据类型的头文件 #include //数学函数的头文件,如sqrt. #include //定义数据类型的头文件 #include // DSPLIB 库文件

FFT算法的DSP实现

FFT算法的DSP实现 对于离散傅里叶变换(DFT)的数字计算,FFT是一种有效的方法。一般假定输入序列是复数。当实际输入是实数时,利用对称性质可以使计算DFT非常有效。 一个优化的实数FFT算法是一个组合以后的算法。原始的2N个点的实输入序列组合成一个N点的复序列,之后对复序列进行N点的FFT运算,最后再由N点的复数输出拆散成2N点的复数序列,这2 N点的复数序列与原始的2N点的实数输入序列的DFT输出一致。 使用这种方法,在组合输入和拆散输出的操作中,FFT运算量减半。这样利用实数FFT 算法来计算实输入序列的DFT的速度几乎是一般FFT算法的两倍。下面用这种方法来实现一个256点实数FFT(2N=256)运算。 1.实数FFT运算序列的存储分配 如何利用有限的DSP系统资源,合理的安排好算法使用的存储器是一个比较重要的问题。本文中,程序代码安排在0x3000开始的存储器中,其中0x3000~0x3080存放中断向量表,FFT程序使用的正弦表和余弦表数据(.data段)安排在0xc00开始的地方,变量(.bss段定义) 存放在0x80开始的地址中。另外,本文中256点实数FFT程序的数据缓冲位0x2300~0x23ff , FFT变换后功率谱的计算结果存放在0x2200~0x22ff中。连续定位.cmd文件程序如下: MEMORY { PAGE 0: IPROG: origin = 0x3080,len=0x1F80 VECT: lorigin=0x3000,len=0x80 EPROG: origin=0x38000,len=0x8000 PAGE 1: USERREGS: origin=0x60,len=0x1c BIOSREGS: origin=0x7c,len=0x4 IDA TA: origin=0x80,len=0xB80 EDA TA: origin=0xC00,len=0x1400 } SECTIONS { .vectors: { } > VECT PAGE 0 .sysregs: { } > BIOSREGS PAGE 1 .trcinit: { } > IPROG PAGE 0 .gblinit: { } > IPROG PAGE 0 .bios: { } > IPROG PAGE 0 frt: { } > IPROG PAGE 0 .text: { } > IPROG PAGE 0 .cinit: { } > IPROG PAGE 0 .pinit: { } > IPROG PAGE 0 .sysinit: { } > IPROG PAGE 0 .data: { } > EDATA PAGE 1 .bss: { } > IDATA PAGE 1 .far: { } > IDATA PAGE 1 .const: { } > IDATA PAGE 1 .switch: { } > IDATA PAGE 1

fft_原理详解

FFT算法 FFT是离散傅立叶变换的快速算法,可以将一个信号变换到频域。有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征了。这就是很多信号分析采用FFT变换的原因。另外,FFT可以将一个信号的频谱提取出来,这在频谱分析方面也是经常用的。虽然很多人都知道FFT是什么,可以用来做什么,怎么去做,但是却不知道FFT之后的结果是什意思、如何决定要使用多少点来做FFT。现在圈圈就根据实际经验来说说FFT结果的具体物理意义。一个模拟信号,经过ADC采样之后,就变成了数字信号。采样定理告诉我们,采样频率要大于信号频率的两倍,这些我就不在此罗嗦了。 采样得到的数字信号,就可以做FFT变换了。N个采样点,经过FFT之后,就可以得到N个点的FFT结果。为了方便进行FFT运算,通常N取2的整数次方。 假设采样频率为Fs,信号频率F,采样点数为N。那么FFT之后结果就是一个为N点的复数。每一个点就对应着一个频率点。这个点的模值,就是该频率值下的幅度特性。具体跟原始信号的幅度有什么关系呢假设原始信号的峰值为A,那么FFT的结果的每个点(除了第一个点直流分量之外)的模值就是A的N/2倍。而第一个点就是直流分量,它的模值就是直流分量的N倍。而每个点的相位呢,就是在该频率下的信号的相位。第一个点表示直流分量(即0Hz),而最后一个点N的再下一个点(实际上这个点是不存在的,这里是假设的第N+1个点,也可以看做是将第一个点分做两半分,另一半移到最后)则表示采样频率Fs,这中间被N-1个点平均分成N等份,每个点的频率依次增加。例如某点n所表示的频率为:Fn=(n-1)*Fs/N。由上面的公式可以看出,Fn所能分辨到频率为为Fs/N,如果采样频率Fs为1024Hz,采样点数为1024点,则可以分辨到1Hz。1024Hz的采样率采样1024点,刚好是1秒,也就是说,采样1秒时间的信号并做FFT,则结果可以分析到1Hz,如果采样2秒时间的信号并做FFT,则结果可以分析到。如果要提高频率分辨力,则必须增加采样点数,也即采样时间。频率分辨率和采样时间是倒数关系。 假设FFT之后某点n用复数a+bi表示,那么这个复数的模就是An=根号a*a+b*b,相位就是Pn=atan2(b,a)。根据以上的结果,就可以计算出n点(n≠1,且n<=N/2)对应的信号的表达式为:An/(N/2)*cos(2*pi*Fn*t+Pn),即2*An/N*cos(2*pi*Fn*t+Pn)。对于n=1点的信号,是直流分量,幅度即为A1/N。由于FFT结果的对称性,通常我们只使用前半部分的结果,即小于采样频率一半的结果。好了,说了半天,看着公式也晕,下面圈圈以一个实际的信号来做说明。 假设我们有一个信号,它含有2V的直流分量,频率为50Hz、相位为-30度、幅度为3V的交流信号,以及一个频率为75Hz、相位为90度、幅度为的交流信号。用数学表达式就是如下: S=2+3*cos(2*pi*50*t-pi*30/180)+*cos(2*pi*75*t+pi*90/180) 式中cos参数为弧度,所以-30度和90度要分别换算成弧度。 我们以256Hz的采样率对这个信号进行采样,总共采样256点。按照我们上面的分析,Fn=(n-1)*Fs/N,我们可以知道,每

fft的发展、现状、典型算法

数字信号处理期末大作业FFT的发展史、现状及典型算法 班级 学号: 姓名:

FFT的发展史、现状及典型算法 傅里叶分析已有200多年的历史,目前FFT及其校正算法在工程实际中仍在广泛应用,展现了其不竭的生命力。本次作业我们论述FFT的现状,发展史以及一些算法,去详细了解、扩展这一算法,巩固所学知识。 一.FFT的简介 傅里叶变换是一种将信号从时域变换到频域的变换形式,然而当N很大的时候,求一个N点的DFT要完成N*N次复数乘法和N*(N-1)次复数加法,计算量非常大,所以人们开始探索一种简便的算法对于一个较大的N进行傅里叶变换。在20世纪60年代由Cooley和Tukey提出了快速傅里叶变换算法,它是快速计算DFT的一种简单高效的方法。 关于何为FFT,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。举个例子,设x(n)为N项的复数序列,由DFT 变换,任一X(m)的计算都需要N次复数乘法和N-1次复数加法,而一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实数加法,即使把一次复数乘法和一次复数加法定义成一次“运算”(四次实数乘法和四次实数加法),那么求出N项复数序列的X(m),即N点DFT变换大约就需要N^2次运算。当N=1024点甚至更多的时候,需要N2=1048576次运算,在FFT中,利用WN的周期性和对称性,把一个N项序列(设N=2k,k为正整数),分为两个N/2项的子序列,每个N/2点DFT变换需要(N/2)2次运算,再用N次运算把两个N/2点的DFT变换组合成一个N点的DFT变换。这样变换以后,总的运算次数就变成N+2*(N/2)^2=N+(N^2)/2。继续上面的例子,N=1024时,总的运算次数就变成了525312次,节省了大约50%的运算量。而如果我们将这种“一分为二”的思想不断进行下去,直到分成两两一组的DFT运算单元,那么N点的DFT变换就只需要Nlog2N次的运算,N在1024点时,运算量仅有10240次,是先前的直接算法的1%,点数越多,运算量的节约就越大,这就是FFT的优越性。 所以使用FFT算法,可以大大提高傅里叶变换的运算速度,运算时间缩短一到两个数量级,从而使DFT变换应用迅速普及,不仅在频谱分析,而且在线性卷积、线性相关等方面得到广泛应用。

快速傅里叶变换(FFT)原理及源程序

《测试信号分析及处理》课程作业 快速傅里叶变换 一、程序设计思路 快速傅里叶变换的目的是减少运算量,其用到的方法是分级进行运算。全部计算分解为M 级,其中N M 2log =;在输入序列()i x 中是按码位倒序排列的,输出序列()k X 是按顺序排列;每级包含2N 个蝶形单元,第i 级有i N 2 个群,每个群有12-i 个蝶形单元; 每个蝶形单元都包含乘r N W 和r N W -系数的运算,每个蝶形 单元数据的间隔为12-i ,i 为第i 级; 同一级中各个群的系数W 分布规律完全相同。 将输入序列()i x 按码位倒序排列时,用到的是倒序算法——雷德算法。 自然序排列的二进制数,其下面一个数总比上面的数大1,而倒序二进制数的下面一个数是上面一个数在最高位加1并由高位向低位仅为而得到的。 若已知某数的倒序数是J ,求下一个倒序数,应先判断J 的最高位是否为0,与2 N k =进行比较即可得到结果。如果J k >,说明最高位为0,应把其变成1,即2 N J +,这样就得到倒序数了。如果J k ≤,即J 的最高位为1,将最高位化为0,即2N J -,再判断次高位;与4N k =进行比较,若为0,将其变位1,即4 N J +,即得到倒序数,如果次高位为1,将其化为0,再判断下一位……即从高位到低位依次判断其是否为1,为1将其变位0,若这一位为0,将其变位1,即可得到倒序数。若倒序数小于顺序数,进行换位,否则不变,防治重复交换,变回原数。 注:因为0的倒序数为0,所以可从1开始进行求解。 二、程序设计框图 (1)倒序算法——雷德算法流程图

(2)FFT算法流程

用matlab实现fft算法

A1=str2double(get(handles.edit8,'String')); A2=str2double(get(handles.edit9,'String')); F1=str2double(get(handles.edit10,'String')); F2=str2double(get(handles.edit11,'String')); Fs=str2double(get(handles.edit12,'String')); N=str2double(get(handles.edit13,'String')); t=[0:1/Fs:(N-1)/Fs]; x=A1*sin(2*pi*F1*t)+A2*sin(2*pi*F2*t); %信号x的离散值 axes(handles.axes1) %在axes1中作原始信号图 plot(x); grid on m=nextpow2(x);N=2^m; % 求x的长度对应的2的最低幂次m if length(x)

实验二 FFT算法的MATLAB实现

班级:学号:姓名 实验二FFT算法的MATLAB实现 (一)实验目的: (1)掌握用matlab进行FFT在数字信号处理中的高效率应用。 (2)学习用FFT对连续信号和时域离散信号进行谱分析。 (二)实验内容及运行结果: 题1:若x(n)=cos(nπ/6)是一个N=12的有限序列,利用MATLAB计算它的DFT 并进行IDFT变换同时将原图与IDFT变换后的图形进行对比。当求解IFFT变换中,采样点数少于12时,会产生什么问题。 程序代码: N=12; n=0:11; Xn=cos(n*pi/6); k=0:11; nk=n'*k; WN=exp(-j*2*pi/N) WNnk=WN.^nk XK=Xn*WNnk; figure(1) stem(Xn) figure(2) stem(abs(XK)) 运行结果:

IFFT变换中,当采样点数少于12时图像如下图显示:

分析:由图像可以看出,当采样点数小于12时,x(n)的频谱不变,周期为6,而XK 的频谱图发生改变。 题2:对以下序列进行谱分析 132()()103()8470x n R n n n x n n n =+≤≤?? =-≤≤??? 其他n 选择FFT 的变换区间N 为8和16点两种情况进行频谱分析,分别打印其幅频特 性曲线并进行对比、分析和讨论。 ㈠ 程序代码: x=ones(1,3);nx=0:2; x1k8=fft(x,8); F=(0:length(x1k8)-1)'*2/length(x1k8); %进行对应的频率转换 stem(f,abs(x1k8));%8点FFT title('8点FFTx_1(n)'); xlabel('w/pi'); ylabel('幅度'); N=8时:

FFT原理与实现

FFT原理与实现 在数字信号处理中常常需要用到离散傅立叶变换(DFT),以获取信号的频域特征。尽管传统的DFT算法能够获取信号频域特征,但是算法计算量大,耗时长,不利于计算机实时对信号进行处理。因此至DFT被发现以来,在很长的一段时间内都不能被应用到实际的工程项目中,直到一种快速的离散傅立叶计算方法——FFT,被发现,离散是傅立叶变换才在实际的工程中得到广泛应用。需要强调的是,FFT并不是一种新的频域特征获取方式,而是DFT的一种快速实现算法。本文就FFT的原理以及具体实现过程进行详尽讲解。 DFT计算公式 其中x(n)表示输入的离散数字信号序列,WN为旋转因子,X(k)一组N点组成的频率成分的相对幅度。一般情况下,假设x(n)来自于低通采样,采样频率为fs,那么X(k)表示了从-fs/2率开始,频率间隔为fs/N,到fs/2-fs/N截至的N个频率点的相对幅度。因为DFT计算得到的一组离散频率幅度只实际上是在频率轴上从成周期变化的,即X(k+N)=X(k)。因此任意取N个点均可以表示DFT的计算效果,负频率成分比较抽象,难于理解,根据X(k)的周期特性,于是我们又可以认为X(k)表示了从零频率开始,频率间隔为fs/N,到fs-fs/N截至的N个频率点的相对幅度。 N点DFT的计算量 根据(1)式给出的DFT计算公式,我们可以知道每计算一个频率点X(k)均需要进行N次复数乘法和N-1次复数加法,计算N各点的X(k)共需要N^2次复数乘法和N*(N-1)次复数加法。当x(n)为实数的情况下,计算N点的DFT需要2*N^2次实数乘法,2*N*(N-1)次实数加法。 旋转因子WN的特性 1. W的对称性 N W的周期性 2. N W的可约性 3. N

FFT算法(查表法)

ARM或单片机用的FFT算法,用于信号处理。经过愚昧的本人优化,提高了计算效率 (在aduc7026 @41MHz FFT256点环境下运算时间为0.06s左右) PS:以下有两部分(fft.h和fft.c) 【复制以下内容改名为fft.h】 #ifndef __FFT_H__ #define __FFT_H__ #include #ifdef FFT_GLOBALS #define FFT_EXT #else #define FFT_EXT extern #endif #define PI 3.1415926 #define FFT_POINT 8 //设置点数(此值变,下面的也要变)(0~11) #define SAMPLE_NUM 256 //可设256或512两种数 //count[n] //count[]={1,2,4,8,16,32,64,128,256,512,1024,2048} FFT_EXT float dataR[SAMPLE_NUM]; FFT_EXT float dataI[SAMPLE_NUM]; FFT_EXT void SetData(float data,unsigned int i); //采集数据到第i个点(0~SAMPLE_NUM) FFT_EXT void FFT(void);//采样来的数据放在dataR[ ]数组中 //***************FFT结果数值处理******************************************************* //计算和返回峰(模)值,k表示第几个值(0~SAMPLE_NUM-1),type为0返回峰值,1返回模值,2返回有效值 FFT_EXT float GetPeak(unsigned int k,unsigned int type); //FFT_EXT float GetPhase(unsigned int k,unsigned int type); //计算和返回相位,k同上 //type为0返回角度,1返回弧度 //speed为采样速率,返回第k(0~SAMPLE_NUM)个点代表的频率 FFT_EXT float GetStepF(float speed,unsigned int k); FFT_EXT float GetPower1(unsigned int k); //返回功率谱的第k点 FFT_EXT float GetPower2(unsigned int k,float total); // 返回k点所占的功率百分比(单位是%) total为总功率 FFT_EXT float GetTotalPower(void); //计算功率谱总和 FFT_EXT float GetTHD(void); //计算失真度 #endif

(完整word版)stm32F103进行FFT算法教程

STM32F103 12-15元左右 本文将以一个实例来介绍如何使用STM32提供的DSP库函数进行FFT。 1.FFT运算效率 使用STM32官方提供的DSP库进行FFT,虽然在使用上有些不灵活(因为它是基4的FFT,所以FFT的点数必须是4^n),但其执行效率确实非常高效,看图1所示的FFT运算效率测试数据便可见一斑。该数据来自STM32 DSP库使用文档。 图1 FFT运算效率测试数据 由图1可见,在STM32F10x系列处理器上,如果使用72M的系统主频,进行64点的FFT运算,仅仅需要0.078ms而已。如果是进行1024点的FFT运算,也才需要2.138ms。 2.如何使用STM32提供的DSP库函数 2.1下载STM32的DSP库 大家可以从网上搜索下载得到STM32的DSP库,这里提供一个下载的地址:https://https://www.360docs.net/doc/4510244697.html,/public/STe2ecommunities/mcu/Lists/cortex_ mx_stm32/DispForm.aspx?ID=30831&RootFolder=%2fpublic%2fST e2ecommunities%2fmcu%2fLists%2fcortex%5fmx%5fstm32%2fST M32F10x%20DSP%20library%2c%20where%20is%20it 2.2添加DSP库到自己的工程项目中 下载得到STM32的DSP库之后,就可以将其添加到自己的工程项目中了。

其中,inc文件夹下的stm32_dsp.h和table_fft.h两个文件是必须添加的。stm32_dsp.h是STM32的DSP库的头文件。 src文件夹下的文件可以有选择的添加(用到那个添加那个即可)。因为我只用到了256点的FFT,所以这里我只添加了cr4_fft_256_stm32.s文件。添加完成后的项目框架如图2所示。 图2 项目框架 2.3模拟采样数据 根据采样定理,采样频率必须是被采样信号最高频率的2倍。这里,我要采集的是音频信号,音频信号的频率范围是20Hz到20KHz,所以我使用的采用频率是44800Hz。那么在进行256点FFT时,将得到44800Hz / 256 = 175Hz的频率分辨率。 为了验证FFT运算结果的正确性,这里我模拟了一组采样数据,并将该采样数据存放到了long类型的lBufInArray数组中,且该数组中每个元素的高16 位存储采样数据的实部,低16位存储采样数据的虚部(总是为0)。 为什么要这样做呢?是因为后面要调用STM32的DSP库函数,需要传入的参数规定了必须是这样的数据格式。 下面是具体的实现代码: 1 /****************************************************************** 2函数名称:InitBufInArray() 3函数功能:模拟采样数据,采样数据中包含3种频率正弦波(350Hz,8400Hz,18725Hz) 4参数说明: 5备注:在lBufInArray数组中,每个数据的高16位存储采样数据的实部, 6低16位存储采样数据的虚部(总是为0) 7作者:博客园依旧淡然(https://www.360docs.net/doc/4510244697.html,/menlsh/) 8 *******************************************************************/

相关文档
最新文档