数学原理#
Complex to Complex (C2C) DIT-FFT#
对于N点序列x[n],它的离散傅里叶变换 Discrete Fourier Transform (DFT) 为
X[k]=n=0∑N−1x[n]e−j2πNkn=n=0∑N−1x[n]WNkn, k=0, 1, …, N−1
将x[n]按奇偶索引拆分为两个长度为M=N/2的子序列:
xe[n]=x[2n], xo[n]=x[2n+1], n=0, 1, …, M−1
则它的DFT可以表示为
X[k]=n=0∑N/2−1x[2n]e−j2πkN2n+n=0∑N/2−1x[2n+1]e−j2πkN2n+1=n=0∑Mxe[n]e−j2πMkn+e−j2πNkn=0∑Mxo[n]e−j2πMkn=n=0∑Mxe[n]WMkn+WNkn=0∑Mxo[n]WMkn=E[k]+WNkO[k], k=0, 1, …, M−1
由于周期性E[k+2n]=E[k], O[k+2n]=O[k]与对称性WNk+2/N=−WNk,有
X[k+M]=E[k]−WNkO[k], k=0, 1, …, M−1
Real to Complex (R2C) DIT-FFT#
由于音频信号都是实信号(虚部均为0),将其当成复信号计算 FFT 时会产生很多不必要的冗余计算。
可以将N点输入实序列x[n]按奇偶索引拆分为两个长度为M=N/2的子序列:
xe[n]=x[2n], xo[n]=x[2n+1], n=0, 1, …, M−1
然后用偶数索引项作为实部,奇数索引项作为虚部,构造一个复序列:
z[n]=xe[n]+jxo[n], n=0, 1, …, M−1
对这个复序列做M点复DFT:
Z[k]=n=0∑M−1z[n]WMkn=E[k]+jO[k], k=0, 1, …, M−1①
由于xe和xo都是实序列,故
E∗[k]=E[M−k], O∗[k]=O[M−k], k=1, 2, …, M−1
其中特殊点E[0],O[0]需要单独计算。
又
Z[M−k]=E[M−k]+jO[M−k]=E∗[k]+jO∗[k]
Z∗[M−k]=E[k]−jO[k], k=1, 2, …, M−1②
① + ②得
E[k]=21(Z[k]+Z∗[M−k]), k=1, 2, …, M−1
① - ②得
O[k]=−2j(Z[k]−Z∗[M−k]), k=1, 2, …, M−1
故
X[k]=E[k]+WNkO[k]=21[(Z[k]+Z∗[M−k])−jWNk(Z[k]−Z∗[M−k])], k=1, 2, …, M−1
又由于实数序列DFT的共轭对称性,有
X[N−k]=X∗[k], k=1, 2, …, M−1
两个特殊点
X[0]X[M]=E[0]+O[0]=Re{Z[0]}+Im{Z[0]}=E[M]+WNMO[M]=E[0]−O[0]=Re{Z[0]}−Im{Z[0]}
故有
X[0]=Re{Z[0]}+Im{Z[0]},k=0
X[k]=21[(Z[k]+Z∗[M−k])−jWNk(Z[k]−Z∗[M−k])],k=1, 2, …, 2N−1
X[k]=Re{Z[0]}−Im{Z[0]},k=2N
X[k]=X∗[N−k],k=2N+1, 2N+2, …, N−1
由此得到,要对N点实数序列做DFT时,可将这个实数序列当作一个2N点的复序列,对这个复序列进行2N点DFT,再由上式还原得到原本要求的N点DFT。
Complex to Real (C2R) IFFT#
对于音频信号这样一个实信号,它的频域信号是具有共轭对称性的:
X[N−k]=X[k]∗, k=1, 2, ,…, N−1
故频谱信息只有一半是不重复的,也可以进行计算优化。前面 C2C DIT-FFT 的内容提到,将按奇偶索引拆分为两个长度为M=N/2的子序列后带入DFT定义可得
X[k]X[k+M]=E[k]+WNkO[k], k=0, 1, …, M−1=E[k]−WNkO[k], k=0, 1, …, M−1
从这两个式子中反解得到E[k]和O[k]:
E[k]O[k]=2X[k]+X[k+M], k=0, 1, …, M−1=2WNkX[k]−X[k+M], k=0, 1, …, M−1
然后根据FFT与IFFT的线性性质,我们就只需要构造复序列:
T[k]=E[k]+jO[k]
再对其进行N/2点IFFT:
x[n]=IFFT{T[k]}=xe[n]+jxo[n], k=0, 1, …, M−1
就得到了实部为时域偶数索引项,虚部为时域奇数索引项的复数信号,由于本身该算法在存储复数时实部和虚部就是交替存储的,得到的复数信号同时也是时域的实数信号,无需进行后处理。
Radix-4 DIT-FFT#
本身我们需要做的是128点实数 FFT和复数IFFT,通过R2C和C2R的处理转化成了64点复数 FFT/IFFT,而由于64恰好是4的整数次幂,因此可将常用的 Radix-2 64点 FFT 改为Radix-4 64点 FFT,可将蝶形运算层数从6层缩减至3层,大幅减少循环次数与函数调用次数。
设序列x[n]的长度N=4m,通过抽取将x[n]分为四个长度为4N的子序列如下:
x1[n]x2[n]x3[n]x4[n]=x[4n]=x[4n+1]=x[4n+2]=x[4n+3]
则x[n]的DFT可表示为
X[k]=n=0∑N−1x[n]WNnk=n=0∑N/4−1x[4n]WN4nk+n=0∑N/4−1x[4n+1]WN(4n+1)k+n=0∑N/4−1x[4n+2]WN(4n+2)k+n=0∑N/4−1x[4n+3]WN(4n+3)k=n=0∑N/4−1x[4n]WN/4nk+n=0∑N/4−1x[4n+1]WN/4nkWNk+n=0∑N/4−1x[4n+2]WN/4nkWN2k+n=0∑N/4−1x[4n+3]WN/4nkWN3k=n=0∑N/4−1x1[n]WN/4nk+n=0∑N/4−1x2[n]WN/4nkWNk+n=0∑N/4−1x3[n]WN/4nkWN2k+n=0∑N/4−1x4[n]WN/4nkWN3k=X1[k]+WNkX2[k]+WN2kX3[k]+WN3kX4[k]
其中,X1(k), X2(k), X3(k), X4(k) 分别为x1[n], x2[n], x3[n], x4[n] 的4N点DFT,k=1, 2, …, 4N−1
对于k=4N−1之后的X[k]计算过程如下:
X[k+N/4]X[k+2N/4]X[k+3N/4]=X1[k]+WNk+N/4X2[k]+WN2(k+N/4)X3[k]+WN3(k+N/4)X4[k]=X1[k]−jWNkX2[k]−WN2kX3[k]+jWN3kX4[k]=X1[k]+WNk+2N/4X2[k]+WN2(k+2N/4)X3[k]+WN3(k+2N/4)X4[k]=X1[k]−WNkX2[k]+WN2kX3[k]−WN3kX4[k]=X1[k]+WNk+3N/4X2[k]+WN2(k+3N/4)X3[k]+WN3(k+3N/4)X4[k]=X1[k]+jWNkX2[k]−WN2kX3[k]−jWN3kX4[k]
用图表示上述过程:
我们可以继续用上述的方法将每个子序列继续划分,直到最后序列长度为4。4点的DFT计算如下:
X[0]X[1]X[2]X[3]=11111−j−1j1−11−11−j−1j⋅x[0]x[1]x[2]x[3]