FFT快速傅立叶算法纯C语言版本【转】

来自:http://blog.csdn.net/calcular/article/details/46804643

快速离散傅立叶变换FFT利用DFT计算的对称性实现的,具体的介绍网上一大堆。这次自己写了个定点FFT头文件,直接用C语言写的很容易移植。

/* 
     快速离散傅立叶算法V1.0 
       含有:FFT,IFFT 
         made by xyt 
          2015/7/8 
           C语言 
*/  
#ifndef _FFT_H  
#define _FFT_H  
#include<math.h>  
  
#define FFT_N 8  //点数,要求2的次方  
  
#define PI 3.14159265354  
struct fft_complex{  
    double r,i;  
};  
int fft_fi(double in){  //四舍五入转整  
    if((in-(int)in)>0.5) return (int)in+1;  
    else return (int)in;  
}  
int fft_fac2(int n){   //返回log2(n)  
    int count=0;  
    while(n/2!=0){  
        n/=2;count++;  
    }  
    return count;  
}  
int fft_turndat(int n,int num){   
    int g=n,m,r=0;  
    int count=0;  
    while(num/2!=0){  
        num/=2;count++;  
    }   
    while(count>=0){  
        m=g%2;  
        r+=m*pow(2,--count);  
        g/=2;  
    }  
    return r;  
}  
fft_complex fft_t(fft_complex a){  
    fft_complex tmp;  
    tmp.i=-1*a.i;  
    tmp.r=-1*a.r;  
    return tmp;  
}  
fft_complex fft_multi(fft_complex a,fft_complex b){  
    fft_complex tmp;  
    tmp.r=a.r*b.r-a.i*b.i;  
    tmp.i=a.r*b.i+a.i*b.r;  
    return tmp;  
}  
fft_complex fft_add(fft_complex a,fft_complex b){  
    fft_complex tmp;  
    tmp.r=a.r+b.r;  
    tmp.i=a.i+b.i;  
    return tmp;  
}  
/* 定点FFT,返回两个double型数组分别是实部和虚部 */  
void FFT(int *in,double *outr,double *outi)   
{  
    int i,j;  
    int deep;  
    const int N=FFT_N/2;  
    fft_complex W[N];  
    W[0].r=1;W[0].i=0;  
    W[1].r=cos(2.0*PI/FFT_N);  
    W[1].i=sin(2.0*PI/FFT_N);  
    for(i=2;i<N;i++){  
        W[i]=fft_multi(W[1],W[i-1]);  
    }  
    deep=fft_fac2(FFT_N);  
    int g=1;  
    int ne=0,ge=0;  
  
    fft_complex left[FFT_N];  
    fft_complex right[FFT_N];  
    for(i=0;i<FFT_N;i++){  
        left[i].r=in[fft_turndat(i,FFT_N)];  
        left[i].i=0;  
    }  
    fft_complex tpp;  
    int mggtmp;  
    while(1)  
    {  
        if(deep==0) break;  
        int adt=pow(2,deep-1);  
        mggtmp=pow(2,g);  
        for(i=0;i<FFT_N;i+=mggtmp){   
            ne=0;ge=0;  
            for(j=0;j<mggtmp;j++){  
                if(j<mggtmp/2){  
                    tpp=fft_multi(left[i+j+mggtmp/2],W[ne]);  
                    right[i+j]=fft_add(left[i+j],tpp);ne+=adt;  
                }else{  
                    tpp=fft_t(fft_multi(left[i+j],W[ge]));  
                    right[i+j]=fft_add(left[i+j-mggtmp/2],tpp);ge+=adt;  
                }  
            }  
        }  
        for(i=0;i<FFT_N;i++){  
            left[i]=right[i];  
        }  
        deep--;g++;  
    }  
    for(i=0;i<FFT_N;i++){  
        outr[i]=left[i].r;  
        outi[i]=-1*left[i].i;  
    }  
}  
/* 定点IFFT,输入实部和虚部,返回时域int类型 */  
void IFFT(double *inr,double *ini,int *out)   
{  
    int i,j;  
    int deep;  
    const int N=FFT_N/2;  
    fft_complex W[N];  
    W[0].r=1;W[0].i=0;  
    W[1].r=cos(2.0*PI/FFT_N);  
    W[1].i=-1*sin(2.0*PI/FFT_N);  
    for(i=2;i<N;i++){  
        W[i]=fft_multi(W[1],W[i-1]);  
    }  
    deep=fft_fac2(FFT_N);  
    int g=1;  
    int ne=0,ge=0;  
  
    fft_complex left[FFT_N];  
    fft_complex right[FFT_N];  
    for(i=0;i<FFT_N;i++){  
        left[i].r=inr[fft_turndat(i,FFT_N)];  
        left[i].i=-1*ini[fft_turndat(i,FFT_N)];  
    }  
    fft_complex tpp;  
    int mggtmp;  
    while(1)  
    {  
        if(deep==0) break;  
        int adt=pow(2,deep-1);  
        mggtmp=pow(2,g);  
        for(i=0;i<FFT_N;i+=mggtmp){   
            ne=0;ge=0;  
            for(j=0;j<mggtmp;j++){  
                if(j<mggtmp/2){  
                    tpp=fft_multi(left[i+j+mggtmp/2],W[ne]);  
                    right[i+j]=fft_add(left[i+j],tpp);ne+=adt;  
                }else{  
                    tpp=fft_t(fft_multi(left[i+j],W[ge]));  
                    right[i+j]=fft_add(left[i+j-mggtmp/2],tpp);ge+=adt;  
                }  
            }  
        }  
        for(i=0;i<FFT_N;i++){  
            left[i]=right[i];  
        }  
        deep--;g++;  
    }  
    for(i=0;i<FFT_N;i++){  
        out[i]=fft_fi(left[i].r/FFT_N);  
    }  
}  
#endif  




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值