① 请用MATLAB、C语言或者其他语言编程实现8点序列的基2-DIT-FFT算法,并对结果进行分析验证。
typedef struct
{
float real;
float img;
}COMPLEX;
void reverse(COMPLEX *X,COMPLEX *x,int N) /*输入数组名称和元素个数,实现倒序 */
{
int LH = N/2;
int j = LH;
int N1 = N-2;
int i;
for(i = 1; i <= N1; i++)
{
int k = LH;
X[i] = (i<j ? x[j] : x[i]);
/*
if(i < j)
{
comp T = a[j];
a[j] = a[i];
a[i] = T;
*/
}
while(j >= k)
{
j = j-k;
k = k/2;
}
j = j+k;
}
}
/*
函数功能:对指定长度的采样数据进行快速傅立叶变换,并返回变换值, X = FFT(x)
入口参数:目标采样数据,保存变换值的指针,采样数据长度
出口参数:指向变换值的指针
注意事项:保存结果的空间是在函数外部申请,本函数不处理此内容
/*/
COMPLEX *FFT(COMPLEX *X,COMPLEX *x, unsigned N)
{
unsigned temp=N,L=0,M=0,LE=1,LE1=0,J=0,I=0,IP=0;
COMPLEX U={0,0},W={0,0},T={0,0};
while((temp>>=1)>0) /*获得阶码M*/
{
M++;
}
reverse(X,x,N);
for(L=0;L<M;L++)
{
LE=1<<L; /*LE=2^L,分组间隔*/
LE1 = LE>>1; /*LE1=LE/2,对偶跨距,实际也是一个分组中对偶点的对数*/
U.real = 1.0;
U.img = 1.0;
W.real = cos(PI / LE1);
W.img = sin(PI / LE1);
J = 0;
while(J<LE1)
{
I = J;
while(I < N)
{
IP = I + LE1;
ComMul(X + IP,&U,&T);
ComSub(X + I,&T,X + IP);
ComAdd(X + I,&T,X + I);
I += LE;
}
ComMul(&U,&W,&U);
J++;
}
}
return X;
}
FFT中有几个复数运算,自己实现,不想发给你,年轻人还是要自己动手做点东西。N为任意数,正常应该为2的幂次方。
② 谁知道DFT和FFT的发展历史啊
DFT/FFT的发展历史
离散傅里叶变换(Discrete Fourier Transform,DFT)是数字信号处理最重要的基石之一,也是对信号进行分析和处理时最常用的工具之一。在200多年前法国数学家、物理学家傅里叶提出后来以他名字命名的傅里叶级数之后,用DFT这个工具来分析信号就已经为人们所知。历史上最伟大的数学家之一。
欧拉是第一个使用“函数”一词来描述包含各种参数的表达式的人,例如:y = f(x)。他是把微积分应用于物理学的先驱者之一。 给出了一个用实变量函数表示傅立叶级数系数的方程; 用三角级数来描述离散声音在弹性媒介中传播,发现某些函数可以通过余弦函数之和来表达。 但在很长时间内,这种分析方法并没有引起更多的重视,最主要的原因在于这种方法运算量比较大。直到1965年,Cooley和Tukey在《计算机科学 》发表着名的《机器计算傅立叶级数的一种算法》论文,FFT才开始大规模应用。
那个年代,有个肯尼迪总统科学咨询委员会。其中有项研究主题是,对苏联核测试进行检测,Tukey就是其中一员。美国/苏联核测试提案的批准,主要取决于不实地访问核测试设施而做出检测的方法的发展。其中一个想法是,分析离海岸的地震计情况,这种计算需要快速算法来计算DFT。其它应用是国家安全,如用声学探测远距离的核潜艇。所以在军事上,迫切需要一种快速的傅立叶变换算法,这也促进了FFT的正式提出。
FFT的这种方法充分利用了DFT运算中的对称性和周期性,从而将DFT运算量从N2减少到N*log2N。当N比较小时,FFT优势并不明显。但当N大于32开始,点数越大,FFT对运算量的改善越明显。比如当N为1024时,FFT的运算效率比DFT提高了100倍。在库利和图基提出的FFT算法中,其基本原理是先将一个N点时域序列的DFT分解为N个1点序列的DFT,然后将这样计算出来的N个1点序列DFT的结果进行组合,得到最初的N点时域序列的DFT值。实际上,这种基本的思想很早就由德国伟大的数学家高斯提出过,在某种情况下,天文学计算(也是现在FFT应用的领域之一)与等距观察的有限集中的行星轨道的内插值有关。由于当时计算都是靠手工,所以产生一种快速算法的迫切需要。 而且,更少的计算量同时也代表着错误的机会更少,正确性更高。高斯发现,一个富氏级数有宽度N=N1*N2,可以分成几个部分。计算N2子样本DFT的N1长度和N1子样本DFT的N2长度。只是由于当时尚欠东风——计算机还没发明。在20世纪60年代,伴随着计算机的发展和成熟,库利和图基的成果掀起了数字信号处理的革命,因而FFT发明者的桂冠才落在他们头上。
之后,桑德(G.Sand)-图基等快速算法相继出现,几经改进,很快形成了一套高效运算方法,这就是现在的快速傅立叶变换(FFT)。这种算法使DFT的运算效率提高1到2个数量级,为数字信号处理技术应用于各种信号的实时处理创造了良好的条件,大大推进了数学信号处理技术。1984年,法国的杜哈梅(P.Dohamel)和霍尔曼(H.Hollamann)提出的分裂基块快速算法,使运算效率进一步提高。
库利和图基的FFT算法的最基本运算为蝶形运算,每个蝶形运算包括两个输入点,因而也称为基-2算法。在这之后,又有一些新的算法,进一步提高了FFT的运算效率,比如基-4算法,分裂基算法等。这些新算法对FFT运算效率的提高一般在50%以内,远远不如FFT对DFT运算的提高幅度。从这个意义上说,FFT算法是里程碑式的。可以说,正是计算机技术的发展和FFT的出现,才使得数字信号处理迎来了一个崭新的时代。除了运算效率的大幅度提高外,FFT还大大降低了DFT运算带来的累计量化误差,这点常为人们所忽略。
分给我吧 哈哈
③ 试画出信号按时间抽取的基-2FFT算法信号流图,并写出对应过程奇偶分流的公式。
基2算法,序列的长度是为2的幂,序列的DFT为。序列可以由奇序列和偶序列组成,DFT分别为和。 从最后一级往前分解对应的蝶形结构,这些蝶形结构最左边的输入都是序列的DFT值,而分解直到最左边的蝶形结构是两点序列的DFT,此时最左边的值是序列x[k]。
f1=50; %10Hz
f2=100; %100Hz
%抽样频率
Fs=1000; %100Hz
%抽样点数N
L=10;
N=2^L;
%抽样脉冲序列
n = 0:N-1;
t = n./Fs;
% f2 一个周期的采样数
M = floor(Fs/f2);
%被采样信号
x = cos(2*pi*f1.*t)+sin(2*pi*f2.*t);
%采样序列
subplot(311);
stem(t(1:2*M),x(1:2*M));
hold off;
%傅里叶变换
%根据有限长序列的离散傅里叶变换公式计算DFT
n = 0:N-1;
k = 0:N-1;
F = x * exp(-j*2*pi/N).^(n'*k);
subplot(312);
plot(n,abs(F));
subplot(313);
plot(k,angle(F));
(3)基2算法和直接算法扩展阅读:
库利-图基快速傅里叶变换算法是将序列长为N的DFT分区为两个长为N/2的子序列的DFT,因此这一应用只适用于序列长度为2的幂的DFT计算,即基2-FFT。实际上,如同高斯和库利与图基都指出的那样,库利-图基算法也可以用于序列长度N为任意因数分解形式的DFT,即混合基FFT,而且还可以应用于其他诸如分裂基FFT等变种。
尽管库利-图基算法的基本思路是采用递归的方法进行计算,大多数传统的算法实现都将显示的递归算法改写为非递归的形式。另外,因为库利-图基算法是将DFT分解为较小长度的多个DFT,因此它可以同任一种其他的DFT算法联合使用。
④ 基-2fft算法的软件实现 matlab代码
% 基于Matlab的时间抽取基2FFT算法
function y=myditfft(x)
%本程序对输入序列实现DIT-FFT基2算法,点数取大于等于长度的2的幂次
%------------------------------------
% Leo's fft program(改编网上的一个程序)
%------------------------------------
m=log2(2^nextpow2(length(x))); %求的x长度对应的2的最低幂次m
N=2^m;
if length(x)<N
x=[x,zeros(1,N-length(x))]; %若长度不是2的幂,补0到2的整数幂
end
x;
%--------------------------------------------------------------------------
%对输入序列进行倒序
%如果输入序列的自然顺序号I用二进制数(例如n2n1n0)表示
%则其倒位序J对应的二进制数就是(n0n1n2),这样,在原来自然顺序时应该放x(I)的
%单元,现在倒位序后应放x(J)。
%--------------------------------------------------------------------------
%以下程序相当于以下程序:
%nxd=bin2dec(fliplr(dec2bin([1:N]-1,m)))+1; %求1:2^m数列的倒序
%y=x(nxd); %将倒序排列作为初始值
%--------------------------------------------------------------------------
NV2=N/2;
NM1=N-1;
I=0;
J=0;
while I<NM1
if I<J
T=x(J+1);
x(J+1)=x(I+1);
x(I+1)=T;
end
K=NV2;
while K<=J
J=J-K;
K=K/2;
end
J=J+K;
I=I+1;
end
x;
%--------------------------------------------------------------------------
%以下程序解释:
%第一级从x(0)开始,跨接一阶蝶形,再取每条对称
%第二级从x(0)开始,跨接两阶蝶形,再取每条对称
%第m级从x(0)开始,跨接2^(m-1)阶蝶形,再取每条对称....
%--------------------------------------------------------------------------
for mm=1:m %将DFT做m次基2分解,从左到右,对每次分解作DFT运算
Nmr=2^mm;
u=1; %旋转因子u初始化
WN=exp(-j*2*pi/Nmr); %本次分解的基本DFT因子WN=exp(-i*2*pi/Nmr)
for n=1:Nmr/2 %本次跨越间隔内的各次碟形运算
for k=n:Nmr:N %本次碟形运算的跨越间隔为Nmr=2^mm
kp=k+Nmr/2; %确定碟形运算的对应单元下标(对称性)
t=x(kp)*u; %碟形运算的乘积项
x(kp)=x(k)-t; %碟形运算的加法项
x(k)=x(k)+t;
end
u=u*WN; %修改旋转因子,多乘一个基本DFT因子WN
end
end
y=x; %输出
⑤ fft绠楁硶镄勫熀链镐濊矾鏄浠涔堬纻
锘2绠楁硶锛屽簭鍒楃殑闀垮害鏄涓2镄勫箓锛屽簭鍒楃殑DFT涓恒傚簭鍒楀彲浠ョ敱濂囧簭鍒楀拰锅跺簭鍒楃粍鎴愶纴DFT鍒嗗埆涓哄拰銆 浠庢渶钖庝竴绾у线鍓嶅垎瑙e瑰簲镄勮澏褰㈢粨鏋勶纴杩欎簺铦跺舰缁撴瀯链宸﹁竟镄勮緭鍏ラ兘鏄搴忓垪镄凞FT鍊硷纴钥屽垎瑙g洿鍒版渶宸﹁竟镄勮澏褰㈢粨鏋勬槸涓ょ偣搴忓垪镄凞FT锛屾ゆ椂链宸﹁竟镄勫兼槸搴忓垪x[k]銆
锘4镞堕棿鎶藉彇FFT璁$畻锛氩皢搴忓垪鍒嗕负4涓鐭搴忓垪锛屽垎鍒涓簒[4k]銆亁[4k+1]銆亁[4k+2]銆亁[4k+3]锛屾疮涓绾ф湁N/4涓铦跺舰杩愮畻锛岀涓绾ф疮涓铦跺舰杩愮畻涓嶉渶瑕佷箻阃夋嫨锲犲瓙锛屾墍浠ユ病链夊嶆暟涔樻硶銆备箣钖庣殑绾ф暟锛屽洜涓猴纴涓嶉渶瑕佷箻绉锛屾墍浠ユ疮涓铦跺舰杩愮畻閮介渶瑕3娆′箻镞嬭浆锲犲瓙锛屾晠闇瑕3娆″嶆暟涔樻硶銆
镓╁𪾢璧勬枡锛
娉ㄦ剰浜嬮”锛
1銆佹渶灏忚垂鐢ㄦ渶澶ф祦锘轰簬链澶ф祦闂棰桡纴闾d箞灏辫佹敞镒忔祦镄勪笁涓閲嶈佺殑镐ц川锛屽叾娆¤佺悊瑙f祦閲忔槸涓绉嶉熺巼,钥屼笉鏄镐婚噺銆
2銆佹渶澶ф祦闂棰樼殑涓绉嶈В娉曞氨鏄澧炲箍璺锛屾渶閲嶈佺殑灏辨槸瑕佺悊瑙i娴佹搷浣滐纴鏄涓烘挙阌鍏埚墠阃夊彇镄勪笉钖堥傜殑寮с
3銆佹疮涓缁撶偣瑕佸缓绔4涓寮э纴鍒嗕负涓ゅ癸纴姣忓归兘鏄涓涓瀹归噺涓鸿竟瀹归噺镄勬h垂鐢╟ 鍜 鍙嶅悜瀹归噺涓0镄勪粯璐圭敤锛屼袱瀵圭殑鍖哄埆鏄鏂瑰悜𨱍冲弽锛屾疮瀵圭殑镎崭綔鐢ㄥ纾鎴朸銆
鍙傝冭祫鏂欐潵婧愶细锏惧害锏剧-FFT铡熺悊