[分享] FFT算法的实现

莫恩   2010-3-17 21:32 楼主

关于FFT算法全国大学生电子设计竞赛连续出了两年了,07年的音频信号分析仪,09年的音频均衡器也可以用FFT去做.国内的学生最不擅长还是算法,所有网上都找不到相关的赛后优秀论文,所以我在这里给出我已经实现并验证的思路,算法参考了网上给出的一些设计思路和代码,并进行了局部的修改和优化。这里完全套用了FFT算法公式,并不是最为优化的,因为实际的物理量并没有虚部,于是我们强制虚部为零,这样计算出的结果是关于Fs/2对称的,我们可以把一半的实部放虚部去做n/2点的FFT,这样时间上可以减少一半。所以有兴趣的网友可以在我的基础上继续研究优化算法。我也可以利用业余时间给你支持(通过站内邮箱或回帖给我留下联系方法)。
基础的知识网上都有,我就不再讲了,对这个感兴趣的应该都了解一些了.比如采样频率,频率分辨率,以及离散傅立叶变换到快速傅立叶变换的推倒等等,就说说我算法的实现吧.fs=20kHzn=512
首先是倒序,如果用的不是高速的DSP,建议你用一张表去实现,我现在用的是ARM,所以用了一张倒位的表格。我做的是512点的FFT,所以看起来表格挺大的,但是现在ARMFLASH都挺大,没有任何关系。

 

 

i=x_n_re[
1]; x_n_re[
1]=x_n_re[256]; x_n_re[256]=i;

 

 

……
i=x_n_re[479]; x_n_re[479]=x_n_re[503]; x_n_re[503]=i;

FFT的两个公式的实现网上较多的做法是用三级循环的方式,我也采用了这个思路,需要说明的是现在的控制器都有硬件乘法器,里面的乘法计算最好用汇编代码启动硬件乘法器去实现,否则编译器可能会利用软件去实现乘法计算.

for(stage=0; stage级的FFT算法

{

for(nb_index=0; nb_index

{

int tf_index = 0; // The twiddle factor index

for(sb_index=0; sb_index

{

s16 resultMulReCos;


s16 resultMulImCos;

s16 resultMulReSin;

s16 resultMulImSin;


s16 b_index = a_index+s_of_b; // 2nd fft data index

                          

resultMulReCos=MUL_1(cosLUT[tf_index],x_n_re[b_index]); // MUL_1就是汇编代码

resultMulReSin=MUL_1(sinLUT[tf_index],x_n_re[b_index]);

resultMulImCos=MUL_1(cosLUT[tf_index],x_n_im[b_index]);

resultMulImSin=MUL_1(sinLUT[tf_index],x_n_im[b_index]);
         

x_n_re[b_index] = x_n_re[a_index]-resultMulReCos+resultMulImSin;

x_n_im[b_index] = x_n_im[a_index]-resultMulReSin-resultMulImCos;

x_n_re[a_index] = x_n_re[a_index]+resultMulReCos-resultMulImSin;

x_n_im[a_index] = x_n_im[a_index]+resultMulReSin+resultMulImCos;
            

if (((sb_index+1) & (s_of_b-1)) == 0)

a_index = a_index_ref;

else

a_index++;


tf_index += n_of_b;

}

a_index
= ((s_of_b<<1) + a_index) & N_MINUS_1;


a_index_ref = a_index;

}

n_of_b >>= 1;

s_of_b <<= 1;

}
最后一步就是把FFT的结果的实部和虚部换算到实际的物理量
x_n_re =sqrt(x_n_re*x_n_re+x_n_im*x_n_im);
需要注意的是他和实际的物理量之间还有系数关系。当i=0,即为直流分量的时候理论为x_n_re /n,其他分量为x_n_re /(N/2),但实际上我们一般不关注直流分量,所以就不管他了。有些网友反应直流分量计算不准确,应该就是这个原因了。
来看看效果吧:320×240的TFT液晶,界面不美观,只是为了把频谱显示出来,信号来自麦克风,源来自电脑。

回复评论 (29)

呵呵,抛砖引玉,希望大家多发原创帖,把自己的业余作品,或者工作中的经验总结出来,发到论坛,大家一起共享,我想只要这个氛围被带动起来,大家一定会进步得更快。我平时上班都比较忙,但也在利用一些琐碎的时间做一些东东,前段时间突发其想,想做个小电视。现在已经调通了一些,还要把字符叠加的芯片给加上去,还有音频的部分正在调。做完再和大家分享。
  • 46.JPG
  • 47.JPG
  • 49.JPG
  • 51.JPG
  • 60.JPG
点赞  2010-3-17 21:51
“抛砖引玉”? 楼主这可是货真价实的 宝贝
光“/LOG_2_N级的FFT算法”这个函数就已经值得我Orz了 hoho
学习
生活在激情中 ... 希望 哈哈 https://home.eeworld.com.cn/?80086
点赞  2010-3-18 08:51
吼吼,莫哥哥的帖子,一定要顶!
点赞  2010-3-18 10:15
不错不错,好东西
点赞  2010-3-18 10:22
不错,呵呵
点赞  2010-3-18 10:55
cool!!
点赞  2010-3-18 10:56
信号采样怎么弄啊 ,是先采样模拟信号然后转换成数字吗?
点赞  2010-3-18 11:06

回复 8楼 122402902 的帖子

对,用的CPU内部AD。
点赞  2010-3-18 12:20

好牛啊!

太厉害了!更贴近实际!
点赞  2010-3-18 12:26
如果有朋友愿意继续研究下去,把算法尽一步优化,并且在EEWORLD开源,我可以提供一些PCB板,部分器件,并可以协助完成部分工作。
点赞  2010-3-18 12:26
不错,好东西
点赞  2010-3-18 13:03
嘿嘿,我对FFT不熟悉,不过还是很有兴趣的
点赞  2010-3-18 15:17
支持!!
点赞  2010-3-18 17:39
我本科论文里面就用了FFT,用的是数学物理方程书后面现成的程序,挺好用的,只是我当时是在电脑上运行的,在单片机里面跑的话会很慢,而且需要很大的RAM。
只有求知欲,没有求偶欲的人是植物,只有求偶欲,没有求知欲的人叫动物,既没求知欲,又没求偶欲的人是矿物。
点赞  2010-3-18 18:04
一般进行FFT最起码要求是信号处理MCU,不是普通单片机能胜任的。
点赞  2010-3-18 22:38
太利害
点赞  2010-3-19 09:08

回复 15楼 wangjiafu1985 的帖子

对,比如07年电子设计竞赛的A题,里面的发挥部分要求输入20~10KHz,分辨率20HZ,既采样最低要求20K,如果采样为20K,则需要采集1024点才能达到20Hz的分辨率,即使每点只有1字节(AD为8bit或者只取了AD的高8位)那么在没有优化的情况下存实部和虚部需要2048字节。
点赞  2010-3-19 12:23
莫恩对信号处理很有见解啊。啥时候给大家多讲讲。
点赞  2010-3-19 16:15
顶一下 佩服莫恩大哥 哈哈
点赞  2010-3-21 12:42
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复