NOW ! It's time to implement "FFT" !

本文详细阐述了快速傅立叶变换(FFT)的工作原理,并通过C语言实现了一个简单的FFT程序。从逆序输入操作开始,文章深入介绍了如何使用位反转技巧优化输入序列,最终展示了一个完整的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

of 4 points. This pattern continues until there are N signals composed of a single point. An interlaced decomposition is used each time a signal is broken in two, that is, the signal is separated into its even and odd numbered samples.



上面 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 file       : bit_reverse.m
%     Code date       : 2014.09.04
%     e-mail          : jasonleaster@gmail.com
%
%     Function        : ret = get_r_in_Wn(k,m,N,bits)
%
%     Input Parameter : @k, the location of input signal
%                       @m, the current layyer
%                       @N, the total number of inputed signal
%                       @bits, how many bits should be used to represent 'N'
%
%     Output Parameter: @ret , the value of 'r'
%             
%****************************************************************************

function ret = get_r_in_Wn(k,m,N,bits)

         tmp = bitshift(k,bits - m);
         
         ret = bitand(tmp,(2^m) - 1);    
end



%****************************************************************************
%     Code writer     : EOF
%     Code file       : bit_reverse.m
%     Code date       : 2014.09.04
%     e-mail          : jasonleaster@gmail.com
%
%     Function        : ret = bit_reverse(Number,Bits)
%
%     Input Parameter : @Number, that is which number you want to reverse
%                                in bits.
%                       @Bits,   You should tell this function that how
%                                many bits you used to represent 'Number'
%
%     Output Parameter : @ret, that is a bit-reverse number of input 'Number'
%
%     Usage:
%            bit_reverse(1,3) == 4        001 --> 100 
%
%****************************************************************************
function ret = bit_reverse(Number,Bits)

    copy_num = Number;
    tmp_bits = Bits;
    tmp	 = 0;
	
    while	tmp_bits > 0
      
        tmp = tmp + (mod(copy_num,2)) * (2^(tmp_bits-1));
        
        copy_num = floor(copy_num/2);
        
        tmp_bits = tmp_bits - 1;
    end

    ret = tmp;
    
end



%% ***************************************************************************************
% 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






继续翻译: Spectral debug enhancements The following functional and debug enhancements are made to Spectral Analysis feature to enhance the usability and troubleshooting capability.  Configurable number FFT reports logging using spectraltool—Number of FFT reports to logged is made configurable (from fixed 1000 samples) between 1 to Max, where Max is decided by user, based on the available free memory.. Usage: #spectraltool -i wifiX [-a] get_samples 1024 Optional arguments after number of samples:-l <separation_character> Where separation_character is a single character to be used to separate values in output (e.g. ',' for comma). By default, space is used.-x <0/1> To disable (0) or enable (1) generation III linear bin format scaling (default: disabled). This is not applicable for other generations. This should be used only for linear format. Example, to enable scaling Usage: #spectraltool -i wifi0 [-a] get_samples 1024 -x 1 NOTE Because spectraltool is a raw tool, it will currently not reject an enable if dBm format is used on generation III (to enable debugging of scenarios such as incorrect programmatic application of scaling in incorrect formats). But the results with dBm are undefined and not applicable. Note that this command explicitly starts and stops Spectral scan.  Enhance spectraltool to support low configuration system—Spectraltool used to fail on low configuration system, owing to the limitation on buffers for FFT reports. This limitation is now resolved, which causes the spectraltool to function in low configuration platforms.  Enhance the logging formats for spectraltool—Spectraltool dumps the FFT reports in plain text format. Now option is added to dump into CSV format Usage: #spectraltool -i wifiX get_samples 1024 -l ','  Implement timeout feature for athssd and spectraltool—Applications such as athssd and spectraltool are in closed loop while receiving the FFT reports from HW. If HW fails to generate FFT reports, then these applications are blocked and do not respond. To recover from this deadlock, timeout feature is implemented in athssd and spectraltool. If the FFT reports fail for any reason to arrive at application layer, these will timeout and give control to the user.  Support to enable/disable the spectral direct DMA buffer debug at runtime (Disabled by default). Usage: #spectraltool -i wifiX dma_buff_debug <1/0>  Support to enable/disable the spectral direct DMA ring debug at runtime (Disabled by default). Usage: #spectraltool -i wifiX dma_ring_debug <1/0>  Support to enable/disable the spectral direct DMA buffer debug from the buffers creation time (Disabled by default). Usage: #uci set wireless.qcawifi=qca-wifi #uci set wireless.qcawifi.poison_spectral_bufs=<1/0> # uci commit wireless  Spectraltool -i wifiX dma_ring_debug <1/0> Enables/Disables Spectral DMA ring debug at run time (Disabled by default)  Spectraltool -i wifiX dma_buff_debug <1/0> Enables/Disables Spectral DMA buffer debug at run time (Disabled by default) NOTE Runtime configuration Spectraltool -i wifiX dma_buff_debug poisons only those buffers which are replenished after the command is issued whereas the INI poison_ spectral_bufs poisons all the buffers from their creation time.
最新发布
09-17
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值