您当前的位置:首页 > 精选知识 > 正文

fft的用法(通俗易懂的讲解FFT的让你快速了解FFT)

fft的用法(通俗易懂的讲解FFT的让你快速了解FFT)

我相信有很多关于FFT的在线教程,我也看过很多在线教程,都不是很好理解。在对FFT及其编程实现进行了基本研究后。我决定写一个关于FFT的通俗易懂的解释。所以我会在接下来的叙述中尽量用一种很通俗很详细的方式来解释。

我第一次知道傅立叶变换的时候,我沉迷于音乐的频谱,我想做一个音乐频谱显示器。看了很多资料,了解了傅立叶变换和FFT。当然,这一切都发生在之前。经过两周的系统学习和研究,我自制了一个FFT算法。我不敢说它在速度上高人一等,但我个人认为它是一种简单易懂的实现方法。经过实际的VC仿真实验,用STM32运行也很成功。

首先,要了解FFT,必须对DFT有所了解,因为两者本质上是一样的。在此之前,列出离散傅里叶变换对(DFT):

,k=0,1,…N-1

n=0,1…N-1

其中包括:

但FFT之所以叫快速傅立叶变换,是利用了以下性质(最重要的!)

周期性:

对称性:

还原性:

先把这三个公式放在这里,然后你会用到它们。

根据这些特性,一个长的DFT运算可以分解成几个短的DFT运算序列的组合,从而减少计算量。这里,为了便于理解,我使用了时间抽取快速傅立叶变换(DIT-FFT)方法。

首先,把一个序列x(n)一分为二。

对于,k=0,1,n-1,设n是2的整数次幂,即n=2 m。

按奇偶性分组x(n)。

x(2r)=x1(r)

x(2r 1)=x2(r) r=0,1,….(N/2)-1

然后DFT也分两组做预算。

(第一项为偶数,第二项为奇数)

这时,上面提到的三个属性的可还原性将发挥作用:

回顾:

那么这个公式可以简化为:

(公式1-1)

那么x1(k)和X2(k)是长度为N/2的序列X1(k)和x2(k)的N/2个点的离散傅立叶变换。

其中包括:

K=0,1,2…N/2-1

此时,一个N点的DFT被分解成两个N/2的DFT。但是X1(k),X2(k)只有N/2个点,也就是说,公式(1-1)只是DFT的前半部分。要求DFT的后半部分可以利用其对称性得到,如下:

(公式1-2)

那么表达式(1-1)和(1-2)可以由蝶形信号流图符号来表示。如图所示:

以N=8为例,可以用下图表示:

通过这种分解,每N/2点DFT只需要(n 2)/4次复数乘法,明显节省了计算量。

依此类推,继续把得到的X1(k)和X2(k)按奇偶性分解,方法同上。然后,我们得到了这张可以在百度上找到的图片的大推送。(笑)

对于这张图,我想强调的是,在进行二阶蝶形运算的时候,不应该WN1后面是WN0吗?为什么是W2N?这个问题已经困扰我一段时间了,但是唐别忘了前者的W0N展开式是W0N/2因为此时N已经按宇称分开了,所以是N/2而W2N/2也就是W2N是按可约性得到的。它可以不要在这里混淆。

运营效率就不用提了。

那 FFT算法的理论内容,然后它用C语言实现了这个算法。对于FFT算法的C语言实现,在线方法层出不穷。因为我我很懒(我我懒得看别人程序),再加上自给自足的原则,我我写了一个我个人认为很容易理解的程序,为了帮助读者理解,我我有意尽可能减少库函数的使用。一些基本函数是自己写的(难免有很多bug),但是作为FFT算法已经足够了。目前这个程序只能处理2 N个数据。理论上,如果不够,可以按以下顺序加0。我没有为了简单起见,我们不实现这个操作,但是主要的函数都是可用的。代码如下:

#包括

#包括

#定义PI 3.1415926

#定义FFT_LENGTH 8

double input[FFT_LENGTH]={1,1,1,1,1,1,1 };

Struct complex1{ //定义复杂结构

双实;//实部

双重形象;//虚部

};

//将输入的实数结果存储为复数

struct complex1结果_ dat[8];

结构复杂1 con_complex(结构复杂1 a,结构复杂1 b){

结构复杂1温度;

temp . real=(a . real * b . real)-(a . image * b . image);

temp . image=(a . image * b . real)(a . real * b . image);

返回温度;

}

int mypow(int a,int b){

int i,sum=a;

if(b==0)返回1;

for(I=1;我

sum *=a;

}

返回总和;

}

int log2(int n){

无符号I=1;

int sum=1;

对于(我;i ){

sum *=2;

if(sum=n)break;

}

返回I;

}

void交换(结构复杂1 *a,结构复杂1 *b){

结构复杂1温度;

temp=* a;

* a=* b;

* b=温度;

}

void fft(struct complex1 dat[],无符号字符N){

struct complex1 dat_buf,dat _ org

/* L是几个蝶形运算,也代表二进制位数。

n是当前蝶泳所需的次数。N最初是N/2,每次蝶形运算后需要/2。

I是反转要用的自增符号,我也用L盘系列。j是计算当前光盘类别的计算次数。

Re_i i_copy是反演中使用的变量。

k是当前圆盘cos(2*pi/N*k),k也是E的k(-J2 * pi/N)* k

*/

无符号char L,I,j,re_i=0,i_copy=0,k=0,FFT _ flag=1;

//经过观察发现,每个蝶形运算都需要N/2次运算,总共N/2*log2N次运算。

无符号字符FFT _ counter=0;

//这里要补充的2 N,这里必须省略2 n。

//蝴蝶系列(L级)

l=log2(N);

//计算每一关蝴蝶计算的次数(这里只是一个初始值)然后每次求/2。

//N=N/2;

//反转dat的顺序

for(I=1;ii _ copy=I;

re _ I=0;

for(j=L-1;j0;j - ){

//判断I的副本的最低位数,并将其移动到最高位。

//re_i是交换的号码。每次它的数字不能移动,循环后都要清零。

re _ I |=((I _ copy0x 01)I _ copy=1;

}

swap(dat[i],dat[re _ I]);

}

//执行fft计算

for(I=0;IFFT _ flag=1;

FFT _ counter=0;

for(j=0;Jif (FFT _ counter==mypower (2,I)){//每隔几次控制,每隔几次计算,

FFT _ flag=0;

} else if(FFT _ counter==0){//rest结束,继续运算。

FFT _ flag=1;

}

//当这个语句没有被判断时,fft_flag保持,这样操作就可以继续。

if(fft_flag){

dat _ buf . real=cos((2 * PI * k)/(N/mypow(2,L-I-1)));

dat _ buf . image=-sin((2 * PI * k)/(N/mypow(2,L-I-1)));

dat _ buf=con _ complex(dat[j mypow(2,i)],dat _ buf);

//计算当前蝶形运算的奇数项与w的乘积。

dat_org.real=dat[j]。真实;

dat_org.image=dat[j]。形象;//临时存储

dat[j]。real=dat _ org . real dat _ buf . real;

dat[j]。image=dat _ org . image dat _ buf . image;

//实部加实部加虚部加虚部

dat[j mypow(2,i)]real=dat _ org . real-dat _ buf . real;

dat[j mypow(2,i)]image=dat _ org . image-dat _ buf . image;

//实部减实部减虚部

k;

fft _ counter

}否则{

FFT _ counter-;//算几次,就休息几次。

k=0;

}

}

}

}

void main(){

int I;

//首先将输入信号转换成复数。

for(I=0;iresult_dat[i]。image=0;

//输入信号是二维的,暂时没有复数。

result_dat[i]。real=input[I];

//result_dat[i]。实数=10;

//输入信号都是实数

}

fft(result_dat,FFT _ LENGTH);

for(I=0;iinput[i]=sqrt(result_dat[i])。real*result_dat[i]。真实结果_dat[i]。image*result_dat[i]。图片);

//拿模具

printf(% lf \ n ,输入[I]);

}

while(1);

}

在这个程序中,输入的数组是输入信号,这里只取8个模拟样本,输出数据也是输入的。如果你想看到其他的序列,你可以改变FFT_LENGTH的值和输入的内容。程序输出实部和虚部的模块。如果你只是单纯的想看实部或虚部的幅度,请自行修改程序~这就是这篇关于FFT的简介和FFT算法的基本实现的全部内容。参考书:数字信号处理

标签:FFTIn


声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,谢谢。

上一篇: 万能打印机驱动器下载(有没有针式打印机的万能驱动)

下一篇: 双盲法和单盲法区别(双盲法)



推荐阅读