快速傅里葉變換很難實現(xiàn)嗎净捅?其實有它就足夠了

相信內(nèi)行一看標(biāo)題就知道我要說誰了疑枯!沒錯,就是 FFTW 蛔六。這是一個求解快速傅里葉變換的開源庫荆永,就連大佬級別的Matlab也是用FFTW家的庫。當(dāng)然了国章,也有人知道這個庫的存在具钥,可能苦于這個庫還不足夠傻瓜,而長時間沒有親自體驗液兽。本文的目的就是一步一步道來FFTW的使用過程骂删。linux和mac系統(tǒng)下的使用太簡單了,問后稍微提一下就行抵碟。主要講解windows系統(tǒng)下的使用,我這里使用的環(huán)境是:windows 10 + Visual Studio 2017 Community版本

Windows

下載

獲取FFTW庫有兩種方式坏匪,一種是從 源碼編譯 拟逮;一種是直接使用 官方發(fā)布的dll,有 x63win32 兩種版本可供選擇适滓。我推薦 第二種方式 敦迄。我測試的是x64版本,直接 下載 后解壓即可。解壓后的文件列表如下圖所示:

FFTW-3.3.5-dll64.zip解壓后的文件列表

綠色方框內(nèi)的 .dll 文件和 .def 文件是兩個關(guān)鍵文件罚屋。還有類似的兩組苦囱,分別后面帶有 fl 應(yīng)該表示數(shù)值精度的區(qū)別,同樣的用法脾猛。

生成lib

一般在VS中編寫C/C++程序調(diào)用dll時候撕彤,同時也需要lib文件作為連接庫文件。雖然FFTW下載文件里面沒有對應(yīng)的lib文件猛拴,但是沒關(guān)系羹铅,可以使用一個工具生成lib文件。

這個工具就是vs2017自帶的一個程序 lib.exe愉昆,位于 C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\bin\Hostx64\x64 目錄(自己的系統(tǒng)下也可以按照類似的路徑去尋找)职员。

然后在命令行中切換到此目錄下,運行命令跛溉。
命令格式為:lib /out:保存lib的路徑\fftw3-3.lib /machine:x64或者win32 /def:.def文件的路徑\fftw3-3.def
運行命令: lib /out:D:\SoftwareProject\fftw-3.3.5-dll64\fftw3-3.lib /machine:x64 /def:D:\SoftwareProject\fftw-3.3.5-dll64\libfftw3-3.def 焊切。
或者直接在隨便一個目錄下新建一個.bat文件(比如createlib.bat),里面寫入如下代碼芳室,然后雙擊運行即可

C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\bin\Hostx64\x64\lib /out:D:\SoftwareProject\fftw-3.3.5-dll64\fftw3-3.lib /machine:x64 /def:D:\SoftwareProject\fftw-3.3.5-dll64\libfftw3-3.def

然后在代碼中填入的lib生成路徑(D:\SoftwareProject\fftw-3.3.5-dll64)下看到新生成的兩個文件: fftw3-3.lib和fftw3-3.exp∽ǚ荆現(xiàn)在就可以正式編寫代碼使用fftw進行快速傅里葉變換啦。

使用fftw

這里舉個一維傅里葉變換的例子渤愁,二維和三維的用法與一維的類似牵祟,細(xì)節(jié)可以參考 官方文檔

問題描述和模擬數(shù)據(jù)生成

(1) 問題: 提取一個疊加正弦信號的頻率抖格。
(2)模擬信號: 用代碼生成頻率為30 Hz和90Hz的兩個正弦信號的疊加作為模擬信號诺苹,可用下面這段matlab代碼生成,并保存到文件 signal_30_90.txt雹拄。

% create a 1-D signal with frequancy of 30Hz and 90Hz
f1=30; f2=90;
x=linspace(-3*pi,3*pi,2000);
y=sin(2*pi*f1*x)+sin(2*pi*f2*x);

figure(1);
plot(x,y);

fpout=fopen('signal_30_90.txt','w');
for i=1:length(x)
    fprintf(fpout,'%.5E  %.5E\n',x(i),y(i));
end

fclose(fpout);

編寫C++代碼使用fftw進行頻譜分析

前奏
(1)添加fftw頭文件
有兩種方式添加fftw的頭文件到自己的項目中:第一種方式是直接將解壓文件中的fftw3.h拷貝到項目目錄下收奔;第二種方式是在vs2017的項目屬性中添加包含目錄中加入fftw3.h所在的路徑。然后就可以在自己的代碼中用 #include "fftw3.h包含頭文件了滓玖,不然編譯器會提示錯誤:找不到頭文件坪哄。推薦第一種方式,因為畢竟文件很小很少势篡,而且這種方式方便移植程序給別人 翩肌。
(2)添加鏈接庫
與(1)類似,將libfftw3-3.lib拷貝到項目目錄下禁悠,然后在vs2017項目屬性中的連接庫下面添加libfftw3-3.lib念祭,操作過程如下圖所示:

在項目中添加fftw鏈接庫操作示意圖

在代碼中使用fftw

首先將fftw通過 #include "fftw3.h"將fftw的頭文件加入代碼中,然后就可以用fftw中的函數(shù)進行正碍侦、逆傅里葉變換粱坤。
下面代碼功能是從文件 signal_30_90.txt 中讀取信號隶糕,然后對其進行傅里葉變化求出頻譜并保存到文件 Spectrum_Singal.txt 中,結(jié)果見下圖

信號及其頻譜
// TestFFT.cpp : 此文件包含 "main" 函數(shù)站玄。程序執(zhí)行將在此處開始并結(jié)束枚驻。
//

#define PI 3.141592653

#include <iostream>
#include <fstream>
using namespace std;

// 將fftw的使用進行一定的封裝,??使用過程更簡便
void FFT1d(vector<double> invector_r, fftw_complex* out_c);
//測試一維傅里葉變換
int testFFT1d();

int main()
{
    //測試一維傅里葉變換:求解一個正弦疊加信號的頻譜
    testFFT1d();
    return 0;
}

void FFT1d(vector<double> invector_r, fftw_complex* out_c)
{
    //1. 申明數(shù)據(jù)輸入輸出數(shù)組
    fftw_complex *in;
    //2. 申明fft執(zhí)行變量
    fftw_plan p;//,q;
    //3. 給出數(shù)據(jù)個數(shù)
    int N = invector_r.size();
    //4. 根據(jù)數(shù)據(jù)個數(shù)開辟動態(tài)數(shù)組空間
    in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)* N);
    //out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)* N);
    //5. 給輸入數(shù)據(jù)數(shù)組賦值
    for (int i = 0; i < N; i++)
    {
        in[i][0] = invector_r[i];
        in[i][1] = 0.0;
        //printf("%6.2f \n", in[i][0]);
    }
    //6. 調(diào)用fft執(zhí)行函數(shù)
    p = fftw_plan_dft_1d(N, in, out_c, FFTW_FORWARD, FFTW_ESTIMATE);
    fftw_execute(p); /* repeat as needed*/

    //8. 最后銷毀fft相關(guān)的變量
    fftw_destroy_plan(p);
    //fftw_destroy_plan(q);
    fftw_free(in);
}
int testFFT1d()
{
    string filename = "data\\signal_30_90.txt";
    ifstream fin = ifstream(filename);
    vector<double> t;
    vector<double> amplitude;
    vector<double> fvector;
    vector<double> SpectrumVector;
    double t0, amp0;
    if (!fin)
    {
        cout << "打開文件失斨昕酢: " << endl;
        return 0;
    }
    while (!fin.eof())
    {
        fin >> t0 >> amp0;
        t.push_back(t0);
        amplitude.push_back(amp0);
    }
    cout << t[0] << "  " << amplitude[0] << "  " << t.size() << endl;
    
    //2. Calculate FFT
    fftw_complex* fftout=(fftw_complex*)fftw_malloc(sizeof(fftw_complex)*t.size());
    FFT1d(amplitude, fftout);

    //3. calculate spectrum
    GetSpectrum1d(t.size(), t[1]-t[0],fftout, fvector, SpectrumVector);

    //write spectrum to file 
    ofstream fout = ofstream("data\\Spectrum_Singal.txt");
    for (int i = 0; i < SpectrumVector.size(); i++)
    {
        fout<<fvector[i]<<"\t" << SpectrumVector[i] << endl;
    }
    fout.close();

    //free pointer
    fftw_free(fftout);

    return 0;
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末再登,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子灾常,更是在濱河造成了極大的恐慌霎冯,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钞瀑,死亡現(xiàn)場離奇詭異沈撞,居然都是意外死亡,警方通過查閱死者的電腦和手機雕什,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門缠俺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人贷岸,你說我怎么就攤上這事壹士。” “怎么了偿警?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵躏救,是天一觀的道長。 經(jīng)常有香客問我螟蒸,道長盒使,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任七嫌,我火速辦了婚禮少办,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘诵原。我一直安慰自己英妓,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布绍赛。 她就那樣靜靜地躺著蔓纠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吗蚌。 梳的紋絲不亂的頭發(fā)上腿倚,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機與錄音褪测,去河邊找鬼猴誊。 笑死,一個胖子當(dāng)著我的面吹牛侮措,可吹牛的內(nèi)容都是我干的懈叹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼分扎,長吁一口氣:“原來是場噩夢啊……” “哼澄成!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起畏吓,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤墨状,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后菲饼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肾砂,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年宏悦,在試婚紗的時候發(fā)現(xiàn)自己被綠了镐确。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡饼煞,死狀恐怖源葫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情砖瞧,我是刑警寧澤息堂,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站块促,受9級特大地震影響荣堰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜褂乍,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一持隧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧逃片,春花似錦屡拨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至损离,卻和暖如春哥艇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背僻澎。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工貌踏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留十饥,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓祖乳,卻偏偏與公主長得像逗堵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子眷昆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容