快速傅里葉算法實現 學習筆記

      一、基礎知識

    考研階段學習過傅里葉級數,而最近的項目正好是用C語言編寫傅里葉變換,於是很認真的複習了傅里葉級數。可是無奈,看來看去反而暈暈乎乎的。後經師兄師姐的指教,才得知對於工程中的信號處理,研究週期性的傅里葉變換都沒有現實意義,而傅里葉級數更沒有什麼關係。
       工程中待處理的信號,通常具有非週期性,故我們需要對離散傅里葉變換進行研究。離散公式:


【x(n)是採樣的時域信號,X(k)是對於不同頻率k的頻域信號。】

       而快速傅里葉變換又是對離散傅里葉變換的改進,通過蝶形運算(網上的圖片如下),計算速度可大大提升,使計算量呈指數型下降。

一、最左的x(n)是採樣的時域信號,最右的X(k)是算出的頻域信號。可以看到左邊的x(n)中,n 的序列並非正常的遞增,這是爲了使得輸出的X(k)中的k頻率呈遞增序列。

二、[n]的序列是通過將十進制n轉化成的二進制數字後,倒序排列生成的,如4的二進制碼爲100,倒序爲001,故排在第二位。

三、在上圖中,共8個信號,可分成3級。第一級,每個分組兩個節點,一個蝶形單元。第二級,每個分組四個節點,兩個蝶形單元。第三級,每個分組八個節點,四個蝶形單元。

二、算法語言實現

下面是一段HTML快速傅里葉核心代碼,和C語言差不多:

<span style="font-size:12px;">

void fft(complex f[], int N)
{
	complex t, wn;//中間變量
	int i, j, k, la, lb, lc, l, r, m, n;//中間變量
	//M:分解運算級數
	int M;
	/*----計算分解的級數M=nextpow2(N)----*/
	for (i = N, M = 1; (i = i / 2) != 1; M++);
	/*----輸入信號二進制碼位倒序*/
	for (i = 1, j = N / 2; i <= N - 2; i++)
	{
		if (i<j)
		{
			t = f[j];
			f[j] = f[i];
			f[i] = t;
		}
		k = N / 2;
		while (k <= j)
		{
			j = j - k;
			k = k / 2;
		}
		j = j + k;
	}
	/*----FFT算法----*/
	for (m = 1; m <= M; m++)
	{
		la = pow(2.0, m); //la=2^m代表第m級每個分組所含節點數       
		lb = la / 2;    //lb代表第m級每個分組所含碟形單元數  
		//同時它也表示每個碟形單元上下節點之間的距離  
		/*----碟形運算----*/
		for (l = 1; l <= lb; l++)
		{
			r = (l - 1)*pow(double(2), M - m);
			for (n = l - 1; n<N - 1; n = n + la) //遍歷每個分組,分組總數爲N/la  
			{
				lc = n + lb;  //n,lc分別代表一個碟形單元的上、下節點編號       
				Wn_i(N, r, &wn, 1);//wn=Wnr  
				c_mul(f[lc], wn, &t);//t = f[lc] * wn複數運算  
				c_sub(f[n], t, &(f[lc]));//f[lc] = f[n] - f[lc] * Wnr  
				c_plus(f[n], t, &(f[n]));//f[n] = f[n] + f[lc] * Wnr  
			}
		}
	}
}
</span>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章