快速傅里叶变换(正/反)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.141592653589793238462643383279 //这三十位的PI我小学就会背了

void fft_rec(int N,int offset,int delta,double (*x)[2],double (*X)[2],double (*XX)[2])
{
int N2=N/2;
int k;
double cs,sn;
int k00,k01,k10,k11;
double tmp0,tmp1;

if(N != 2)
{
fft_rec(N2, offset, 2*delta, x, XX, X);
fft_rec(N2, offset+delta, 2*delta, x, XX, X);

for(k=0; k<N2; k++)
{
k00 = offset + k*delta; k01 = k00 + N2*delta;
k10 = offset + 2*k*delta; k11 = k10 + delta;
cs = cos(2*PI*k/(double)N); sn = sin(2*PI*k/(double)N);
tmp0 = cs * XX[k11][0] + sn * XX[k11][1];
tmp1 = cs * XX[k11][1] - sn * XX[k11][0];
X[k01][0] = XX[k10][0] - tmp0;
X[k01][1] = XX[k10][1] - tmp1;
X[k00][0] = XX[k10][0] + tmp0;
X[k00][1] = XX[k10][1] + tmp1;
}
}
else
{
k00 = offset; k01 = k00 + delta;
X[k01][0] = x[k00][0] - x[k01][0];
X[k01][1] = x[k00][1] - x[k01][1];
X[k00][0] = x[k00][0] + x[k01][0];
X[k00][1] = x[k00][1] + x[k01][1];
}
}

void fft(int N,double (*x)[2],double (*X)[2])
{
double (*XX)[2]=malloc(2*N*sizeof(double));
fft_rec(N,0,1,x,X,XX);
free(XX);
}

void ifft(int N, double (*x)[2], double (*X)[2])
{
int N2 = N/2;
int i;
double tmp0, tmp1;

fft(N, X, x);
x[0][0] = x[0][0]/N;
x[0][1] = x[0][1]/N;
x[N2][0] = x[N2][0]/N;
x[N2][1] = x[N2][1]/N;
for(i=1; i<N2; i++)
{
tmp0 = x[i][0]/N;
tmp1 = x[i][1]/N;

x[i][0] = x[N-i][0]/N;
x[i][1] = x[N-i][1]/N;

x[N-i][0] = tmp0;
x[N-i][1] = tmp1;
}
}

int main()
{
int N; //N点FFT变换,数据的个数
int i; //通用索引变量
double dummy; //随便起的名字
double (*x)[2]; //时域采样,x[i][0]实部,x[i][1]虚部
double (*X)[2]; //频域采样,X[i][0]实部,X[i][1]虚部
FILE *fp; //文件指针
char *file="C:\\Users\\tc\\Documents\\Visual Studio 2010\\Projects\\fftc\\Debug\\data.txt"; //data.txt文件全路径
N=0;

if (!(fp=fopen(file,"r")))
{
printf("file not read data");
system("pause");
return 0;
}

while (fscanf(fp, "%lg%lg",&dummy,&dummy)==2)
N++;
printf("N=%d",N);

if (N>=2)
{
i=N;
while(i==2*(i/2))
i=i/2;
}

if (N<2 || i!=1)
{
printf(",must equal 2^n for an integer n>=1");
system("pause");
return 0;
}

x=malloc(2*N*sizeof(double));
X=malloc(2*N*sizeof(double));

rewind(fp); //重置文件指针

for (i=0;i<N;i++)
fscanf(fp,"%lg%lg",&x[i][0],&x[i][1]); //读取文件数据,赋为时域采样值
fclose(fp); //关闭文件

printf("\n时域采样数据x(n):\n"); //显示原始数据
for (i=0;i<N;i++)
{
printf("%12f %12f\n",x[i][0],x[i][1]);
}

fft(N,x,X); //正变换函数

printf("\n频域变换数据X(k):\n"); //显示正变换后的数据
for (i=0;i<N;i++)
{
printf("%12f %12f\n",X[i][0],X[i][1]);
x[i][0]=0;
x[i][1]=0;
}

ifft(N,x,X); //反变换函数

printf("\n再反变换后时域数据x(n):\n"); //显示反变换后的数据,理论上和原数据一致
for (i=0;i<N;i++)
{
printf("%12f %12f\n",x[i][0],x[i][1]);
}
free(x);
free(X);

system("pause");
return 0;
}

data.txt:

3.6 2.6
2.9 6.3
5.6 4.0
4.8 9.1
3.3 0.4
5.9 4.8
5.0 2.6
4.3 4.1

受朋友所托,写了这样的一个程序,参考了加州理工一个老外的程序。

转载于:https://www.cnblogs.com/tiandsp/archive/2012/03/15/2398771.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值