美文网首页
4.FFT(DFT)

4.FFT(DFT)

作者: wit_yuan | 来源:发表于2019-04-19 15:24 被阅读0次

1.简介

这一篇说到哪里就写到哪里,因为这个问题是信号处理的基本问题,也没什么太多好讲的,而且讲这个的文章也太多了。如果留意的话,放狗搜一下,还能发现有一本比较老的书:《快速傅里叶变换及其C程序》。

先摆出DFT与IDFT的定义:
X(k)=\sum^{N-1}_{n=0}{x(n)W^{nk}_N},k=0,1,...,N-1 , W_N=e^{-j \frac{2\pi}N}
x(n)=\frac{1}{N}{\sum^{N-1}_{k=0}{X(k)W^{-nk}_N}},n=0,1,...,N-1

对于X(k),先假设x(n)也是一个复数,那么每一个X(k)就有n个点的{x(n)W^{nk}_N}(是一个复数)求和,这一个点就需要N-1次加法运算和N次复数乘法运算。对于X(k)(有n个点),就总共需要N^2次复数乘法运算与N(N-1)次复数加法运算了。

计算一下,对1024个点做DFT处理,就有1024^2的复数乘法与1024*(1024-1)的加法运算。这种计算量对于DSP做实时处理而言将是灾难性的,所以就需要做优化,降低计算量。

这个时候,就由W_N的设计的合理性来起作用了,因为x(n)是无规律的,而W_N的可设计性很强。

做一个简单的示例,使用4点DFT来说后面的优化:
X(0)=x(0)+x(1)+x(2)+x(3);
X(1)=x(0)+x(1)W^1_4+x(2)W^2_4+x(3)W^3_4;
X(2)=x(0)+x(1)W^2_4+x(2)W^4_4+x(3)W^6_4;
X(3)=x(0)+x(1)W^3_4+x(2)W^6_4+x(3)W^9_4;

从这个示例来看,比较复杂,有W^1_4,W^2_4,W^3_4,W^4_4,W^6_4,W^9_4,可是再代入W_N=e^{-j \frac{2\pi}N},N=4,再简单手算一下,可以得出一个等价关系:
W^4_4=1,W^2_4=W^6_4=-1,W^1_4=W^9_4=-j,W^3_4=j,所以简化以上计算,就变为:

X(0)=x(0)+x(1)+x(2)+x(3)=(x0)+x(2))+(x(1)+x(3));
X(1)=x(0)+x(1)(-j)+x(2)(-1)+x(3)(j)=(x(0)-x(2))+(x(3)-x(1))j;
X(2)=x(0)+x(1)(-1)+x(2)+x(3)(-1)=(x(0)+x(2))-(x(1)+x(3));
X(3)=x(0)+x(1)(j)+x(2)(-1)+x(3)(-j)=(x(0)-x(2))+(x(1)-x(3))j;

从这里就能看出本来需要4^2次复数乘法与4*(4-1))次复数加法的运算最终变为1次复数乘法了,这明显提高了运算速率。注意到一点,缩减运算量主要是运用W_N的对称性。

继续这个例子,假设有4个点,值为:(2,3,3,2),则计算结果为:
X(0)=10;
X(1)=-1-j;
X(2)=0;
X(3)=-1+j;

使用matlab编写以上程序,程序如下:

clc;
clear all;
format long;

N=4;
n=0:N-1;
xn=[2 3 3 2];
Xk=fft(xn)

2.算法提速

根据上面的基础,再来看一下,运用这种对称关系,能将上面的算法速率提高到多少。

还是摆公式:
X(k)=\sum^{N-1}_{n=0}{x(n)W^{nk}_N}=\sum^{N/2-1}_{n=0}{x(2n)W^{2nk}_N}+\sum^{N/2-1}_{n=0}{x(2n+1)W^{(2n+1)k}_N}, W^{2nk}_N=W^{nk}_{N/2}
=\sum^{N/2-1}_{n=0}{x(2n)W^{nk}_{N/2}}+W^{k}_N\sum^{N/2-1}_{n=0}{x(2n+1)W^{nk}_{N/2}}

这里,可以将一个复杂问题进行分解,令:
Y(k)=\sum^{N/2-1}_{n=0}{x(2n)W^{nk}_{N/2}}
Z(k)=\sum^{N/2-1}_{n=0}{x(2n+1)W^{nk}_{N/2}}

从上面的式子中,可以发现一个问题,K从一个范围0,1,2,3,...N-1变为范围为0,1,2,...N/2-1了,因此,最终计算的X(k)只能表示一般的数,为了补足另外一半的数据,需要自己重新扩展另外一半,也就是下面的式子。
X(k+N/2)=Y(k+N/2)+W^{k+N/2}_NZ(k+N/2)=Y(k+N/2)-W^{k}_NZ(k+N/2)
另外:
Y(k+N/2)=Y(k)
Z(k+N/2)=Z(k)
故:
X(k)=Y(k)+W^{k}_NZ(k),k=0,1,2,...N/2-1
X(k+N/2)=Y(k)-W^{k}_NZ(k),k=0,1,2,...N/2

所以,从这里可以看出X(k)X(k+N/2)组合起来做一次蝶形运算,而该运算只需要一次复数运算即可。那么按照这样的方式推导,一共有\log_2(N)次运算,每次运算有N/2次复数运算,所以共有复数运算N/2\log_2(N)次复数运算。顺便计算一下复数加法,即:2*N/2*\log_2(N)=N\log_2(N)次。

到这一步,再去跟前面的计算量对比,可以发现,效率提高了很多了。

3.应用

这节主要说一下在TMS320C6748上的使用。

可以使用两个API来执行fft与ifft操作,分别如:

void DSPF_sp_fftSPxSP(int N, float *ptr_x, float *ptr_w, float *ptr_y, 
    unsigned char *brev, int n_min, int offset, int n_max);
void DSPF_sp_ifftSPxSP (int N, float *ptr_x, float *ptr_w, float *ptr_y,
    unsigned char *brev, int n_min, int offset, int n_max);

如果要知道每一个代入参数来由,可以参考链接 ,另外提一句,在文档里面说了一个产生旋转因子的话:

void tw_gen (float *w, int n)//This is for FFT, IFF will be slightly different 

其实fft与ifft都可以用此函数并只需产生一次,经过验证并没有问题。而旋转因子是怎么产生的,可以参考链接

4.参考资料

关于本小节的内容,可以参考书籍:《数字信号处理理论、算法与实现 第3版 [胡广书 编著]》

相关文章

网友评论

      本文标题:4.FFT(DFT)

      本文链接:https://www.haomeiwen.com/subject/cwwqgqtx.html