傅里叶变换

  1 #include <stdio.h>
  2 #include <math.h>
  3 
  4 typedef char int8_t;
  5 typedef unsigned char uint8_t;
  6 typedef unsigned short uint16_t;
  7 typedef short int16_t;
  8 
  9 #define N    64    //傅里叶变换的点数
 10 #define M     6    //蝶形运算的级数,N = 2^M
 11 #define N2    32    //N/2
 12 #define N4    16    //N/4
 13 
 14 #define PI  3.14159    //圆周率
 15 #define PI2 6.28318
 16 
 17 //定义复数结构体
 18 typedef struct                
 19 {
 20     float real;    //实部
 21     float imag;    //虚部
 22 }complex;
 23 
 24 //傅里叶变换序列,一维
 25 float pr[64] = 
 26 {
 27     1234,1285,1151,1086,896,671,541,392,368,565,762,905,987,1103,1352,1601,1593,1565,1576,1565,1379,1152,1208,1150,1086,1124,1092,945,791,561,393,291,352,596,950,1307,1490,1707,1760,1494,1351,1510,1427,1191,1156,1090,953,917,944,847,655,580,457,495,679,877,1015,1084,1256,1519,1469,1411,1423,1509
 28 };
 29 
 30 //正弦函数表
 31 float sin_table[N4 + 1];
 32 
 33 
 34 float find_sin(float x)
 35 {
 36     int i = ((int)(N * x)) >> 1;
 37 
 38     if (i > N4)        //不会超过N/2 
 39         i = N2 - i;
 40 
 41     return sin_table[i];
 42 }
 43 
 44 float find_cos(float x)
 45 {
 46     int i = ((int)(N * x)) >> 1;
 47 
 48     if (i < N4)
 49         return sin_table[N4 - i];
 50     else                //i>Npart4 && i<N/2
 51         return -sin_table[i - N4];
 52 }
 53 
 54 //dir:1 - 傅里叶变换, -1 - 傅里叶逆变换
 55 void fft(complex data[], uint8_t num, uint8_t n, int8_t dir)
 56 {
 57     uint8_t i = 0, j = 0, k = 0, m = 0, t = num - 1;
 58     float angle;
 59     complex w, temp;
 60 
 61     //变址,把自然顺序变为倒位序
 62     for (i = 0; i < t; i++)
 63     {
 64         if (i < j)
 65         {
 66             temp = data[j];
 67             data[j] = data[i];
 68             data[i] = temp;
 69         }
 70         k = N2;
 71         while (k <= j)
 72         {
 73             j -= k;
 74             k >>= 1;
 75         }
 76 
 77         j += k;    
 78     }
 79 
 80     for (i = 1; i <= n; i++)
 81     {
 82         uint8_t km, step = 1 << i;
 83         m = step >> 1;
 84 
 85         for (j = 0; j < m; j++)
 86         {
 87             angle = ((double)j) / m;
 88 
 89             if (dir == 1)
 90                 w.imag = -find_sin(angle);
 91             else if (dir == -1)
 92                 w.imag = find_sin(angle);
 93             w.real = find_cos(angle);
 94 
 95             for (k = j; k < num; k += step)
 96             {
 97                 km = k + m;
 98                 //用下面两行直接计算复数乘法,省去函数调用开销
 99                 temp.real = data[km].real * w.real - data[km].imag * w.imag;
100                 temp.imag = w.imag * data[km].real + w.real * data[km].imag;
101 
102                 data[km].real = data[k].real - temp.real;
103                 data[km].imag = data[k].imag - temp.imag;
104 
105                 data[k].real = data[k].real + temp.real;
106                 data[k].imag = data[k].imag + temp.imag;            
107             }
108         }    
109     }
110 
111     if (dir == -1)
112     {
113         for (i = 0; i < num; i++)
114         {
115             data[i].real /= num;
116         }
117     }
118 }
119 
120 
121 int main()
122 {
123     int i;
124     complex data[N];
125 
126     //初始化输入数据
127     for (i = 0; i < N; i++)
128     {
129         data[i].real = pr[i];
130         data[i].imag = 0;
131     }
132 
133     //创建正弦表
134     for (i = 0; i <= N4; i++)
135     {
136         sin_table[i] = (float)sin(PI * i /N2);
137     }
138 
139     //正变换
140     fft(data, N, M, 1);
141 
142     for (i = 0; i < N; i++)
143     {
144         printf("%.f    %.f
", data[i].real, data[i].imag);
145     }
146     printf("
");
147 
148     //波形处理
149     for (i = 5; i < N; i++)    //10:3.9Hz,11:4.3Hz
150     {
151         data[i].imag= 0;
152         data[i].real = 0;
153     }
154 
155     //逆变换
156     fft(data, N, M, -1);
157 
158     for (i = 0; i < N; i++)
159     {
160         printf("%.f    %.f
", data[i].real, data[i].imag);
161     }
162     printf("
");
163 
164     return 0;
165 }
原文地址:https://www.cnblogs.com/cmembd/p/3507402.html