快速傅里叶变换 要用C++ 才行吧 你可以用MATLAB来实现更方便点啊
①.
下面为FFT.CPP文件:
// FFT.cpp : 定义控制台应用程序的入口点.
#include "stdafx.h"
#include iostream
#include complex
#include bitset
#include vector
#include conio.h
#include string
#include fstream
using namespace std;
bool inputData(unsigned long , vectorcomplexdouble ); //手工输入数据
void FFT(unsigned long , vectorcomplexdouble ); //FFT变换
bool readDataFromFile(unsigned long , vectorcomplexdouble ); //从文件中读取数据
bool saveResultToFile(unsigned long , vectorcomplexdouble ); //保存结果至文件中
int _tmain(int argc, _TCHAR* argv[])
{
vectorcomplexdouble vecList; //有限长序列
unsigned long ulN = 0; //N
char chChoose = ' '; //功能选择
//功能循环
while(chChoose != 'Q' chChoose != 'q')
//显示选择项
cout "\nPlease chose a function" endl;
cout "\t1.Input data manually, press 'M':" endl;
cout "Please chose:";
//输入选择
chChoose = getch();
//判断
switch(chChoose)
case 'm': //手工输入数据
case 'M':
if(inputData(ulN, vecList))
FFT(ulN, vecList);
saveResultToFile(ulN, vecList);
}
break;
case 'f': //从文档读取数据
case 'F':
if(readDataFromFile(ulN, vecList))
return 0;
return false;
while( ul 1 )
return true;
bool inputData(unsigned long ulN, vectorcomplexdouble vecList)
//题目
cout "\n\n\n==============================Input Data===============================" endl;
//输入N
cout "\nInput N:";
cinulN;
//输入各元素
vecList.clear(); //清空原有序列
complexdouble c;
for(unsigned long i = 0; i ulN; i++)
cout "Input x(" i "):";
cin c;
vecList.push_back(c);
bool readDataFromFile(unsigned long ulN, vectorcomplexdouble vecList) //从文件中读取数据
cout "\n\n\n===============Read Data From File==============" endl;
//输入文件名
string strfilename;
cout "Input filename:" ;
cin strfilename;
//打开文件
cout "open file " strfilename "......." endl;
ifstream loadfile;
loadfile.open(strfilename.c_str());
if(!loadfile)
cout "\tfailed" endl;
else
cout "\tsucceed" endl;
vecList.clear();
//读取N
loadfile ulN;
cout "can't get N" endl;
cout "N = " ulN endl;
//读取元素
loadfile c;
cout "can't get enough infomation" endl;
cout "x(" i ") = " c endl;
//关闭文件
loadfile.close();
bool saveResultToFile(unsigned long ulN, vectorcomplexdouble vecList) //保存结果至文件中
//询问是否需要将结果保存至文件
char chChoose = ' ';
cout "Do you want to save the result to file? (y/n):";
chChoose = _getch();
if(chChoose != 'y' chChoose != 'Y')
cout "\nInput file name:" ;
cout "Save result to file " strfilename "......" endl;
ofstream savefile(strfilename.c_str());
if(!savefile)
cout "can't open file" endl;
//写入N
savefile ulN endl;
//写入元素
for(vectorcomplexdouble ::iterator i = vecList.begin(); i vecList.end(); i++)
savefile *i endl;
//写入完毕
cout "save succeed." endl;
savefile.close();
void FFT(unsigned long ulN, vectorcomplexdouble vecList)
//得到幂数
unsigned long ulPower = 0; //幂数
unsigned long ulN1 = ulN - 1;
while(ulN1 0)
ulPower++;
//反序
unsigned long ulIndex; //反转后的序号
unsigned long ulK;
for(unsigned long p = 0; p ulN; p++)
ulIndex = 0;
ulK = 1;
for(unsigned long j = 0; j ulPower; j++)
ulIndex += bsIndex.test(ulPower - j - 1) ? ulK : 0;
if(ulIndex p)
complexdouble c = vecList[p];
vecList[p] = vecList[ulIndex];
vecList[ulIndex] = c;
//计算旋转因子
vectorcomplexdouble vecW;
cout "\nvW[" m "]=" vecW[m];
//计算FFT
unsigned long ulGroupLength = 1; //段的长度
unsigned long ulHalfLength = 0; //段长度的一半
unsigned long ulGroupCount = 0; //段的数量
complexdouble cw; //WH(x)
complexdouble c1; //G(x) + WH(x)
for(unsigned long b = 0; b ulPower; b++)
ulHalfLength = ulGroupLength;
for(unsigned long j = 0; j ulN; j += ulGroupLength)
for(unsigned long k = 0; k ulHalfLength; k++)
cw = vecW[k * ulN / ulGroupLength] * vecList[j + k + ulHalfLength];
c1 = vecList[j + k] + cw;
vecList[j + k] = c1;
cout "\n\n===========================Display The Result=========================" endl;
for(unsigned long d = 0; d ulN;d++)
cout "X(" d ")\t\t\t = " vecList[d] endl;
下面为STDAFX.H文件:
// stdafx.h : 标准系统包含文件的包含文件,
// 或是常用但不常更改的项目特定的包含文件
#pragma once
#include tchar.h
// TODO: 在此处引用程序要求的附加头文件
下面为STDAFX.CPP文件:
// stdafx.cpp : 只包括标准包含文件的源文件
// FFT.pch 将成为预编译头
// stdafx.obj 将包含预编译类型信息
// TODO: 在 STDAFX.H 中
//引用任何所需的附加头文件,而不是在此文件中引用
r[m]?=?Autocorrelation(data,N);?可解决语法错误
printf("%d\n",r[m]);应改为
printf("%f\n",r[m]);
#includestdio.h
int?N=10;
int?i,m;
float?Autocorrelation(float?data[],?int?N)
for(?m=0;mN;m++)for(?i=1;?i=N;?i++)r[m]+=?data[i]?*?data[i+m];
return?r[N-1];}
void?main()
{r[m]?=?Autocorrelation(data,N);
printf("%f\n",r[m]);}
getch();
①.、二维FFT相当于对行和列分别进行一维FFT运算.具体的实现办法如下:
先对各行逐一进行一维FFT,然后再对变换后的新矩阵的各列逐一进行一维FFT.相应的伪代码如下所示:
for (int i=0; iM; i++)
FFT_1D(ROW[i],N);
for (int j=0; jN; j++)
FFT_1D(COL[j],M);
其中,ROW[i]表示矩阵的第i行.注意这只是一个简单的记法,并不能完全照抄.还需要通过一些语句来生成各行的数据.同理,COL[i]是对矩阵的第i列的一种简单表示方法.
所以,关键是一维FFT算法的实现.
#include?stdio.h
#include?math.h
#include?stdlib.h
#define?N?1000
/*定义复数类型*/
typedef?struct{
double?real;
double?img;
}complex;
complex?x[N],?*W;?/*输入序列,变换核*/
double?PI;??/*圆周率*/
void?fft();??/*快速傅里叶变换*/
void?initW();?/*初始化变换核*/
void?change();?/*变址*/
void?add(complex?,complex?,complex?*);?/*复数加法*/
void?mul(complex?,complex?,complex?*);?/*复数乘法*/
void?sub(complex?,complex?,complex?*);?/*复数减法*/
void?output();
int?main(){
int?i;??????/*输出结果*/
system("cls");
printf("Please?input?the?size?of?x:\n");
scanf("%d",size_x);
printf("Please?input?the?data?in?x[N]:\n");
for(i=0;isize_x;i++)
scanf("%lf%lf",x[i].real,x[i].img);
initW();
fft();
output();
return?0;
/*快速傅里叶变换*/
void?fft(){
int?i=0,j=0,k=0,l=0;
complex?up,down,product;
change();
l=1i;
for(k=0;kl;k++){??/*一个蝶形运算*/
add(x[j+k],product,up);
sub(x[j+k],product,down);
x[j+k]=up;
x[j+k+l]=down;
/*初始化变换核*/
void?initW(){
int?i;
W=(complex?*)malloc(sizeof(complex)?*?size_x);
for(i=0;isize_x;i++){
/*变址计算,将x(n)码位倒置*/
void?change(){
complex?temp;
unsigned?short?i=0,j=0,k=0;
double?t;
k=i;j=0;
while(?(t--)0?){
j=j1;
j|=(k?1);
k=k1;
if(ji){
temp=x[i];
x[i]=x[j];
x[j]=temp;
/*输出傅里叶变换的结果*/
void?output(){
printf("The?result?are?as?follows\n");
else?if(fabs(x[i].img)0.0001)printf("\n");
void?add(complex?a,complex?b,complex?*c){
c-real=a.real+b.real;
c-img=a.img+b.img;
void?mul(complex?a,complex?b,complex?*c){
c-real=a.real*b.real?-?a.img*b.img;
c-img=a.real*b.img?+?a.img*b.real;
void?sub(complex?a,complex?b,complex?*c){
c-real=a.real-b.real;
c-img=a.img-b.img;
void fft(int nn) /* nn数据长度 */
switch(nn)
j=1;
for(i=1;i=nn;i++)
if(lj)
k=n1;
while (kj)
j=j-k;
j=j+k;
for(i=1;i=s;i++)
u1=1;
m=(1i);
k=m1;
w1=fcos[i-1];
for(j=1;j=k;j++)
for(l=j;lnn;l=l+m)
l1=l+k;
u1=z;
土嘎嘎的粉丝们大家好,这是我的回答,希望可以帮到你.
①.)结果讨论
一,如果对信号进行同样点数N的FFT变换,采样频率fs越高,则可以分析越高频的信号;与此同时,采样频率越低,对于低频信号的频谱分辨率则越好.
二,假设采样点不在正弦信号的波峰、波谷、以及0电压处,频谱则会产生泄露(leakage).
三,对于同样的采样率fs,提高FFT的点数N,则可提高频谱的分辨率.
五,对于(二)中泄露现象,可以通过在信号后面补零点解决.
%清除命令窗口及变量
clc;
clear all;
%输入f、N、T、是否补零(补几个零)
f=input('Input frequency of the signal: f\n');
N=input('Input number of pointsl: N\n');
T=input('Input sampling time: T\n');
flag=input('Add zero too sampling signal or not? yes=1 no=0\n');
if(flag)
ZeroNum=input('Input nmber of zeros\n');
ZeroNum=0;
end
%生成信号,signal是原信号.signal为采样信号.
fs=1/T;
t=0:0.00001:T*(N+ZeroNum-1);
if (flag)
%画出原信号及采样信号.
figure;
plot(t,signal);
xlabel('Time(s)');
ylabel('Amplitude(volt)');
title('Singnal');
hold on;
axis([0 T*(N+ZeroNum) -1 1]);
%作FFT变换,计算其幅值,归一化处理,并画出频谱.
Pyy = Y.* conj(Y) ;
xlabel('Frequency(Hz)');
ylabel('Amplitude');
title('Frequency compnents of signal');
grid on;
good luck!
我可以帮助你,你先设置我最佳答案后,我百度Hii教你.
以上就是土嘎嘎小编为大家整理的c语言写fft自相关函数相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!