打印
[开发资料]

FFT算法的原理详解

[复制链接]
467|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cemaj|  楼主 | 2022-12-22 21:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

/*

功能:将input里的数据进行快速傅里叶变换 并且输出

*/

#include

#include

#define FFT_LENGTH 8

double input[FFT_LENGTH]={1,1,1,1,1,1,1,1};

struct complex1{ //定义一个复数结构体

double real; //实部

double image; //虚部

};

//将input的实数结果存放为复数

struct complex1 result_dat[8];

/*

虚数的乘法

*/

struct complex1 con_complex(struct complex1 a,struct complex1 b){

struct complex1 temp;

temp.real=(a.real*b.real)-(a.image*b.image);

temp.image=(a.image*b.real)+(a.real*b.image);

return temp;

}

/*

简单的a的b次方

*/

int mypow(int a,int b){

int i,sum=a;

if(b==0)return 1;

for(i=1;i

sum*=a;

}

return sum;

}

/*

简单的求以2为底的正整数

*/

int log2(int n){

unsigned i=1;

int sum=1;

for(i;;i++){

sum*=2;

if(sum>=n)break;

}

return i;

}

/*

简单的交换数据的函数

*/

void swap(struct complex1 *a,struct complex1 *b){

struct complex1 temp;

temp=*a;

*a=*b;

*b=temp;

}

/*

dat为输入数据的数组

N为抽样次数 也代表周期 必须是2^N次方

*/

void fft(struct complex1 dat[],unsigned char N){

/*最终 dat_buf计算出 当前蝶形运算奇数项与W 乘积

dat_org存放上一个偶数项的值

*/

struct complex1 dat_buf,dat_org;

/* L为几级蝶形运算 也代表了2进制的位数

n为当前级蝶形的需要次数 n最初为N/2 每级蝶形运算后都要/2

i j为倒位时要用到的自增符号 同时 i也用到了L碟级数 j是计算当前碟级的计算次数

re_i i_copy均是倒位时用到的变量

k为当前碟级 cos(2*pi/N*k)的 k 也是e^(-j2*pi/N)*k 的 k

*/

unsigned char L,i,j,re_i=0,i_copy=0,k=0,fft_flag=1;

//经过观察,发现每级蝶形运算需要N/2次运算,共运算N/2*log2N 次

unsigned char fft_counter=0;

//在此要进行补2 N必须是2^n 在此略

//蝶形级数 (L级)

L=log2(N);

//计算每级蝶形计算的次数(这里只是一个初始值) 之后每次要/2

//n=N/2;

//对dat的顺序进行倒位

for(i=1;i

i_copy=i;

re_i=0;

for(j=L-1;j>0;j--){

//判断i的副本最低位的数字 并且移动到最高位 次高位 ..

//re_i为交换的数 每次它的数字是不能移动的 并且循环之后要清0

re_i|=((i_copy&0x01)<

i_copy>>=1;

}

swap(&dat,&dat[re_i]);

}

//进行fft计算

for(i=0;i

fft_flag=1;

fft_counter=0;

for(j=0;j

if(fft_counter==mypow(2,i)){ //控制隔几次,运算几次

fft_flag=0;

}else if(fft_counter==0){ //休止结束,继续运算

fft_flag=1;

}

//当不判断这个语句的时候 fft_flag保持 这样就可以持续运算了

if(fft_flag){

dat_buf.real=cos((2*PI*k)/(N/mypow(2,L-i-1)));

dat_buf.image=-sin((2*PI*k)/(N/mypow(2,L-i-1)));

dat_buf=con_complex(dat[j+mypow(2,i)],dat_buf);

//计算 当前蝶形运算奇数项与W 乘积

dat_org.real=dat[j].real;

dat_org.image=dat[j].image; //暂存

dat[j].real=dat_org.real+dat_buf.real;

dat[j].image=dat_org.image+dat_buf.image;

//实部加实部 虚部加虚部

dat[j+mypow(2,i)].real=dat_org.real-dat_buf.real;

dat[j+mypow(2,i)].image=dat_org.image-dat_buf.image;

//实部减实部 虚部减虚部

k++;

fft_counter++;

}else{

fft_counter--; //运算几次,就休止几次

k=0;

}

}

}

}

void main{

int i;

//先将输入信号转换成复数

for(i=0;i

result_dat.image=0;

//输入信号是二维的,暂时不存在复数

result_dat.real=input;

//result_dat.real=10;

//输入信号都为实数

}

fft(result_dat,FFT_LENGTH);

for(i=0;i

input=sqrt(result_dat.real*result_dat.real+result_dat.image*result_dat.image);

//取模

printf("%lfn",input);

}

while(1);

}

这个程序中input这个数组是输入信号,在这里只模拟抽样了8次,输出的数据也是input,如果想看其它序列的话,可以改变FFT_LENGTH 的值以及 input里的内容,程序输出的是实部和虚部的模


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

3780

帖子

2

粉丝