其实以前有用过fft,当时频率是对的,幅值总是不对,一直卡着,后面就放下了;最近因为项目需要,又重新研究fft转换,并且需要精度较高,所以做出一下总结,仅个人理解。
一、fft库的选择
以前用的最早的fft标准库,发现使用不是很方便,需要调试地方挺多,现在使用比较流行的fftw库,是后面大神在原fft库上做的封装,省去了很多工作,更容易理解,使用更方便。
fftw官方网站 http://www.fftw.org/
可以自行下载,感谢该博主翻译的用户手册https://www.cnblogs.com/aiguona/p/9407425.html
二、fftw库的使用
linux下使用:参考https://blog.csdn.net/grafx/article/details/38750107
window下使用:参考https://blog.csdn.net/cyh706510441/article/details/46676123 注意windows下使用,注意lib生成的位数x64建议将dll文件拷贝到C:\Windows\System32下,x86建议将dll文件拷贝到C:\Windows\SysWOW64,此处是一些博主避坑经验,但本人还是放在项目对应的目录下。
三、fft转换原理
以前没有理解fft变换的原理,一直以为一些值随意取,只要将结果调整得一样就行了,现在深入理解了fft变换的原理后,原来所以值都是有迹可寻的。
参考https://blog.csdn.net/jbb0523/article/details/44850703
此处不做过多解释,主要关注采样点数 幅值、频率、相位 的获取方式
采样点数:为保证频率获取的准确性,让精度更高,一般设置fftw转换点数为采样频率的整数倍,避免精度问题,导致某些频率值获取不到
幅值:如上图所示,|X|为fftw转换后的输出复数的sqrt(实部的平方+虚部的平方),所以最终的幅值等于 |X| / (采样点数/2)
频率:fn = n * 采样频率 / 采样数 ; n++ ,n表示在0~采样数/2的点
相位:如上图所示arctan(b/a),实际就是反正切值;在代码中使用atan2(虚部,实部)这个函数,由于atan2求出来的值为弧度值,需要转换成角度,最终相位 等于 atan(虚部,实部) * 180 / pi ;它的范围总是在-pi ~+pi;
四、验证
采集97kHz 7.7v的正弦波,通过分析得到,如图:左边是原始波形、右边是频率图、下面是相位图
结论:频率一致,幅值相近,当然,幅值有波动是正常现象
相位处只能验证起始相位,以及对应的最大幅值均一致
最后、感谢网上大佬们的分享,希望能帮助到更多人