首页 > 代码库 > NOW ! It's time to implement "FFT" !
NOW ! It's time to implement "FFT" !
Fast Fourier Transform
半年前的样子写了DFT,就想自己实现一个FFT,当时写不出,蝶形算法就是不明白,现在时机成熟了.
Now, it‘s time to implement "FFT".
How the FFT works
The FFT is a complicated algorithm, and its details are usually left to those that specialize in such things. This section describes the general operation of the FFT. Don‘t worry if the details elude you; few scientists and engineers that use the FFT could write the program from scratch.
In complex notation, the time and frequency domains each contain one signal made up of N complex points. Each of these complex points is composed of two numbers, the real part and the imaginary part.
一种重要的操作——逆序输入
这里输入序列是0~15的顺序输入
In this example, a 16 point signal is decomposed through four separate stages. The first stage breaks the 16 point signal into two signals each consisting of 8 points. The second stage decomposes the data into four signals
上面 0 ~ 15 的顺序输入被化做 0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15的输入,有什么依据可循吗?
看下面:
Bit reversal
Bit reversal的实现是很简单的
这里我给出C 的demo
/******************************************************* Code writer : EOF Code file : reverse_bits.c e-mail : jasonleaster@gmail.com code purpose: This code is a demo for how to bit-reversal input bits in FFT. If there is something wrong with my code, please touche me by e-mail. Thank you. *********************************************************/ #include<stdio.h> #define ARRAY_SIZE 16 int main(void) { int array[ARRAY_SIZE] = {0,}; int tmp = 0; int bits = 0; /* ** Initialization of array */ for(tmp = 0;tmp < ARRAY_SIZE;tmp++) { array[tmp] = tmp; } for(tmp = ARRAY_SIZE-1;tmp > 0; tmp >>= 1) { bits++; } for(tmp = 0;tmp < ARRAY_SIZE; tmp++) { printf("%4d %4d\n",array[tmp],reverse_bits(array[tmp],bits)); } return 0 ; } /* ** Reverse the bits of input number */ int reverse_bits(int num,int bits) { int ret = 0; int copy_num = 0; for(ret = 0,copy_num = num; bits > 0; bits--) { ret += (copy_num % 2) * (1<<(bits-1)); copy_num >>= 1; } return ret; }
在Octave下实现的FFT(没有利用特殊的API,所以应该可以在Matlab中运行,我没有Matlab环境,如果有心人可以去测试一下)
%% *************************************************************************************** % code writer : EOF % code date : 2014.09.03 % e-mail : jasonleaster@gmail.com % code file : fft_EOF.m % Version : 1.0 % % code purpose : % % It's time to finish my demo for DFT. I would like to share my code with % someone who is interesting in DSP. If there is something wrong with my code, % please touche me by e-mail. Thank you! % %% *************************************************************************************** clear all; %************************************************* % The number of all the signal that our sensor got %************************************************* TotalSample = 8; % We assume that the preiod of the signal we generated is 'circle'; circle = TotalSample/2; %************************************************************** % This varible is used for recording the signal which % were processed by inverse-DFT in time domain %************************************************************** SignalInT = zeros(TotalSample,1); SignalInT_reversed = zeros(TotalSample,1); %This varible is used for recording the signal which were processed by inverse-DFT in time domain OutPutSignal = zeros(TotalSample,1); OriginalSignal = zeros(TotalSample,1); %This varible is used for recording the original signal that we got. %% initialize a square wave for SampleNumber = -(TotalSample/2):(TotalSample/2)-1 if (mod(abs(SampleNumber),circle) < (circle/2))&&(SampleNumber>0) OriginalSignal((TotalSample/2)+1+SampleNumber) = 5; elseif (mod(abs(SampleNumber),circle) >= (circle/2))&&(SampleNumber>0) OriginalSignal((TotalSample/2)+1+SampleNumber) = 0; elseif (mod(abs(SampleNumber),circle) < (circle/2))&&(SampleNumber<0) OriginalSignal((TotalSample/2)+1+SampleNumber) = 0; elseif (mod(abs(SampleNumber),circle) >= (circle/2))&&(SampleNumber<0) OriginalSignal((TotalSample/2)+1+SampleNumber) = 5; end end % We show the original signal in time domain. figure(1); plot( -(TotalSample/2):(TotalSample/2)-1,OriginalSignal,'.-'); title('The original signal'); tmp = TotalSample - 1; %%*********************************************************************** % @Bits : describe how many bits should be used to make up the TotalSample %%*********************************************************************** Bits = 0; while tmp > 0 %% floor (X) Return the largest integer not greater than X. tmp = floor(tmp/2); Bits = Bits + 1; end SignalInT = OriginalSignal; %****************************************** % Reverse the bits of input number %****************************************** for SampleNumber = 1 : TotalSample ret = bit_reverse(SampleNumber - 1,Bits); SignalInT_reversed(SampleNumber) = SignalInT(ret+1); end InPutSignal = SignalInT_reversed; for layyer = 1 : Bits for SampleNumber = 1 : 2^(layyer) : TotalSample for pre_half = SampleNumber:(SampleNumber+2^(layyer-1) -1) r = get_r_in_Wn(pre_half-1,layyer,TotalSample,Bits); W_rN = exp(-2*pi*j*(r)/TotalSample) ; OutPutSignal(pre_half) = ... InPutSignal(pre_half) + ... W_rN * InPutSignal(pre_half + 2^(layyer-1)); OutPutSignal(pre_half + 2^(layyer-1)) = ... InPutSignal(pre_half) - ... W_rN * InPutSignal(pre_half + 2^(layyer-1)); end end InPutSignal = OutPutSignal; end
程序的运行结果输出数据OutPutSignal,和Octave自带的FFT函数对比,发现计算结果是正确的 \O/
这个blog仅仅记录FFT的实现结果,之后将补充理论基础以及实现细节分析.
—— EOF
于XTU. 2014.09.04
NOW ! It's time to implement "FFT" !