#include <stdio.h>#include <math.h> #include <stdlib.h> #define N 512 //信号长度#define M 23 //单位脉冲响应的长度 #define size_x 512 //fft点数, 2的次幂 #define PI 3.1415926535 //圆周率 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 };/*定义复数类型*/typedef struct { double real; double img;}complex;int Lenx = 4096;int M1 = M - 1; // 重叠部分的长度int L = N - 22; //不重叠部分的长度complex x[4096], * W; //输入序列,变换核complex y[4410]; //输出序列complex h[size_x], * W1; //输入滤波器,变换核 complex x1[9][size_x], * W2; //输入分段,变换核 complex y2[9][size_x], * W5; //输出结果,变换核/*快速傅里叶变换*/void fft(complex h[512]);void ifft_y1(complex y_1[512]);/*初始化变换核*/void initW1();void initW2();/*变址*/void change1(complex H[512]);void change5(complex y_1[512]);void add(complex, complex, complex*); //复数加法 void mul(complex, complex, complex*); //复数乘法 void sub(complex, complex, complex*); //复数减法 void output(); //输出快速傅里叶变换的结果 int main(){ int i; //输出结果 system("cls"); printf("输出滤波后的结果\n"); //输入序列 for (i = 0; i < 4096; i++) { x[i].real = sin(2 * PI * 150 * i / 8000); //150Hz x[i].real += sin(2 * PI * 200 * i / 8000); //200Hz x[i].real += sin(2 * PI * 2000 * i / 8000); //2000Hz } //滤波器 for (i = 0; i < size_x; i++) { if (i < M) { h[i].real = HI[i]; } if (i >= M) { h[i].real = 0; } h[i].img = 0; } int K = floor((Lenx + M1 - 1) / L) + 1; //分的段数 int p = (K)*L - Lenx; // 最后一段结尾补零数 double zong[4432]; for (i = 0; i < 4432; i++) { if (i < M1) { zong[i] = 0; } if (i >= M1 && i < 4096) { zong[i] = x[i + M1].real; } else { zong[i] = 0; } h[i].img = 0; } double Y[9][512] = { 0 }; //输入函数的分段(重叠保留法) for (int j = 0; j < 512; j++) { for (int k = 0; k < 9; k++) { x1[k][j].real = zong[k * L + j]; } } initW1();//调用变换核 initW2();//调用变换核 //对h进行DFT fft(h); //调用快速傅里叶变换 for (int k = 0; k < 9; k++) { fft(x1[k]); } //h的DFT分别与x1,x2,x3的DFT相乘 for (int k = 0; k < 9; k++) { for (i = 0; i < size_x; i++) { y2[k][i].real = x1[k][i].real * h[i].real - x1[k][i].img * h[i].img; y2[k][i].img = x1[k][i].img * h[i].real + x1[k][i].real * h[i].img; } } //对乘积求IDFT, 得到子序列和单位脉冲响应的循环卷积 //调用快速傅里叶变换 for (int k = 0; k < 9; k++) { ifft_y1(y2[k]); } //把每一段循环卷积数据前端的M-1个点去掉之后衔接起来 for (i = 0; i < size_x; i++) { for (int k = 0; k < 9; k++) { y2[k][i].real = y2[k][i].real / size_x; y2[k][i].img = y2[k][i].img / size_x; } } for (i = 0; i < 4410; i++) { for (int k = 0; k < 9; k++) { if (i < (k + 1) * L && i > k * L) { y[i].real = y2[k][i + M - L * k - 1].real; y[i].img = y2[k][i + M - L * k - 1].img; } } } output();//结果输出 system("pause"); return 0;}//h的fftvoid fft(complex h[512]){ int i = 0, j = 0, k = 0, l = 0; complex up, down, product; change1(h); //调用变址函数 for (i = 0; i < log(size_x) / log(2); i++) /*一级蝶形运算 stage */ { l = 1 << i; for (j = 0; j < size_x; j += 2 * l) /*一组蝶形运算 group,每个group的蝶形因子乘数不同*/ { for (k = 0; k < l; k++) /*一个蝶形运算 每个group内的蝶形运算*/ { mul(h[j + k + l], W1[size_x * k / 2 / l], &product); add(h[j + k], product, &up); sub(h[j + k], product, &down); h[j + k] = up; h[j + k + l] = down; } } }}//y1的ifftvoid ifft_y1(complex y_1[512]){ int i = 0, j = 0, k = 0, l = 0; complex up, down, product; change5(y_1); //调用变址函数 for (i = 0; i < log(size_x) / log(2); i++) /*一级蝶形运算 stage */ { l = 1 << i; for (j = 0; j < size_x; j += 2 * l) /*一组蝶形运算 group,每个group的蝶形因子乘数不同*/ { for (k = 0; k < l; k++) /*一个蝶形运算 每个group内的蝶形运算*/ { mul(y_1[j + k + l], W2[size_x * k / 2 / l], &product); add(y_1[j + k], product, &up); sub(y_1[j + k], product, &down); y_1[j + k] = up; y_1[j + k + l] = down; } } }}/*初始化变换核,定义一个变换核,相当于旋转因子WAP*/void initW1(){ int i; W1 = (complex*)malloc(sizeof(complex) * size_x); //生成变换核 for (i = 0; i < size_x; i++) { W1[i].real = cos(2 * PI / size_x * i); //用欧拉公式计算旋转因子 W1[i].img = -1 * sin(2 * PI / size_x * i); }}void initW2(){ int i; W2 = (complex*)malloc(sizeof(complex) * size_x); //生成变换核 for (i = 0; i < size_x; i++) { W2[i].real = cos(2 * PI / size_x * i); //用欧拉公式计算旋转因子 W2[i].img = 1 * sin(2 * PI / size_x * i); }}/*变址计算,将输入序列的码位倒置*/void change1(complex H[512]){ complex temp; unsigned short i = 0, j = 0, k = 0; double t; for (i = 0; i < size_x; i++) { k = i; j = 0; t = (log(size_x) / log(2)); while ((t--) > 0) //利用按位与以及循环实现码位颠倒 { j = j << 1; j |= (k & 1); k = k >> 1; } if (j > i) //将x(n)的码位互换 { temp = H[i]; H[i] = H[j]; H[j] = temp; } }}void change5(complex y_1[512]){ complex temp; unsigned short i = 0, j = 0, k = 0; double t; for (i = 0; i < size_x; i++) { k = i; j = 0; t = (log(size_x) / log(2)); while ((t--) > 0) //利用按位与以及循环实现码位颠倒 { j = j << 1; j |= (k & 1); k = k >> 1; } if (j > i) //将x(n)的码位互换 { temp = y_1[i]; y_1[i] = y_1[j]; y_1[j] = temp; } }}/*输出结果*/void output(){ int i; FILE* file; if ((file = fopen ("D:\\q.txt","w+" )) == NULL)//打开操作不成功 { printf("The file can not be opened.\n"); exit(1);//结束程序的执行 } printf("The result are as follows:\n"); for (i = 0; i < 4410; i++) { printf("%lf", y[i].real); //if (y[i].img >= 0.0001)printf("+%lfj\n", y[i].img); //else if (fabs(y[i].img) < 0.0001)printf("\n"); //else printf("%lfj\n", y[i].img); fprintf(file, "%f,", y[i].real); } fclose(file);}void add(complex a, complex b, complex* c) //复数加法的定义 { c->real = a.real + b.real; c->img = a.img + b.img;}void mul(complex a, complex b, complex* c) //复数乘法的定义 { c->real = a.real * b.real - a.img * b.img; c->img = a.real * b.img + a.img * b.real;}void sub(complex a, complex b, complex* c) //复数减法的定义 { c->real = a.real - b.real; c->img = a.img - b.img;}