FFT c++語言實現


FFT公式如下:


用圖表示整個過程:


/*
 * test.cpp
 *
 *  Created on: 2013-8-18
 *      Author: zhijian
 */




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


#define N 128            //N 點
#define RATE 128      //抽樣頻率
#define LEN 7            //1<<7=128
#define PI 3.141592653


float src[N];      //輸入
float AFreal[N];//實部
float AFimg[N];      //虛部


int upset(int a,int len){
      int sum = 0;
      while(len--){
            sum <<=1;
            if(a&1)sum++;
            a >>=1;
      }
      return sum;
}
/*
 * 公式X(k) = F1(k) + WnkF2(k)  k = 0,1,....N/2-1
 *         X(k+N/2) = F1(k) - WnkF2(k)  k = 0,1,....N/2-1
 * 我一開始老是認爲,從Wnk中的n是不會變的,因爲在上述遞歸方程中Wnk中的n並沒有縮小
 * 其實這個n也是遞歸函數的輸入參數之一 形如F(n,k) = F(n/2,k) + Wnk;
 * 換言之,Wnk中的n其實是要縮小的......
 *
 *
 */
void FFT(){
      //
      for(int i = 0;i<N;i++){
            AFreal[i]= src[upset(i,LEN)];
            AFimg[i] = 0;
      }
      float Wn = - PI;
      float tempReal,tempImg;
      for(int i = 1;i<N;i<<=1){
            int offset = 0;
            while(offset<N){
                  //two group
                  for(int j = 0;j<i;j++){
                        float tempSin = sin(Wn*j);
                        float tempCos = cos(Wn*j);
                        tempReal = tempCos * AFreal[offset+i+j]
                                    - tempSin * AFimg[offset+i+j];
                        tempImg = tempCos * AFimg[offset+i+j]
                                  + tempSin * AFreal[offset+i+j];
                        AFreal[offset+i+j] = AFreal[offset+j] - tempReal;
                        AFimg[offset+i+j] = AFimg[offset+j] - tempImg;


                        AFreal[offset+j] = AFreal[offset+j] + tempReal;
                        AFimg[offset+j] = AFimg[offset+j] + tempImg;
                  }
                  offset += (i<<1);
            }
            Wn /= 2;
      }
}


/*
 * 生成單一頻率序列點
 * A位振幅
 * f位頻率
 * derta爲偏移
 * dc爲直流分量
 */


void F(float A,int f,int derta,float dc){


      for(int i = 0;i<N;i++){
            src[i] = A*sin(2*PI*f*(derta + i)/RATE) + dc;
      }
      printf("頻率:%dHZ\n振幅:%f\n偏移:%d\n直流:%f\n",f,A,derta,dc);
      FFT();


      for(int i = 0;i<N>>1;i++)      {
            printf("%dHZ:",RATE*i/N);
            if(i==0)printf("%f\n",sqrt(AFreal[i]*AFreal[i] + AFimg[i]*AFimg[i])/N);
            else printf("%f\n",sqrt(AFreal[i]*AFreal[i] + AFimg[i]*AFimg[i])*2/N);
      }
}




int main(){
      F(23,29,14,4.5);
      return 0;
}


頻率:29HZ
振幅:23.000000
偏移:14
直流:4.500000
0HZ:4.500000
1HZ:0.000000
2HZ:0.000000
3HZ:0.000001
4HZ:0.000000
5HZ:0.000000
6HZ:0.000000
7HZ:0.000000
8HZ:0.000000
9HZ:0.000000
10HZ:0.000000
11HZ:0.000000
12HZ:0.000000
13HZ:0.000000
14HZ:0.000000
15HZ:0.000000
16HZ:0.000000
17HZ:0.000000
18HZ:0.000000
19HZ:0.000001
20HZ:0.000000
21HZ:0.000001
22HZ:0.000000
23HZ:0.000000
24HZ:0.000000
25HZ:0.000000
26HZ:0.000000
27HZ:0.000000
28HZ:0.000000
29HZ:23.000000 //幾乎只有29HZ不爲0
30HZ:0.000000
31HZ:0.000000
32HZ:0.000000
33HZ:0.000000
34HZ:0.000000
35HZ:0.000000
36HZ:0.000000
37HZ:0.000000
38HZ:0.000000
39HZ:0.000000
40HZ:0.000000
41HZ:0.000000
42HZ:0.000000
43HZ:0.000000
44HZ:0.000000
45HZ:0.000000
46HZ:0.000000
47HZ:0.000000
48HZ:0.000000
49HZ:0.000000
50HZ:0.000000
51HZ:0.000000
52HZ:0.000000
53HZ:0.000000
54HZ:0.000000
55HZ:0.000000
56HZ:0.000000
57HZ:0.000000
58HZ:0.000000
59HZ:0.000000
60HZ:0.000000
61HZ:0.000000
62HZ:0.000000
63HZ:0.000000


輸出數據

發佈了43 篇原創文章 · 獲贊 3 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章