1. #include <stdio.h>
    2. #include <math.h>
    3. #include <stdlib.h>
    4. #define N 512 //信号长度
    5. #define M 23 //单位脉冲响应的长度
    6. #define size_x 512 //fft点数, 2的次幂
    7. #define PI 3.1415926535 //圆周率
    8. double HI[512] = { -0.00491000678664519, -0.0110940581309966, 0.00410194747948791, 0.0123959008767979, 0.0260846944086577, 0.0280068857178369, 0.0117031929574722, -0.0282213909190478, -0.0862193226866780, -0.148431590883831, -0.196291852743501, 0.785720061596288, -0.196291852743501, -0.148431590883831, -0.0862193226866780, -0.0282213909190478, 0.0117031929574722, 0.0280068857178369, 0.0260846944086577, 0.0123959008767979, 0.00410194747948791, -0.0110940581309966, -0.00491000678664519 };
    9. /*定义复数类型*/
    10. typedef struct {
    11. double real;
    12. double img;
    13. }complex;
    14. int Lenx = 4096;
    15. int M1 = M - 1; // 重叠部分的长度
    16. int L = N - 22; //不重叠部分的长度
    17. complex x[4096], * W; //输入序列,变换核
    18. complex y[4410]; //输出序列
    19. complex h[size_x], * W1; //输入滤波器,变换核
    20. complex x1[9][size_x], * W2; //输入分段,变换核
    21. complex y2[9][size_x], * W5; //输出结果,变换核
    22. /*快速傅里叶变换*/
    23. void fft(complex h[512]);
    24. void ifft_y1(complex y_1[512]);
    25. /*初始化变换核*/
    26. void initW1();
    27. void initW2();
    28. /*变址*/
    29. void change1(complex H[512]);
    30. void change5(complex y_1[512]);
    31. void add(complex, complex, complex*); //复数加法
    32. void mul(complex, complex, complex*); //复数乘法
    33. void sub(complex, complex, complex*); //复数减法
    34. void output(); //输出快速傅里叶变换的结果
    35. int main()
    36. {
    37. int i;
    38. //输出结果
    39. system("cls");
    40. printf("输出滤波后的结果\n");
    41. //输入序列
    42. for (i = 0; i < 4096; i++)
    43. {
    44. x[i].real = sin(2 * PI * 150 * i / 8000); //150Hz
    45. x[i].real += sin(2 * PI * 200 * i / 8000); //200Hz
    46. x[i].real += sin(2 * PI * 2000 * i / 8000); //2000Hz
    47. }
    48. //滤波器
    49. for (i = 0; i < size_x; i++)
    50. {
    51. if (i < M)
    52. {
    53. h[i].real = HI[i];
    54. }
    55. if (i >= M)
    56. {
    57. h[i].real = 0;
    58. }
    59. h[i].img = 0;
    60. }
    61. int K = floor((Lenx + M1 - 1) / L) + 1; //分的段数
    62. int p = (K)*L - Lenx; // 最后一段结尾补零数
    63. double zong[4432];
    64. for (i = 0; i < 4432; i++)
    65. {
    66. if (i < M1)
    67. {
    68. zong[i] = 0;
    69. }
    70. if (i >= M1 && i < 4096)
    71. {
    72. zong[i] = x[i + M1].real;
    73. }
    74. else
    75. {
    76. zong[i] = 0;
    77. }
    78. h[i].img = 0;
    79. }
    80. double Y[9][512] = { 0 };
    81. //输入函数的分段(重叠保留法)
    82. for (int j = 0; j < 512; j++)
    83. {
    84. for (int k = 0; k < 9; k++)
    85. {
    86. x1[k][j].real = zong[k * L + j];
    87. }
    88. }
    89. initW1();//调用变换核
    90. initW2();//调用变换核
    91. //对h进行DFT
    92. fft(h); //调用快速傅里叶变换
    93. for (int k = 0; k < 9; k++)
    94. {
    95. fft(x1[k]);
    96. }
    97. //h的DFT分别与x1,x2,x3的DFT相乘
    98. for (int k = 0; k < 9; k++)
    99. {
    100. for (i = 0; i < size_x; i++)
    101. {
    102. y2[k][i].real = x1[k][i].real * h[i].real - x1[k][i].img * h[i].img;
    103. y2[k][i].img = x1[k][i].img * h[i].real + x1[k][i].real * h[i].img;
    104. }
    105. }
    106. //对乘积求IDFT, 得到子序列和单位脉冲响应的循环卷积
    107. //调用快速傅里叶变换
    108. for (int k = 0; k < 9; k++)
    109. {
    110. ifft_y1(y2[k]);
    111. }
    112. //把每一段循环卷积数据前端的M-1个点去掉之后衔接起来
    113. for (i = 0; i < size_x; i++)
    114. {
    115. for (int k = 0; k < 9; k++)
    116. {
    117. y2[k][i].real = y2[k][i].real / size_x;
    118. y2[k][i].img = y2[k][i].img / size_x;
    119. }
    120. }
    121. for (i = 0; i < 4410; i++)
    122. {
    123. for (int k = 0; k < 9; k++)
    124. {
    125. if (i < (k + 1) * L && i > k * L)
    126. {
    127. y[i].real = y2[k][i + M - L * k - 1].real;
    128. y[i].img = y2[k][i + M - L * k - 1].img;
    129. }
    130. }
    131. }
    132. output();//结果输出
    133. system("pause");
    134. return 0;
    135. }
    136. //h的fft
    137. void fft(complex h[512])
    138. {
    139. int i = 0, j = 0, k = 0, l = 0;
    140. complex up, down, product;
    141. change1(h); //调用变址函数
    142. for (i = 0; i < log(size_x) / log(2); i++) /*一级蝶形运算 stage */
    143. {
    144. l = 1 << i;
    145. for (j = 0; j < size_x; j += 2 * l) /*一组蝶形运算 group,每个group的蝶形因子乘数不同*/
    146. {
    147. for (k = 0; k < l; k++) /*一个蝶形运算 每个group内的蝶形运算*/
    148. {
    149. mul(h[j + k + l], W1[size_x * k / 2 / l], &product);
    150. add(h[j + k], product, &up);
    151. sub(h[j + k], product, &down);
    152. h[j + k] = up;
    153. h[j + k + l] = down;
    154. }
    155. }
    156. }
    157. }
    158. //y1的ifft
    159. void ifft_y1(complex y_1[512])
    160. {
    161. int i = 0, j = 0, k = 0, l = 0;
    162. complex up, down, product;
    163. change5(y_1); //调用变址函数
    164. for (i = 0; i < log(size_x) / log(2); i++) /*一级蝶形运算 stage */
    165. {
    166. l = 1 << i;
    167. for (j = 0; j < size_x; j += 2 * l) /*一组蝶形运算 group,每个group的蝶形因子乘数不同*/
    168. {
    169. for (k = 0; k < l; k++) /*一个蝶形运算 每个group内的蝶形运算*/
    170. {
    171. mul(y_1[j + k + l], W2[size_x * k / 2 / l], &product);
    172. add(y_1[j + k], product, &up);
    173. sub(y_1[j + k], product, &down);
    174. y_1[j + k] = up;
    175. y_1[j + k + l] = down;
    176. }
    177. }
    178. }
    179. }
    180. /*初始化变换核,定义一个变换核,相当于旋转因子WAP*/
    181. void initW1()
    182. {
    183. int i;
    184. W1 = (complex*)malloc(sizeof(complex) * size_x); //生成变换核
    185. for (i = 0; i < size_x; i++)
    186. {
    187. W1[i].real = cos(2 * PI / size_x * i); //用欧拉公式计算旋转因子
    188. W1[i].img = -1 * sin(2 * PI / size_x * i);
    189. }
    190. }
    191. void initW2()
    192. {
    193. int i;
    194. W2 = (complex*)malloc(sizeof(complex) * size_x); //生成变换核
    195. for (i = 0; i < size_x; i++)
    196. {
    197. W2[i].real = cos(2 * PI / size_x * i); //用欧拉公式计算旋转因子
    198. W2[i].img = 1 * sin(2 * PI / size_x * i);
    199. }
    200. }
    201. /*变址计算,将输入序列的码位倒置*/
    202. void change1(complex H[512])
    203. {
    204. complex temp;
    205. unsigned short i = 0, j = 0, k = 0;
    206. double t;
    207. for (i = 0; i < size_x; i++)
    208. {
    209. k = i; j = 0;
    210. t = (log(size_x) / log(2));
    211. while ((t--) > 0) //利用按位与以及循环实现码位颠倒
    212. {
    213. j = j << 1;
    214. j |= (k & 1);
    215. k = k >> 1;
    216. }
    217. if (j > i) //将x(n)的码位互换
    218. {
    219. temp = H[i];
    220. H[i] = H[j];
    221. H[j] = temp;
    222. }
    223. }
    224. }
    225. void change5(complex y_1[512])
    226. {
    227. complex temp;
    228. unsigned short i = 0, j = 0, k = 0;
    229. double t;
    230. for (i = 0; i < size_x; i++)
    231. {
    232. k = i; j = 0;
    233. t = (log(size_x) / log(2));
    234. while ((t--) > 0) //利用按位与以及循环实现码位颠倒
    235. {
    236. j = j << 1;
    237. j |= (k & 1);
    238. k = k >> 1;
    239. }
    240. if (j > i) //将x(n)的码位互换
    241. {
    242. temp = y_1[i];
    243. y_1[i] = y_1[j];
    244. y_1[j] = temp;
    245. }
    246. }
    247. }
    248. /*输出结果*/
    249. void output()
    250. {
    251. int i;
    252. FILE* file;
    253. if ((file = fopen ("D:\\q.txt","w+" )) == NULL)//打开操作不成功
    254. {
    255. printf("The file can not be opened.\n");
    256. exit(1);//结束程序的执行
    257. }
    258. printf("The result are as follows:\n");
    259. for (i = 0; i < 4410; i++)
    260. {
    261. printf("%lf", y[i].real);
    262. //if (y[i].img >= 0.0001)printf("+%lfj\n", y[i].img);
    263. //else if (fabs(y[i].img) < 0.0001)printf("\n");
    264. //else printf("%lfj\n", y[i].img);
    265. fprintf(file, "%f,", y[i].real);
    266. }
    267. fclose(file);
    268. }
    269. void add(complex a, complex b, complex* c) //复数加法的定义
    270. {
    271. c->real = a.real + b.real;
    272. c->img = a.img + b.img;
    273. }
    274. void mul(complex a, complex b, complex* c) //复数乘法的定义
    275. {
    276. c->real = a.real * b.real - a.img * b.img;
    277. c->img = a.real * b.img + a.img * b.real;
    278. }
    279. void sub(complex a, complex b, complex* c) //复数减法的定义
    280. {
    281. c->real = a.real - b.real;
    282. c->img = a.img - b.img;
    283. }