前言:最近要用C++对信号进行一维傅里叶变换,但是对傅里叶变换的内容有些遗忘了,同时自己对FFTW使用也不太了解,所以写下此篇方便以后回顾。
VS项目配置FFTW3
FFTW ( the Faster Fourier Transform in the West) 是一个快速计算离散傅里叶变换的标准C语言程序集。
- FFTW包下载:FFTW网站下载对应版本的zip文件,并解压。
- Window10开始菜单栏中,搜索“X64 Native Tools Commond Prompt for VS xx”,打开运行“lib.exe”命令。
- 跳转到解压缩后的库文件目录下,依次输入如下命令生成lib库。
lib /machine:x64 /def:libfftw3-3.def
lib /machine:x64 /def:libfftw3l-3.def
lib /machine:x64 /def:libfftw3f-3.def
- 把fftw3.h文件加入VS项目的include文件夹中;将libfftw3-3.dll、libfftw3f-3.dll、libfftw3l-3.dll文件加入VS项目的bin文件夹中;VS项目中配置好相关lib,“项目-属性-连接器-输入”中补上libfftw3-3.dll、libfftw3f-3.dll和ibfftw3l-3.dll,“项目-属性-连接器-常规-附加库目录”中补上三个lib的地址的地址。
一维傅里叶变换的理解
傅里叶变换(Fourier transform):将满足一定条件的某个函数表示成三角函数(正弦和/或余弦函数)或者它们的积分的线性组合。
狄里赫莱条件:进行傅里叶变换的函数要满足狄里赫莱条件,有限个间断点;有限个极值点;绝对可积。
时域和频域:以一维傅里叶变换为例子,时域图像是信号随着时间的变换图,频域图像是傅里叶变换后不同频率的振幅。
FFTW3使用一维傅里叶变换
实际中,信号都是采样得到的,并不是连续的,而是很多个离散的点组成,假设有N个点。
fftw_complex* DataIn = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * N);
fftw_complex* DataOut = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * N);
fftw_plan plan = fftw_plan_dft_1d(N, DataIn, DataOut, FFTW_FORWARD, FFTW_ESTIMATE);
// 进行傅里叶变换
fftw_execute(plan);
// 输出幅度谱
for (int i = 1; i < len; i++)
{
float len = sqrt(DataOut[i][0]*DataOut[i][0] + DataOut[i][1]*DataOut[i][1])/(N/2);
printf("%.2f ", len);
}
代码参数解释:N表示有N个采样点;DataIn是输入数据;DataOut是输出数据;FFTW_FORWARD为正傅里叶变换(时域变到频域),FTW_BACKWARD为逆傅里叶变换(频域变到时域);FFTW_MEASURE表示准确计算,FFTW_ESTIMATE表示快速估计。
一维傅里叶变换后:
- N个采样点,经过DFT(离散傅里叶变换)之后,可以得到N个点的DFT结果,这N个点是以复数形式存储的。
- 第1个点表示0HZ,0Hz就是没有波动,专业一点叫做直流分量。从第1个点到N个点,这中间被N-1个点平均分成N等份,每个点的频率依次增加,每个点之间的间隔是Fs/N(Fs是采样频率)。
- DFT后,只需要前N/2个结果即可。一方面是因为采样频率是数字信号频率的两倍及以上,另一方面是FFT后结果是对称的。
- DFT变换后 ,数值不是真实的幅值,需要进行转换。假设说原始信号峰值是A,DFT变化后,除了第1个点直流分量是A的N倍,每个点的模值是A的N/2倍。(通常可以按照需求进行福值转换,有时候幅值很大,会采取log进行减小,以满足需求)