一个基于C++的FFT实现方法—librow
admin 于 2017年09月21日 发表在 数字信号处理
前几天看到一个不错的FFT变换类,基于C++语言的,感觉不错,记录在此,万一以后用到也好找。
1. 官网下载librow,并解压:
complex.h 和 complex.cpp 中定义了各种复数运算的基本单元以及基本运算的具体实现。
fft.h 和 fft.c 中定义了相关运算函数,包含傅里叶反变换、FFT具体实现等。
注:FFT相关原理,请查看博文《数字信号处理算法(2)-快速傅里叶变换(FFT)》,此处不贴。
2. 调用接口函数实现FFT,大体需要如下几步:
(1)初始化参数
double x[N]={0.0}; complex *pSignal = new complex[N]; FILE *fp; //创建文本操作对象
(2)生成原始时域信号:
for(i=0; i<N; i++) { x[i]=sin(2*PI*(5.0*i/(N-1)))+sin(2*PI*(5.0*3.0*i/(N-1)))/3.0+sin(2*PI*(5.0*5.0*i/(N-1)))/5.0; }
(3)将生成的时域值传递给定义的complex
for(i=0; i<N; i++) { pSignal[i] = x[i]; }
(4)调用librow中对应接口函数
CFFT::Forward(pSignal,N);
(5)保存并打印输出(可选)
for(i=0; i<N; i++) { pSignal[i] = sqrt(pSignal[i].re()*pSignal[i].re()+pSignal[i].im()*pSignal[i].im()); fprintf(fp,"%lf\t%lf\n",x[i],pSignal[i]); //存储数值到文本 }
(6)释放内存占用
fclose(fp); //关闭文本 delete[] pSignal;
3. 整个main.cpp函数如下:
#include <iostream> #include "fft.h" #include <math.h> #include <stdio.h> //定义PI #define PI 3.141593 #define N 64 int main() { int i=0; double x[N]={0.0}; complex *pSignal = new complex[N]; FILE *fp; //存储最终计算值 fp=fopen("data.dat","w"); //打开文本 //1.生成原始信号x[] for(i=0; i<N; i++) //产生正弦三次谐波叠加而成的方波 { x[i]=sin(2*PI*(5.0*i/(N-1)))+sin(2*PI*(5.0*3.0*i/(N-1)))/3.0+sin(2*PI*(5.0*5.0*i/(N-1)))/5.0; } //2.将原始值赋给pSignal[] for(i=0; i<N; i++) { pSignal[i] = x[i]; } //3.计算FFT数据 CFFT::Forward(pSignal,N); //4.输出计算结果 for(i=0; i<N; i++) { pSignal[i] = sqrt(pSignal[i].re()*pSignal[i].re()+pSignal[i].im()*pSignal[i].im()); fprintf(fp,"%lf\t%lf\n",x[i],pSignal[i]); //存储数值 } //5.释放内存占用 fclose(fp); //关闭文本 delete[] pSignal; }
4. 通过Qtiplot绘制对应数据的图形,如下:
补充: 通过python自带的FFT函数验证上述算法,如下:
(1)Python代码:
# -*- coding: utf-8 -*- """ Created on Tue Sep 19 23:03:53 2017 @author: lu """ import matplotlib.pyplot as plt import numpy as np N=64 x = np.linspace(0,N-1,N) y = np.sin(2*np.pi*(5*x/(N-1)))+ np.sin(2*np.pi*(5*3*x/(N-1)))/3+ np.sin(2*np.pi*(5*5*x/(N-1)))/5 plt.figure(figsize=(9,5)) plt.plot(x,y,label="$f(x)$",color="red",linewidth=2) plt.xlabel("x") plt.ylabel("f(x)") plt.title("Origin") plt.ylim(-1.1,1.1) plt.legend() plt.show() y1 = np.fft.fft(y); y2 = np.sqrt(y1.real**2 + y1.imag**2) plt.figure(figsize=(9,5)) plt.plot(x,y2,label="$F(s)$",color="red",linewidth=2) plt.xlabel("sample") plt.ylabel("F(s)") plt.title("FFT") plt.ylim(0,35) plt.legend() plt.show()
(2)输出相关的图形,如下表: