http://blog.csdn.net/piaojun_pj/article/details/5911914
代码在2011年全国电子大赛结束后(2011年9月3日)发布,多个版本,注释详细。
-
-
- **程序描述:本程序实现快速傅里叶变换
- **程序作者:宋元瑞
- **最后修改:2011年4月5日
- *******************************************************************************/
- #include<stdio.h>
- #include<math.h>
-
- #definePI3.141592653589//圆周率,12位小数
- #defineN8//傅里叶变换的点数
- #defineM3//蝶形运算的级数,N=2^M
- typedefdoubleElemType;
-
- typedefstruct
- {
- ElemTypereal,imag;
- }complex;
- complexdata[N];
- ElemTyperesult[N];
- //变址
- voidChangeSeat(complex*DataInput)
- {
- intnextValue,nextM,i,k,j=0;
- complextemp;
- nextValue=N/2;
- nextM=N-1;
- for(i=0;i<nextM;i++)
- if(i<j)
- temp=DataInput[j];
- DataInput[j]=DataInput[i];
- DataInput[i]=temp;
- }
- k=nextValue;
- while(k<=j)
- j=j-k;
- k=k/2;
- j=j+k;
- }
- /*
- //变址
- voidChangeSeat(complex*DataInput)
- {
- complexTemp[N];
- inti,n,New_seat;
- for(i=0;i<N;i++)
- Temp[i].real=DataInput[i].real;
- Temp[i].imag=DataInput[i].imag;
- }
- for(i=0;i<N;i++)
- {
- New_seat=0;
- for(n=0;n<M;n++)
- New_seat=New_seat|(((i>>n)&0x01)<<(M-n-1));
- }
- DataInput[New_seat].real=Temp[i].real;
- DataInput[New_seat].imag=Temp[i].imag;
- */
- //复数乘法
- complexXX_complex(complexa,complexb)
- complextemp;
- temp.real=a.real*b.real-a.imag*b.imag;
- temp.imag=b.imag*a.real+a.imag*b.real;
- returntemp;
- //FFT
- voidFFT(void)
- intL=0,B=0,J=0,K=0;
- intstep=0;
- ElemTypeP=0,T=0;
- complexW,Temp_XX;
- //ElemTypeTempResult[N];
- ChangeSeat(data);
- for(L=1;L<=M;L++)
- B=1<<(L-1);
- for(J=0;J<=B-1;J++)
- P=(1<<(M-L))*J;
- step=1<<L;
- for(K=J;K<=N-1;K=K+step)
- W.real=cos(2*PI*P/N);
- W.imag=-sin(2*PI*P/N);
- Temp_XX=XX_complex(data[K+B],W);
- data[K+B].real=data[K].real-Temp_XX.real;
- data[K+B].imag=data[K].imag-Temp_XX.imag;
- data[K].real=data[K].real+Temp_XX.real;
- data[K].imag=data[K].imag+Temp_XX.imag;
- voidIFFT(void)
- intstep=0;
- ElemTypeP=0,T=0;
- complexW,Temp_XX;
- //ElemTypeTempResult[N];
- ChangeSeat(data);
- for(L=1;L<=M;L++)
- B=1<<(L-1);
- for(J=0;J<=B-1;J++)
- P=(1<<(M-L))*J;
- step=1<<L;
- for(K=J;K<=N-1;K=K+step)
- W.real=cos(2*PI*P/N);
- W.imag=sin(2*PI*P/N);
- Temp_XX=XX_complex(data[K+B],W);
- data[K+B].real=data[K].real-Temp_XX.real;
- data[K+B].imag=data[K].imag-Temp_XX.imag;
- data[K].real=data[K].real+Temp_XX.real;
- data[K].imag=data[K].imag+Temp_XX.imag;
- intmain(intargc,char*argv[])
- inti=0;
- for(i=0;i<N;i++)
- data[i].real=sin(2*PI*i/N);
- printf("%lf",data[i]);
- printf("nn");
- FFT();
- for(i=0;i<N;i++)
- {printf("%lf",sqrt(data[i].real*data[i].real+data[i].imag*data[i].imag));}
- IFFT();
- printf("nn");
- for(i=0;i<N;i++)
- {printf("%lf",data[i].real/N);}
- printf("n");
- /*for(i=0;i<N;i++)
- {printf("%lf",data[i].imag/N);}
- printf("n");*/
- /*for(i=0;i<N;i++)
- return0;
- }
**性能提升:修正了IFFT的bug,使用宏定义改变N大小
- **程序版本:V6.5
- **最后修改:2011年5月16日
- #definePI3.14159265358979323846264338327950288419716939937510//圆周率,50位小数
- #definePI26.28318530717958647692528676655900576839433879875021
- #defineN1024//傅里叶变换的点数
- #defineM10//蝶形运算的级数,N=2^M
- #defineNpart2512//创建正弦函数表时取PI的1/2
- #defineNpart4256//创建正弦函数表时取PI的1/4
- #defineFFT_RESULT(x)(sqrt(data[x].real*data[x].real+data[x].imag*data[x].imag))
- #defineIFFT_RESULT(x)(data[x].real/N)
- floatElemType;
- //定义复数结构体
- ElemTypereal,imag;
- }complex;
- complexdata[N];
- ElemTypeSIN_TABLE[Npart4+1];
- //产生模拟原始数据输入
- voidInputData(inti;
- data[i].real=sin(2*PI*i/N);
- data[i].imag=0;
- //创建正弦函数表
- voidCREATE_SIN_TABLE(for(i=0;i<=Npart4;i++)
- SIN_TABLE[i]=sin(PI*i/Npart2);
- ElemTypeSin_find(ElemTypex)
- inti=(int)(N*x);
- i=i>>1;
- if(i>Npart4)
- {
- i=Npart2-i;
- returnSIN_TABLE[i];
- ElemTypeCos_find(ElemTypex)
- if(i<Npart4)
- returnSIN_TABLE[Npart4-i];
- else
- //i=i-Npart4;
- return-SIN_TABLE[i-Npart4];
- //变址
- voidChangeSeat(complex*DataInput)
- nextValue=N/2;
- nextM=N-1;
- for(i=0;i<nextM;i++)
- temp=DataInput[j];
- DataInput[j]=DataInput[i];
- DataInput[i]=temp;
- k=nextValue;
- j=j-k;
- k=k/2;
- j=j+k;
- //复数乘法
- /*complexXX_complex(complexa,complexb)
- complextemp;
- temp.real=a.real*b.real-a.imag*b.imag;
- temp.imag=b.imag*a.real+a.imag*b.real;
- returntemp;
- }*/
- //FFT运算函数
- intstep=0,KB=0;
- //ElemTypeP=0;
- ElemTypeangle;
- ChangeSeat(data);
- B=step>>1;(J=0;J<B;J++)
- //P=(1<<(M-L))*J;//P=2^(M-L)*J
- angle=(double)J/B;
- W.imag=-Sin_find(angle);
- W.real=Cos_find(angle);
- //W.real=cos(angle*PI);
- //W.imag=-sin(angle*PI);
- for(K=J;K<N;K=K+step)
- KB=K+B;
- //Temp_XX=XX_complex(data[KB],W);
- //用下面两行直接计算复数乘法,省去函数调用开销
- Temp_XX.real=data[KB].real*W.real-data[KB].imag*W.imag;
- Temp_XX.imag=W.imag*data[KB].real+data[KB].imag*W.real;
- data[KB].real=data[K].real-Temp_XX.real;
- data[KB].imag=data[K].imag-Temp_XX.imag;
- //IFFT运算函数
- W.imag=Sin_find(angle);
- //W.imag=-sin(angle*PI);
- for(K=J;K<N;K=K+step)
- KB=K+B;
- //用下面两行直接计算复数乘法,省去函数调用开销
- Temp_XX.real=data[KB].real*W.real-data[KB].imag*W.imag;
- Temp_XX.imag=W.imag*data[KB].real+data[KB].imag*W.real;
- data[KB].real=data[K].real-Temp_XX.real;
- data[KB].imag=data[K].imag-Temp_XX.imag;
- //主函数
- CREATE_SIN_TABLE();
- InputData();
- {printf("%f",FFT_RESULT(i));}
- //进行IFFT计算
- copy
**程序描述:本程序实现快速傅里叶变换及其逆变换
- **性能提升:修正了FFT的bug,变量重新命名,并将N_FFT改为动态值
- **程序版本:V6.6
- #include<stdlib.h>
- #include<math.h>
- //#defineOUTPRINTprintf
- //#defineDEL/##/
- #defineRESULT(x)sqrt(data_of_N_FFT[x].real*data_of_N_FFT[x].real+data_of_N_FFT[x].imag*data_of_N_FFT[x].imag)
- #definePI3.14159265358979323846264338327950288419716939937510//圆周率,50位小数
- #definePI26.28318530717958647692528676655900576839433879875021
- intN_FFT=0;
- intM_of_N_FFT=0;
- intNpart2_of_N_FFT=0;
- intNpart4_of_N_FFT=0;
- }complex_of_N_FFT,*ptr_complex_of_N_FFT;
- ptr_complex_of_N_FFTdata_of_N_FFT=NULL;
- ElemType*SIN_TABLE_of_N_FFT=NULL;
- for(i=0;i<N_FFT;i++)
- printf("%f",data_of_N_FFT[i].real);
- for(i=0;i<=Npart4_of_N_FFT;i++)
- SIN_TABLE_of_N_FFT[i]=sin(PI*i/Npart2_of_N_FFT);
- int)(N_FFT*x);
- i=i>>1;
- if(i>Npart4_of_N_FFT)
- i=Npart2_of_N_FFT-i;SIN_TABLE_of_N_FFT[i];
- ElemTypeCos_find(ElemTypex)
- if(i<Npart4_of_N_FFT)SIN_TABLE_of_N_FFT[Npart4_of_N_FFT-i];
- return-SIN_TABLE_of_N_FFT[i-Npart4_of_N_FFT];
- voidChangeSeat(complex_of_N_FFT*DataInput)
- complex_of_N_FFTtemp;
- nextValue=N_FFT/2;
- complex_of_N_FFTW,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ChangeSeat(data_of_N_FFT);(L=1;L<=M_of_N_FFT;L++)
- for(K=J;K<N_FFT;K=K+step)
- Temp_XX.real=data_of_N_FFT[KB].real*W.real-data_of_N_FFT[KB].imag*W.imag;
- Temp_XX.imag=W.imag*data_of_N_FFT[KB].real+data_of_N_FFT[KB].imag*W.real;
- data_of_N_FFT[KB].real=data_of_N_FFT[K].real-Temp_XX.real;
- data_of_N_FFT[KB].imag=data_of_N_FFT[K].imag-Temp_XX.imag;
- data_of_N_FFT[K].real=data_of_N_FFT[K].real+Temp_XX.real;
- data_of_N_FFT[K].imag=data_of_N_FFT[K].imag+Temp_XX.imag;
- //IFFT运算函数
- //ElemTypeP=0;
- ElemTypeangle;
- complex_of_N_FFTW,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> ChangeSeat(data_of_N_FFT);
- for(L=1;L<=M_of_N_FFT;L++)
- B=step>>1;(J=0;J<B;J++)
- //P=(1<<(M-L))*J;//P=2^(M-L)*J
- angle=(//这里还可以优化
- W.imag=Sin_find(angle);
- //N_FFT是FFT的点数,必须是2的次方
- voidInit_FFT(intN_of_FFT)
- inti=0;
- inttemp_N_FFT=1;
- N_FFT=N_of_FFT;
- M_of_N_FFT=0;
- for(i=0;temp_N_FFT<N_FFT;i++)
- temp_N_FFT=2*temp_N_FFT;
- M_of_N_FFT++;
- printf("n%dn",M_of_N_FFT);
- Npart2_of_N_FFT=N_FFT/2;
- Npart4_of_N_FFT=N_FFT/4;
- //ptr_complex_of_N_FFTdata_of_N_FFT=NULL;//开辟存储单元,原始数据与负数结果均使用之
- data_of_N_FFT=(ptr_complex_of_N_FFT)malloc(N_FFT*sizeof(complex_of_N_FFT));
- //ptr_complex_of_N_FFTSIN_TABLE_of_N_FFT=NULL;
- SIN_TABLE_of_N_FFT=(ElemType*)malloc((Npart4_of_N_FFT+1)*sizeof(ElemType));
- CREATE_SIN_TABLE();
- voidClose_FFT(if(data_of_N_FFT!=NULL)
- free(data_of_N_FFT);
- data_of_N_FFT=NULL;
- if(SIN_TABLE_of_N_FFT!=NULL)
- free(SIN_TABLE_of_N_FFT);
- SIN_TABLE_of_N_FFT=NULL;
- Init_FFT(1024);
- //输入原始数据
- for(i=0;i<N_FFT;i++)
- printf("%f",RESULT(i));
- IFFT();
- for(i=0;i<N_FFT;i++)
- Close_FFT();
- **模块描述:本程序实现快速傅里叶变换
- **性能提升:已达到网上同类程序最高速度
- **模块版本:V6.0
- **模块作者:宋元瑞
- **最后修改:2011年5月6日
- **程序说明:
- FFT运算输入参数source_Data(i)是一个N大小的数组(注意是小括号)
- FFT运算输出结果result_Data(i)是一个N大小的数组(注意是小括号)
- **调用举例:
- intmain(intargc,char*argv[])
- inti=0;
- ///以下为FFT运算的调用方式
- FFT_prepare();//为FFT做好准备,此函数只需程序开始时执行一次即可,切勿写在循环中
- while(1)
- for(i=0;i<N_FFT;i++)//输入原始数据
- {source_Data(i)=sin(2*PI*i/N_FFT);}//注意inputData后面是小括号
- FFT();//进行FFT计算
- //输出结果:XXX=result_Data(i);
- return0;
- #ifndefSYRFFT_H
- //#pragmaonce
- //#include<stdio.h>
- #defineFFT_prepare()CREATE_SIN_TABLE();//创建正弦函数表
- #definesource_Data(i)data_FFT[i].imag//接收输入数据的数组,大小为N
- #defineresult_Data(i)sqrt(data_FFT[i].real*data_FFT[i].real+data_FFT[i].imag*data_FFT[i].imag)//FFT结果
- #defineN_FFT1024//傅里叶变换的点数
- #defineM_of_N_FFT10//蝶形运算的级数,N=2^M
- #defineNpart2_of_N_FFT512//创建正弦函数表时取PI的1/2
- #defineNpart4_of_N_FFT256//创建正弦函数表时取PI的1/4
- }complex_of_N_FFT;
- complex_of_N_FFTdata_FFT[N_FFT];
- ElemTypeSIN_TABLE[Npart4_of_N_FFT+1];
- /*
- voidInputData(void)
- inti;
- for(i=0;i<N_FFT;i++)//制造输入序列
- source_Data(i)=sin(2*PI*i/N_FFT);//模拟输入正弦波
- //data_FFT[i].imag=sin(2*PI*i/N);//正弦波
- //printf("%f",data_FFT[i].imag);
- SIN_TABLE[i]=sin(PI*i/Npart2_of_N_FFT);)(N_FFT*x);
- returnSIN_TABLE[Npart4_of_N_FFT-i];
- return-SIN_TABLE[i-Npart4_of_N_FFT];
- //变址前data_FFT[i].imag存储了输入数据,变址后data_FFT[i].real存储了输入数据
- inti,New_seat;
- New_seat=0;
- for(n=0;n<M_of_N_FFT;n++)
- New_seat=New_seat|(((i>>n)&0x01)<<(M_of_N_FFT-n-1));
- DataInput[New_seat].real=DataInput[i].imag;
- DataInput[i].imag=0;
- complex_of_N_FFTXX_complex(complex_of_N_FFTa,complex_of_N_FFTb)
- complex_of_N_FFTtemp;
- ChangeSeat(data_FFT);
- Temp_XX.imag=W.imag*data_FFT[KB].real+data_FFT[KB].imag*W.real;
- data_FFT[KB].real=data_FFT[K].real-Temp_XX.real;
- data_FFT[KB].imag=data_FFT[K].imag-Temp_XX.imag;
- data_FFT[K].real=data_FFT[K].real+Temp_XX.real;
- data_FFT[K].imag=data_FFT[K].imag+Temp_XX.imag;
- #defineSYRFFT_H
- #endif
**程序版本:V6.0
- **程序作者:宋元瑞
- **最后修改:2011年5月6日
- *******************************************************************************/
- #include"syrFFT_H.h"//包含FFT运算头文件
- //以下3句为FFT运算的调用函数
- FFT_prepare();
- //while(1)
- //模拟输入
- {source_Data(i)=sin(2*PI*i/N_FFT);}
- FFT();
- //输出结果
-
copy
#ifndefFFT_H
- #include<stdlib.h>
- //创建正弦函数表
- for(i=0;i<=Npart4_of_N_FFT;i++)
- SIN_TABLE_of_N_FFT[i]=sin(PI*i/Npart2_of_N_FFT);
- {
- i=Npart2_of_N_FFT-i;
- returnSIN_TABLE_of_N_FFT[i];
- //i=Npart4-i;
- returnSIN_TABLE_of_N_FFT[Npart4_of_N_FFT-i];
- //i>Npart4&&i<N/2
- //i=i-Npart4;
- return-SIN_TABLE_of_N_FFT[i-Npart4_of_N_FFT];
- voidChangeSeat(complex_of_N_FFT*DataInput)
- complex_of_N_FFTtemp;
- nextValue=N_FFT/2;
- complextemp;
- temp.real=a.real*b.real-a.imag*b.imag;
- temp.imag=b.imag*a.real+a.imag*b.real;
- returntemp;
- }*/
- //FFT运算函数
- W.imag=-Sin_find(angle);(K=J;K<N_FFT;K=K+step)
- Temp_XX.real=data_of_N_FFT[KB].real*W.real-data_of_N_FFT[KB].imag*W.imag;
- Temp_XX.imag=W.imag*data_of_N_FFT[KB].real+data_of_N_FFT[KB].imag*W.real;
- data_of_N_FFT[KB].real=data_of_N_FFT[K].real-Temp_XX.real;
- data_of_N_FFT[KB].imag=data_of_N_FFT[K].imag-Temp_XX.imag;
- data_of_N_FFT[K].real=data_of_N_FFT[K].real+Temp_XX.real;
- data_of_N_FFT[K].imag=data_of_N_FFT[K].imag+Temp_XX.imag;
- //printf("n%dn",M_of_N_FFT);
- //结束FFT运算,释放相关内存
- if(data_of_N_FFT!=NULL)
- free(data_of_N_FFT);
- if(SIN_TABLE_of_N_FFT!=NULL)
- free(SIN_TABLE_of_N_FFT);
- #defineFFT_H
- #endif
**性能提升:修正了FFT的bug
- #include"jxust_fft6_6.h"
- //产生模拟原始数据输入,在实际应用时替换为AD采样数据
- //输入采样数据
- //主函数,示例如何调用FFT运算
- char*argv[])
- Init_FFT(1024);
- InputData();
- FFT();
- //for(i=0;i<N_FFT;i++)//④输出FFT频谱结果sqrt(data_of_N_FFT[i].real*data_of_N_FFT[i].real+data_of_N_FFT[i].imag*data_of_N_FFT[i].imag)
- //{printf("%f",RESULT(i));}
- //for(i=0;i<N_FFT;i++)//(可选步骤)⑤输出IFFT结果,滤波时会用到;暂时不用
- Close_FFT();
- return0;
- }
copy
#ifndefSYRFFT_6_55_H
- #defineFFT_RESULT(x)(sqrt(data_of_N_FFT[x].real*data_of_N_FFT[x].real+data_of_N_FFT[x].imag*data_of_N_FFT[x].imag))
- #defineIFFT_RESULT(x)(data_of_N_FFT[x].real/N_FFT)
- #defineN_FFT1024//傅里叶变换的点数
- #defineM_of_N_FFT10//蝶形运算的级数,N=2^M
- #defineNpart2_of_N_FFT512//创建正弦函数表时取PI的1/2
- #defineNpart4_of_N_FFT256//创建正弦函数表时取PI的1/4
- }complex_of_N_FFT,*ptr_complex_of_N_FFT;
- complex_of_N_FFTdata_of_N_FFT[N_FFT];
- int)(N_FFT*x);
- if(i>Npart4_of_N_FFT)
- //根据FFT相关公式,sin()参数不会超过PI,即i不会超过N/2
- if(i<Npart4_of_N_FFT)
- else
- voidInit_FFT()
- #defineSYRFFT_6_55_H
- #endif
copy
**程序版本:V6.55
- **最后修改:2011年5月22日
- #include"syrFFT_6_55.h"
- inti;
- //制造输入序列
- data_of_N_FFT[i].real=sin(2*PI*i/N_FFT);
- data_of_N_FFT[i].imag=0;
- //主函数,示例如何调用FFT运算
- Init_FFT();
- //③进行FFT计算
- //for(i=0;i<N_FFT;i++)//④输出FFT频谱结果sqrt(data_of_N_FFT[i].real*data_of_N_FFT[i].real+data_of_N_FFT[i].imag*data_of_N_FFT[i].imag)
- //for(i=0;i<N_FFT;i++)//(可选步骤)⑤输出IFFT结果,滤波时会用到;暂时不用
- //结束FFT运算,此版本此句无用,可不写
- }
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|