#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的fft
void 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的ifft
void 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;
}