傅里叶变换应该是上大二的时候《信号与系统》课上学过,上研后在《数字信号处理》课上又学了一遍。当初一直在想傅里叶变换到底有什么用呢?什么时候能用上呢?时间如梭,没想到毕业四年后,一个小项目要用到傅里叶变换,喜大普奔啊,当初晦涩的概念、眼晕的公式,终于没白学。是的, 其实 任何知识都不是白学的,即使工作中一直用不到傅里叶变换,至少思维得到了锻炼,都是有益的。 在应用傅里叶变换过程中,可以按照公式自己编程实现,也可以使用已有的开源傅里叶变换函数库。经过查阅资料,本人选用fftw函数库来进行傅里叶变换,因为 fftw 官网上提到说该函数库性能非常出众,甚至可以和同类型的商业软件相竞争。fftw官网地址为: http://www.fftw.org/。
一、fftw下载
由于本人是在windows平台开发,于是到下面链接:http://www.fftw.org/install/windows.html下载已编译版本。如下图所示,该图信息量很大,既有32/64两个版本的下载链接,同时还有生成lib文件命令。即32位系统命令为: lib /def:libfftw3-3.def,而64位系统为: lib /machine:x64 /def:libfftw3-3.def。
下载解压后,会发现只有dll和头文件,在没有lib文件时,使用fftw库时会比较繁琐。于是在应用fftw编程前还是动手先生成lib文件。方法很简单,首先打开VS命令提示工具。本人使用的开发工具为VS2005,如下图所示:
打开后,cd到已下载的fftw文件目录,然后执行前面提到的lib生成命令,如下图所示:
命令执行完毕后,即可在当前目录内看到新生成的lib文件,我这边分别生成了double、float、long double三个版本,实际使用时可根据项目需要,选择相应精度的版本。生成的lib库文件如下图所示:
二、简单编程实例
有了头文件、lib/dll文件,那就什么都有了。新建一个工程,马上用起来吧。下面为一个非常简单的编程实例,主要完成实数傅里叶变换,输入为正弦曲线,输出为傅里叶变换的幅度谱。
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "include/fftw3.h"
#pragma comment(lib, "libfftw3-3.lib") // double版本
// #pragma comment(lib, "libfftw3f-3.lib")// float版本
// #pragma comment(lib, "libfftw3l-3.lib")// long double版本
#define PI 3.1415926
int main()
{
int len = 8;
double *in = NULL;
// 如果要使用float版本,需先引用float版本的lib库,然后在fftw后面加上f后缀即可.
fftw_complex *out = NULL;// fftwf_complex --> 即为float版本
fftw_plan p;
in = (double *)fftw_malloc(sizeof(double) * len);
out = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * len);
double dx = 1.0 / len;
// 输入纯实数
for (int i = 0; i < len; i++)
{
in[i] = sin(2*PI * dx*i) + sin(4*PI * dx*i);
printf("%.2f ", in[i]);
}
printf("\n\n");
// 傅里叶变换
p = fftw_plan_dft_r2c_1d(len, in, out, FFTW_ESTIMATE);
fftw_execute(p);
// 输出幅度谱
for (int i = 0; i < len; i++)
{
float len = sqrt(out[i][0]*out[i][0] + out[i][1]*out[i][1]);
printf("%.2f ", len);
}
printf("\n");
// 释放资源
fftw_destroy_plan(p);
fftw_free(in);
fftw_free(out);
system("pause");
return 0;
}