FFT

#include <iostream>
#include <stdio.h>
#include <math.h>

//**************************************************************************************

#ifndef M_PI
    #define M_PI 3.14159265358979323846
#endif
#define DATA_LEN 64
#define SAMPLE_FREQ 1000 // Hz

unsigned char sin_data[64] = {0x7F,0x8B,0x98,0xA4,0xB0,0xBB,0xC6,0xD0,0xD9,0xE2,
    0xE9,0xEF,0xF5,0xF9,0xFC,0xFE,0xFE,0xFE,0xFC,0xF9,0xF5,0xEF,0xE9,0xE2,0xD9,0xD0,
    0xC6,0xBB,0xB0,0xA4,0x98,0x8B,0x7F,0x73,0x66,0x5A,0x4E,0x43,0x38,0x2E,0x25,0x1C,
    0x15,0x0F,0x09,0x05,0x02,0x00,0x00,0x00,0x02,0x05,0x09,0x0F,0x15,0x1C,0x25,0x2E,
    0x38,0x43,0x4E,0x5A,0x66,0x73};

typedef struct{
    double r;
    double i;
} cplx_t;


//**************************************************************************************

void cplx_exp(cplx_t *x, cplx_t *r)
{
    double expx = exp(x->r);
    r->r = expx*cos(x->i);
    r->i = expx*sin(x->i);
}

// 复数乘法
void cplx_mul(cplx_t *x, cplx_t *y, cplx_t *r)
{
    r->r = x->r*y->r-x->i*y->i;
    r->i = x->r*y->i+x->i*y->r;
}

// 比特反置
void bit_reverse(cplx_t *x, int N)
{
    unsigned int i = 0,j = 0,k = 0;
    
    cplx_t tmp;
    
    int bit_num = log(0.0+N)/log(2.0);  // 比特位数
    
    for (i=0; i<N; i++)
    {
        int t = bit_num;
        k=i;
        j=0;
        while (t--)
        {
            j <<= 1;
            j |= k&1;
            k >>= 1;
        }
        if (j>i)
        {
            tmp = x[i];
            x[i] = x[j];
            x[j] = tmp;
        }
    }
}


void fft(cplx_t *x, int N)
{
    cplx_t u,d,p,W,tmp;
    int i=0,j=0,k=0,l=0;
    
    double M = floor(log(0.0+N)/log(2.0));  // zhiqiu 换底公式
    if (log(0.0+N)/log(2.0)-M > 0)
    {
        printf("The length of x (N) must be a power of two!!!\n");
        return;
    }
    
    bit_reverse(x,N);
    
    for (i = 0; i < M; i++)
    {
        l = 1<<i;
        for (j = 0; j < N; j += 2*l)
        {
            for (k = 0; k < l; k++)
            {
                tmp.r = 0.0;
                tmp.i = -2*M_PI*k/2/l;
                cplx_exp(&tmp,&W);
                cplx_mul(&x[j+k+l],&W,&p);
                u.r = x[j+k].r+p.r;
                u.i = x[j+k].i+p.i;
                d.r = x[j+k].r-p.r;
                d.i = x[j+k].i-p.i;
                x[j+k] = u;
                x[j+k+l] = d;
            }
        }
    }
}

void ifft(cplx_t *x, int N)
{
    unsigned int i = 0;
    for (i = 0;i < N; i++)
        x[i].i = -x[i].i;
    fft(x,N);
    for (i = 0;i < N; i++)
    {
        x[i].r = x[i].r/(N+0.0);
        x[i].i = -x[i].i/(N+0.0);
    }
}



//**************************************************************************************

int main(int argc, const char * argv[])
{
    int i;
    cplx_t x[DATA_LEN];
    for (i=0;i<DATA_LEN;i++)
    {
        x[i].r = sin_data[i];
        x[i].i = 0;
    }
    
    printf("Before...\nReal\t\tImag\n");
    for (i=0; i<DATA_LEN; i++)
        printf("%f\t%f\n",x[i].r,x[i].i);
    
    fft(x, DATA_LEN);
    
    printf("\nAfter FFT...\nReal\t\tImag\n");
    for (i=0; i<DATA_LEN; i++)
        printf("%f\t%f\n",x[i].r,x[i].i);
    
    printf("\n频率\t\t幅度\t\t相位\n");
    for (i=0; i<DATA_LEN; i++)
    {
        double fudu = sqrt(x[i].r*x[i].r+x[i].i*x[i].i);
        double xiangwei = atan(x[i].i/x[i].r)*180.0/M_PI;
        if (i == 0)
            fudu /= DATA_LEN;
        else
            fudu /= DATA_LEN/2;
        printf("%f\t%f\t%f\n", (double)SAMPLE_FREQ/DATA_LEN*i, fudu, xiangwei);
    }
    
    ifft(x, DATA_LEN);
    
    printf("\nAfter IFFT...\nReal\t\tImag\n");
    for (i=0; i<DATA_LEN; i++)
        printf("%f\t%f\n",x[i].r,x[i].i);
    
    return 0;
}

 

posted @ 2014-08-18 10:04  愚茶道长  阅读(292)  评论(0编辑  收藏  举报