SDR# (SDRSharp)代码讲解 (六)

要理解FFT代码原理,首先要说一下FFT算法的前身DFTDFT是离散傅立叶变换,公式和连续傅立叶变换很接近,只不过是把连续傅立叶变换的积分换成了累加而已。理论上,用DFT的公式(参加幻灯片第四页),只要用软件代码对一个输入的数据序列进行公式里的这些乘法和累加后,就能计算出这个输入的傅立叶变换的结果。但是从公式也可以看出来,为了计算一个频点上的傅立叶变换的值,就要做N次乘法和长度为N-1的累加,然后要计算所有N个频点上的傅立叶变换的输出值,就要再重复前面这些运算N次。也就是N*N次乘法和N*(N-1)次累加。而且这些运算还是复数运算,也就是说前面说的那些乘法和加法是复数的乘法和加法,比实数的更复杂。具体对应的实数运算数量见幻灯片第五页,这里就不再推导了。


经过上面的分析可以知道,当输入序列的长度N很大时,运算量上升很快,这样如果要求实时运算的情形,原来的方法就不能用了。这时就要考虑利用公式中的W(旋转因子)的一些特殊性质来简化运算(见幻灯片第八页),省去很多重复运算。利用这些性质简化后的DFT就是FFT了。所以FFTDFT的结果是相同的,只是运算速度提升了。


具体的优化方法也有很多种,比较主要的两种是幻灯片里介绍的按时间抽取-2和按频率抽取-2。建议先看一遍时间抽取的方法,比较好理解,幻灯片里会告诉你用了这种算法可以把长度为NDFT等价替换为两个长度为N/2DFT,然后再经过碟形运算输出同样的结果,根据前面的分析,序列长度减少后DFT的运算量是大幅减少的,即使考虑到后面的碟形运算所增加的运算量,总体的运算量还是少了(见幻灯片第16页),所以这种分解运算的方法是有效的。


由于长度N2L次方,(通常是1024这样的值,幻灯片里第19页上的例子是8),它除以2以后还是可以继续再除以2,也就是可以继续分解。每分解一次,运算量又可以进一步减少。分解完以后,对更小规模的DFT(幻灯片里是长度为2DFT),先做一级小规模的碟形运算(这个碟形运算规模小,但是要做两次),恢复出前面说的两个N/2序列的DFT,再做一次前面说的碟形运算。见幻灯片19页。


那么对于之前说的N=8的序列,现在已经简化为4个长度2DFT2级碟形运算了,根据幻灯片20可知,长度2DFT本身也可以直接用碟形运算实现。也就是说,把N不停除以2,完全分解后,所有的运算都可以用碟形运算实现,不必再做DFT也可以得到原来DFT产生的一模一样的结果。


现在的问题是,这样对原序列不停地做多次奇偶分解,输入的元素的顺序比较难找,幻灯片26页给出了方法。原理就不多讲了,但是可以大概看一下怎么用程序实现,首先,按照正常的顺序01234567,可以得到它们对应的二进制值000001010011100101110111等,这时候只需要把它们各自的位序倒过来,即把每一个二进制数字的左边放到右边,右边放到左边,得到:000100010110001101011111。然后再把它们转换成十进制,就得到了04261537,正好就是要找的输入序列的顺序,参考幻灯片28页。


那么知道了这个这个04261537的序列顺序后,怎样从原来的按照01234567buffer里获得新的序列顺序呢?可以参照幻灯片29页的方式,对buffer里的各元素逐个交换,这个操作在代码里也有体现。

你可能感兴趣的:(SDR#,(SDRSharp)代码讲解)