一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

FFT原理與實(shí)現(xiàn)

 longsteg 2012-04-16

FFT原理與實(shí)現(xiàn)  

2010-10-07 21:10:09|  分類: 數(shù)字信號(hào)處理 |  標(biāo)簽:fft  dft   |字號(hào) 訂閱

在 數(shù)字信號(hào)處理中常常需要用到離散傅立葉變換(DFT),以獲取信號(hào)的頻域特征。盡管傳統(tǒng)的DFT算法能夠獲取信號(hào)頻域特征,但是算法計(jì)算量大,耗時(shí)長,不 利于計(jì)算機(jī)實(shí)時(shí)對信號(hào)進(jìn)行處理。因此至DFT被發(fā)現(xiàn)以來,在很長的一段時(shí)間內(nèi)都不能被應(yīng)用到實(shí)際的工程項(xiàng)目中,直到一種快速的離散傅立葉計(jì)算方法—— FFT,被發(fā)現(xiàn),離散是傅立葉變換才在實(shí)際的工程中得到廣泛應(yīng)用。需要強(qiáng)調(diào)的是,F(xiàn)FT并不是一種新的頻域特征獲取方式,而是DFT的一種快速實(shí)現(xiàn)算法。 本文就FFT的原理以及具體實(shí)現(xiàn)過程進(jìn)行詳盡講解。

DFT計(jì)算公式

本文不加推導(dǎo)地直接給出DFT的計(jì)算公式:

DFT公式

其 中x(n)表示輸入的離散數(shù)字信號(hào)序列,WN為旋轉(zhuǎn)因子,X(k)一組N點(diǎn)組成的頻率成分的相對幅度。一般情況下,假設(shè)x(n)來自于低通采樣,采樣頻率 為fs,那么X(k)表示了從-fs/2率開始,頻率間隔為fs/N,到fs/2-fs/N截至的N個(gè)頻率點(diǎn)的相對幅度。因?yàn)镈FT計(jì)算得到的一組離散頻 率幅度只實(shí)際上是在頻率軸上從成周期變化的,即X(k+N)=X(k)。因此任意取N個(gè)點(diǎn)均可以表示DFT的計(jì)算效果,負(fù)頻率成分比較抽象,難于理解,根 據(jù)X(k)的周期特性,于是我們又可以認(rèn)為X(k)表示了從零頻率開始,頻率間隔為fs/N,到fs-fs/N截至的N個(gè)頻率點(diǎn)的相對幅度。

N點(diǎn)DFT的計(jì)算量

根 據(jù)(1)式給出的DFT計(jì)算公式,我們可以知道每計(jì)算一個(gè)頻率點(diǎn)X(k)均需要進(jìn)行N次復(fù)數(shù)乘法和N-1次復(fù)數(shù)加法,計(jì)算N各點(diǎn)的X(k)共需要N^2次 復(fù)數(shù)乘法和N*(N-1)次復(fù)數(shù)加法。當(dāng)x(n)為實(shí)數(shù)的情況下,計(jì)算N點(diǎn)的DFT需要2*N^2次實(shí)數(shù)乘法,2*N*(N-1)次實(shí)數(shù)加法。

旋轉(zhuǎn)因子WN的特性

  1.WN的對稱性

WN對稱性        2.WN的周期性

WN周期性 

  3.WN的可約性

WN可約性 根據(jù)以上這些性質(zhì),我們可以得到式(5)的一些列有用結(jié)果

WN性質(zhì)

基-2 FFT算法推導(dǎo)

假設(shè)采樣序列點(diǎn)數(shù)為N=2^L,L為整數(shù),如果不滿足這個(gè)條件可以人為地添加若干個(gè)0以使采樣序列點(diǎn)數(shù)滿足這一要求。首先我們將序列x(n)按照奇偶分為兩組如下:

采樣分組于是根據(jù)DFT計(jì)算公式(1)有:

FFT推導(dǎo)至此,我們將一個(gè)N點(diǎn)的DFT轉(zhuǎn)化為了式(7)的形式,此時(shí)k的取值為0到N-1,現(xiàn)在分為兩段來討論,當(dāng)k為0~N/2-1的時(shí)候,因?yàn)閤1(r),x2(r)為N/2點(diǎn)的序列,因此,此時(shí)式(7)可以寫為:

FFT偶數(shù)部分而當(dāng) k取值為N/2~N-1時(shí),k用k’+N/2取代,k’取值為0~N/2-1。對式(7)化簡可得:

FFT奇數(shù)部分

綜合以上推導(dǎo)我們可以得到如下結(jié)論:一個(gè)N點(diǎn)的DFT變換過程可以用兩個(gè)N/2點(diǎn)的DFT變換過程來表示,其具體公式如式(10)所示DFT快速算法的迭代公式:

DFT遞推公式上式中X'(k’)為偶數(shù)項(xiàng)分支的離散傅立葉變換,X''(k’’)為奇數(shù)項(xiàng)分支的離散傅立葉變換。 式(10)的計(jì)算過程可以用圖1的蝶形算法流圖直觀地表示出來。

蝶形算法信號(hào)流圖圖1 時(shí)間抽取法蝶形運(yùn)算流圖

在圖1中,輸入為兩個(gè)N/2點(diǎn)的DFT輸出為一個(gè)N點(diǎn)的DFT結(jié)果,輸入輸出點(diǎn)數(shù)一致。運(yùn)用這種表示方法,8點(diǎn)的DFT可以用圖2來表示:

8點(diǎn)DFT的一級(jí)分解

圖2 8點(diǎn)DFT的4點(diǎn)分解

根據(jù)公式(10),一個(gè)N點(diǎn)的DFT可以由兩個(gè)N/2點(diǎn)的DFT運(yùn)算構(gòu)成,再結(jié)合圖1的蝶形信號(hào)流圖可以得到圖2的8點(diǎn)DFT的第一次分解。該分解可以用以下幾個(gè)步驟來描述:

  1.將N點(diǎn)的輸入序列按奇偶分為2組分別為N/2點(diǎn)的序列

  2.分別對1中的每組序列進(jìn)行DFT變換得到兩組點(diǎn)數(shù)為N/2的DFT變換值X1和X2

  3.按照蝶形信號(hào)流圖將2的結(jié)果組合為一個(gè)N點(diǎn)的DFT變換結(jié)果

根據(jù)式(10)我們可以對圖2中的4點(diǎn)DFT進(jìn)一步分解,得到圖3的結(jié)果,分解步驟和前面一致。

8點(diǎn)DFT的二級(jí)分解

圖3 8點(diǎn)DFT的2點(diǎn)分解

最后對2點(diǎn)DFT進(jìn)一步分解得到最終的8點(diǎn)FFT信號(hào)計(jì)算流圖:

8點(diǎn)DFT的全分解

圖4 8點(diǎn)DFT的全分解

從 圖2到圖4的過程中關(guān)于旋轉(zhuǎn)系數(shù)的變化規(guī)律需要說明一下。看起來似乎向前推一級(jí),在奇數(shù)分組部分的旋轉(zhuǎn)系數(shù)因子增量似乎就要變大,其實(shí)不是這樣。事實(shí)上奇 數(shù)分組部分的旋轉(zhuǎn)因子指數(shù)每次增量固定為1,只是因?yàn)槊肯蚯巴七M(jìn)一次,該分組序列的數(shù)據(jù)個(gè)數(shù)變少了,為了統(tǒng)一使用以原數(shù)據(jù)N為基的旋轉(zhuǎn)因子就進(jìn)行了變換導(dǎo) 致的。每一次分組奇數(shù)部分的系數(shù)WN,這里的N均為本次分組前的序列點(diǎn)數(shù)。以上邊的8點(diǎn)DFT為例,第一次分組N=8,第二次分組N為4,為了統(tǒng)一根據(jù)式 (4)進(jìn)行了變換將N變?yōu)榱?,但指數(shù)相應(yīng)的需要乘以2。

N點(diǎn)基-2 FFT算法的計(jì)算量

從 圖4可以看到N點(diǎn)DFT的FFT變換可以轉(zhuǎn)為log2(N)級(jí)級(jí)聯(lián)的蝶形運(yùn)算,每一級(jí)均包含有N/2次蝶形計(jì)算。而每一個(gè)蝶形運(yùn)算包含了1次復(fù)數(shù)乘法,2 次復(fù)數(shù)加法。因此N點(diǎn)FFT計(jì)算的總計(jì)算量為:復(fù)數(shù)乘法——N/2×log2(N)    復(fù)數(shù)加法——N×log2(N)。假設(shè)被采樣的序列為實(shí)數(shù)序列,那么也只有第一級(jí)的計(jì)算為實(shí)數(shù)與復(fù)數(shù)的混合計(jì)算,經(jīng)過一次迭代后來的計(jì)算均變?yōu)閺?fù)數(shù)計(jì)算, 在這一點(diǎn)上和直接的DFT計(jì)算不一致。因此對于輸入序列是復(fù)數(shù)還是實(shí)數(shù)對FFT算法的效率影響較小。一次復(fù)數(shù)乘法包含了4次實(shí)數(shù)乘法,2次實(shí)數(shù)加法,一次 復(fù)數(shù)加法包含了2次復(fù)數(shù)加法。因此對于N點(diǎn)的FFT計(jì)算需要總共的實(shí)數(shù)乘法數(shù)量為:2×N×log2(N);總的復(fù)數(shù)加法次數(shù) 為:2xNxlog2(N)。

N點(diǎn)基-2 FFT算法的實(shí)現(xiàn)方法

從圖4我們可以總結(jié)出對于點(diǎn)數(shù)為N=2^L的DFT快速計(jì)算方法的流程:

   1.對于輸入數(shù)據(jù)序列進(jìn)行倒位序變換。

該 變換的目的是使輸出能夠得到X(0)~X(N-1)的順序序列,同樣以8點(diǎn)DFT為例,該變換將順序輸入序列x(0)~x(7)變?yōu)槿鐖D4的 x(0),x(4),x(2),x(6),x(1),x(5),x(3),x(7)序列。其實(shí)現(xiàn)方法是:假設(shè)順序輸入序列一次村在A(0)~A(N-1) 的數(shù)組元素中,首先我們將數(shù)組下標(biāo)進(jìn)行二進(jìn)制化(例:對于點(diǎn)數(shù)為8的序列只需要LOG2(8) = 3位二進(jìn)制序列表示,序號(hào)6就表示為110)。二進(jìn)制化以后就是將二進(jìn)制序列進(jìn)行倒位,倒位的過程就是將原序列從右到左書寫一次構(gòu)成新的序列,例如序號(hào)為 6的二進(jìn)制表示為110,倒位后變?yōu)榱?11,即使十進(jìn)制的3。第三步就是將倒位前和倒位后的序號(hào)對應(yīng)的數(shù)據(jù)互換。依然以序號(hào)6為例,其互換過程如下:

temp = A(6);
A(6) = A(3);
A(3) = A(6);
實(shí)際上考慮到執(zhí)行效率,如果對于每一次輸入的數(shù)據(jù)都需要這個(gè)處理過程是非常浪費(fèi)時(shí)間的。我們可以采用指向指針的指針來實(shí)現(xiàn)該過程,或者是采用指針數(shù)組來實(shí)現(xiàn)該過程。
 
2.蝶形運(yùn)算的循環(huán)結(jié)構(gòu)。
 從圖4中我們可以看到對于點(diǎn)數(shù)為N = 2^L的fft運(yùn)算,可以分解為L階蝶形圖級(jí)聯(lián),每一階蝶形圖內(nèi)又分為M個(gè)蝶形組,每個(gè)蝶形組內(nèi)包含K個(gè)蝶形。根據(jù)這一點(diǎn)我們就可以構(gòu)造三階循環(huán)來實(shí)現(xiàn)蝶 形運(yùn)算。編程過程需要注意旋轉(zhuǎn)因子與蝶形階數(shù)和蝶形分組內(nèi)的蝶形個(gè)數(shù)存在關(guān)聯(lián)。

 3.浮點(diǎn)到定點(diǎn)轉(zhuǎn)換需要注意的關(guān)鍵問題
上邊的分析都是基于浮點(diǎn)運(yùn)算來得到的結(jié)論,事實(shí)上大多數(shù)嵌入式系統(tǒng)對浮點(diǎn)運(yùn)算支持甚微,因此在嵌入式系統(tǒng)中進(jìn)行離散傅里葉變換一般都應(yīng)該采用定點(diǎn) 方式。對于簡單的DFT運(yùn)算從浮點(diǎn)到定點(diǎn)顯得非常容易。根據(jù)式(1),假設(shè)輸入x(n)是經(jīng)過AD采樣的數(shù)字序列,AD位數(shù)為12位,則輸入信號(hào)范圍為 0~4096。為了進(jìn)行定點(diǎn)運(yùn)算我們將旋轉(zhuǎn)因子實(shí)部虛部同時(shí)擴(kuò)大2^12倍,取整數(shù)部分代表旋轉(zhuǎn)因子。之后,我們可以按照(1)式計(jì)算,得到的結(jié)果與原結(jié) 果成比例關(guān)系,新的結(jié)果比原結(jié)果的2^12倍。但是,對于使用蝶形運(yùn)算的fft我們不能采用這種簡單的放大旋轉(zhuǎn)因子轉(zhuǎn)為整數(shù)計(jì)算的方式。因?yàn)閒ft是一個(gè) 非對稱迭代過程,假設(shè)我們對旋轉(zhuǎn)因子進(jìn)行了放大,根據(jù)蝶形流圖我們可以發(fā)現(xiàn)其最終的結(jié)果是,不同的輸入被放大了不同的倍數(shù),對于第一個(gè)輸入x(0)永遠(yuǎn)也 不會(huì)放大。舉一個(gè)更加形象的例子,還是以圖4為例。從圖中可以看出右側(cè)的X(0)可以直接用下式表示:

FFT原理與實(shí)現(xiàn) - kanku - kanku的博客


從上式我們可以看到不同輸入項(xiàng)所乘的旋轉(zhuǎn)因子個(gè)數(shù)(注 意這里是個(gè)數(shù),就算是wn^0,也被考慮進(jìn)去了,因?yàn)樵跊]有放大時(shí)wn^0等于1,放大后所有旋轉(zhuǎn)因子指數(shù)模均不為1,因此需要考慮)。這就導(dǎo)致輸入不平 衡,運(yùn)算結(jié)果不正確。經(jīng)查閱相關(guān)資料,比較妥善的做法是,首先對所有旋轉(zhuǎn)因子都放大2^Q倍,Q必須要大于等于L,以保證不同旋轉(zhuǎn)因子的差異化。旋轉(zhuǎn)因子 放大,為了保證其模為1,在每一次蝶形運(yùn)算的乘積運(yùn)算中我們需要將結(jié)果右移Q位來抵消這個(gè)放大,從而得到正確的結(jié)果。之所以采用放大倍數(shù)必須是2的整數(shù)次 冪的原因也在于此,我們之后可以通過簡單的右移位運(yùn)算將之前的放大抵消,而右移位又代替了除法運(yùn)算,大大節(jié)省了時(shí)間。
  
    4.計(jì)算過程中的溢出問題
最后需要注意的一個(gè)問題就是計(jì)算過程中的溢出問題。在實(shí)際應(yīng)用中,AD雖然有12位的位寬,但是采樣得到的信號(hào)可能較小,例如可能在0~8之間波 動(dòng),也就是說實(shí)際可能只有3位的情況。這種情況下為了在計(jì)算過程中不丟失信息,一般都需要先將輸入數(shù)據(jù)左移P位進(jìn)行放大處理,數(shù)據(jù)放大可能會(huì)導(dǎo)致溢出,從 而使計(jì)算錯(cuò)誤,而溢出的極限情況是這樣:假設(shè)我們數(shù)據(jù)位寬為D位(不包括符號(hào)位),AD采樣位數(shù)B位,數(shù)字放大倍數(shù)P位,旋轉(zhuǎn)因此放大倍數(shù)Q位,F(xiàn)FT級(jí) 聯(lián)運(yùn)算帶來的最大累加倍數(shù)L位。我們得到:
FFT原理與實(shí)現(xiàn) - kanku - kanku的博客
假設(shè)AD位寬12,數(shù)據(jù)位寬32,符號(hào)位1位,因此有效位寬31位,采樣點(diǎn)數(shù)N,那么我們可以得到log2(N)+P+Q<=19,假設(shè)點(diǎn)數(shù)128,又Q>=L可以得到放大倍數(shù)P<=5。
  
FFT代碼示例
根據(jù)以上的分析,我整理了一份128點(diǎn)的FFT代碼如下,該代碼在keil中仿真運(yùn)行,未發(fā)現(xiàn)問題。
#define N           128
#define POWER       6//該值代表了輸入數(shù)據(jù)首先被放大的倍數(shù),放大倍數(shù)為2^POWER
#define P_COEF      8//該值代表了旋轉(zhuǎn)因子被放大的倍數(shù),放大倍數(shù)為2^POWER
#if (N == 4)
#define L           2//L的定義滿足L = log2(N)
#elif (N == 8)
#define L           3//L的定義滿足L = log2(N)
#elif (N == 16)
#define L           4//L的定義滿足L = log2(N)
#elif (N == 32)
#define L           5//L的定義滿足L = log2(N)
#elif (N == 64)
#define L           6//L的定義滿足L = log2(N)
#elif (N == 128)
#define L           7//L的定義滿足L = log2(N)
#endif


//AD采樣位數(shù)為12位,本可以采用s16 x[N]定義數(shù)據(jù)空間,但是為了節(jié)省存儲(chǔ)空間,fft結(jié)果也將存儲(chǔ)在該變量空間。由于受
//fft影響變量需要重新定義,定義的方式及具體原因如下:
//fft過程會(huì)乘以較大旋轉(zhuǎn)因子,因此需要32位定義
//fft過程會(huì)產(chǎn)生負(fù)數(shù),因此需要有符號(hào)定義
//fft過程會(huì)出現(xiàn)復(fù)數(shù),因此需要定義二維數(shù)組,[][0]存放實(shí)部,[][1]存放虛部
s32 x[N][2] = {};

//定義*p[N]是為了在第一次指針初始化以后,該數(shù)組指針按照位倒序指向數(shù)據(jù)變量x
//p[i][0]代表了指向數(shù)據(jù)的實(shí)部,p[i][1]代表了指向數(shù)據(jù)的虛部
s32 *p[N];

//定義旋轉(zhuǎn)因子矩陣
//旋轉(zhuǎn)因子矩陣存儲(chǔ)了wn^0,wn^1,wn^2...wn^(N/2-1)這N/2個(gè)復(fù)數(shù)旋轉(zhuǎn)因子 
s16 w[N>>1][2] = {256,0,256,-13,255,-25,253,-38,251,-50,248,-62,245,-74,241,-86,237,-98,231,-109,226,
                  -121,220,-132,213,-142,206,-152,198,-162,190,-172,181,-181,172,-190,162,-198,152,
                  -206,142,-213,132,-220,121,-226,109,-231,98,-237,86,-241,74,-245,62,-248,50,-251,38,
                  -253,25,-255,13,-256,0,-256,-13,-256,-25,-255,-38,-253,-50,-251,-62,-248,-74,-245,-86,
                  -241,-98,-237,-109,-231,-121,-226,-132,-220,-142,-213,-152,-206,-162,-198,-172,-190,-181,
                  -181,-190,-172,-198,-162,-206,-152,-213,-142,-220,-132,-226,-121,-231,-109,-237,-98,-241,
                  -86,-245,-74,-248,-62,-251,-50,-253,-38,-255,-25,-256,-13}; void init_pointer(void) { unsigned char i = 0; unsigned char j = 0; unsigned char k = 0; for(i = 0; i < N; i++) { j = 0; for(k = 0; k < L; k++) { j |= (((i >> k)&0x01)<<(L-k-1)); } p[i] = &x[j][0]; } } /* *description:基2fft主函數(shù),該函數(shù)將借助指針數(shù)組p對全局變量數(shù)組x進(jìn)行fft計(jì)算 * 并將結(jié)果存儲(chǔ)在數(shù)組x中 *global var:rw->x; r->p,w。(r表示讀,w表示寫,rw表示讀寫) */ void fft2(void) { u8 i;//i用于表示蝶形圖級(jí)聯(lián)的階數(shù) u8 j;//表示蝶形分組起始點(diǎn)序列,蝶形分組跨度為2^i u8 k;//k表示蝶形組內(nèi)偶數(shù)分支序列點(diǎn)號(hào) u8 gp_distance = 1;//蝶形分組跨度 u8 temp;//temp用于記錄當(dāng)前組間距離的一半,同時(shí)也表示了同一碟形兩分支間的距離 u8 gp_hf = 0;//記錄當(dāng)前組的中間點(diǎn)序號(hào) u8 delta = N;//旋轉(zhuǎn)因子下標(biāo)增量,本來下標(biāo)初始值應(yīng)該為N/2,但是。。 s16 *pw = &(w[0][0]); int tp_result[2]; //用于臨時(shí)存放旋轉(zhuǎn)因子和奇數(shù)分組的乘積 //輸入信號(hào)序列放大 for(i = 0; i < N; i++) { x[i][0] <<= POWER; x[i][1] <<= POWER; } for(i = 0; i < L; i++) { temp = gp_distance; gp_distance <<= 1; for(j = 0; j < N; j+=gp_distance) { gp_hf = temp + j; pw = &(w[0][0]); for(k = j; k < gp_hf; k++)//完成一組內(nèi)的所有蝶形運(yùn)算 { //蝶形運(yùn)算中的一組復(fù)數(shù)乘法過程 tp_result[0] = pw[0] * (p[k+temp][0]) - pw[1] * (p[k+temp][1]); tp_result[1] = pw[0] * (p[k+temp][1]) + pw[1] * (p[k+temp][0]); tp_result[0] >>= P_COEF; tp_result[1] >>= P_COEF; //蝶形運(yùn)算中的2組復(fù)數(shù)加法過程 p[k+temp][0] = p[k][0] - tp_result[0]; p[k+temp][1] = p[k][1] - tp_result[1]; p[k][0] += tp_result[0]; p[k][1] += tp_result[1]; pw += delta; } } delta >>= 1; } }

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    亚洲一区精品二人人爽久久| 亚洲国产成人av毛片国产| 日韩欧美一区二区久久婷婷| 国产精品夜色一区二区三区不卡| 欧美日本精品视频在线观看| 国产人妻精品区一区二区三区| 激情三级在线观看视频| 福利一区二区视频在线| 大尺度激情福利视频在线观看| 在线中文字幕亚洲欧美一区| 日韩精品人妻少妇一区二区| 丝袜诱惑一区二区三区| 成年人黄片大全在线观看| 在线九月婷婷丁香伊人| 欧美综合色婷婷欧美激情| 出差被公高潮久久中文字幕| 色无极东京热男人的天堂| 91天堂免费在线观看| 东京干男人都知道的天堂| 国产精品成人一区二区三区夜夜夜| 欧美日韩中国性生活视频| 在线日韩中文字幕一区| 色老汉在线视频免费亚欧| 色婷婷中文字幕在线视频| 精品一区二区三区乱码中文| 免费黄片视频美女一区| 国产三级视频不卡在线观看| 日韩精品中文字幕亚洲| 亚洲丁香婷婷久久一区| 精品久久综合日本欧美| 在线九月婷婷丁香伊人| 夫妻性生活一级黄色录像| 亚洲国产天堂av成人在线播放| 熟女一区二区三区国产| 日本丰满大奶熟女一区二区| 日本人妻免费一区二区三区| 国产日本欧美特黄在线观看| 国产成人午夜av一区二区 | 欧美极品欧美精品欧美| 欧美性猛交内射老熟妇| 欧美av人人妻av人人爽蜜桃|