文章目录
- matlab 代码实现
- 方法一:
- 代码:
- 结果:
- 方法二:
- 代码:
- 结果:
- fdatool 实现
- 幅频响应
- 相频响应
- H(z) 的分子和分母系数
- C语言实现
- 代码:
- 结果:
设计数字巴特沃斯低通滤波器,设计指标如下:
通带截止频率为 200 Hz
阻带截止频率为 400 Hz
通带最大衰减为 1 db
阻带最小衰减为 30 db
采样频率为 1000 Hz
我使用了 3 种方法实现,两种是借助 matlab 实现,最后一种是完全使用 c 语言实现,3种方式得到的结果均相同,我的C语言实现可以给定任何指标来得出和 matlab 一样的结果。
我使用 C 语言实现了 matlab 的 buttord 和 bilinear 函数, buttap 函数并没有以函数形式实现,zp2tf函数 和 lp2lp函数是放在一起实现的。
目前 C 语言版本只是很潦草的实现了一下,主要实现了功能,内存的释放写的非常乱和随意。后面会多写几篇文章把 matlab 的每一个函数都以 C++ 的方式单独实现,因为 C语言要自己构造数据结构,还要很麻烦的内存管理,不适合写这些代码。
matlab 代码实现
方法一:
代码:
clear,clc,close;
%1.数字滤波器的技术指标要求
ap = 1;%通带最大衰减
as = 30;%阻带最小衰减
fp = 200;%通带截止频率
fs = 400;%阻带截止频率
Fs = 1000;%抽样间隔
T = 1/Fs;
%2.将数字指标转化成模拟滤波器指标
wp=(2*pi*fp)/Fs;
ws=(2*pi*fs)/Fs;
% 数字指标转模拟指标 预畸变,前面要× (2/T)
wap=2*Fs*tan(wp/2);
was=2*Fs*tan(ws/2);
%3.设计模拟滤波器
[N,wac]=buttord(wap,was,ap,as,'s');% N为阶数,wac为3dB截止频率, 's'表示设计的是模拟滤波器
disp("N="+N);
disp("wac="+wac);
[z,p,k]=buttap(N);% 创建巴特沃斯低通滤波器 z零点p极点k增益
[Bap,Aap]=zp2tf(z,p,k);% 由零极点和增益确定归一化Han(s)系数
[Bbs,Abs]=lp2lp(Bap,Aap,wac);% 低通到低通 计算去归一化Ha(s)
[B,A] = bilinear(Bbs,Abs,Fs); % 模拟域到数字域:双线性不变法
disp("B="+B);
disp("A="+A);
[H1,w] = freqz(B,A);% 根据H(z)求频率响应特性
%绘制数字滤波器频响幅度谱
figure(2);
f=w*Fs/(2*pi);
subplot(211);
plot(f,20*log10(abs(H1))); % 绘制幅度响应
grid on;
title('双线性变换法——巴特沃斯BLPF(幅度)');
xlabel('频率/Hz');
axis([0 500 -83 5]);
ylabel('H1幅值/dB');
subplot(212);
plot(f,unwrap(angle(H1)));% 绘制相位响应
grid on;
xlabel('频率/Hz');
ylabel('角度/Rad')
title('双线性变换法——巴特沃斯BLPF(相位)');
结果:
方法二:
代码:
%数字低通滤波器指标
fp = 200;%通带截止频率 hz
fs = 400;%阻带截止频率 hz
Ap=1; %通带最大衰减 db
As=30;%阻带最小衰减 db
Fs=1000;%采样频率 hz
%转化为模拟滤波器指标
wp=2*pi*fp/Fs;%通带截止频率 rad
ws=2*pi*fs/Fs;%阻带截止频率 rad
disp("模拟滤波器通带截止频率 = "+wp);
disp("模拟滤波器阻带截止频率 = "+ws);
%数字指标转换为模拟指标要进行预畸变,前面要× (2/T), 乘以 2/T,就是乘以 2*Fs
wap=2*Fs*tan(wp/2);
was=2*Fs*tan(ws/2);
%计算满足模拟低通滤波器指标的最低阶数 N 和 截止频率 wac
[N,wac]=buttord(wap,was,Ap,As,'s');
disp("模拟低通滤波器最低阶数 = "+N);
disp("模拟低通滤波器截止频率 = "+wac);
%计算模拟滤波器系统函数 H(s) 的分子和分母系数,H(s)就是拉普拉斯变换
%numa 是 H(s) 的分子系数,dena 是 H(s) 的分母系数
[numa,dena]=butter(N,wac,'s');
disp("模拟低通滤波器 H(s) 的分子和分母系数:");
disp("分子系数:");
disp(numa);
disp("分母系数:");
disp(dena);
%计算数字滤波器系统函数 H(z) 的分子和分母系数,H(z)就是 z 变换
%numd 是 H(z) 的分子系数,dend 是 H(z) 的分母系数
%[numd,dend]=impinvar(numa,dena,Fs);
[numd,dend]=bilinear(numa,dena,Fs);
disp("数字低通滤波器 H(s) 的分子和分母系数:");
disp("分子系数:");
disp(numd);
disp("分母系数:");
disp(dend);
%画频率响应
w=linspace(0,pi,1024);
h=freqz(numd,dend,w);
%归一化振幅
norm=max(abs(h));
numd=numd/norm;
figure(3);
subplot(311);
plot(w/pi,20*log10(abs(h/norm)));
xlabel('归一化频率');
ylabel('增益 dB');
subplot(312);
plot(w,20*log10(abs(h/norm)));
xlabel('角频率 rad');
ylabel('增益 in dB');
subplot(313);
plot(w/(2*pi)*Fs, 20*log10(abs(h/norm)));
xlabel('频率 Hz');
ylabel('增益 dB');
%computer Ap As of the designed filter
w=[wp ws];
h=freqz(numd,dend,w);
disp("h="+h);
fprintf('Ap= %.4f\n',-20*log10( abs(h(1))));
fprintf('As= %.4f\n',-20*log10( abs(h(2))));
结果:
方法一 和 方法二 得到的结果相同
fdatool 实现
幅频响应
相频响应
H(z) 的分子和分母系数
C语言实现
代码:
#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <string.h>
#define pi ((double)3.141592653589793)
struct DESIGN_SPECIFICATION
{
// 数字通带截止频率 Hz
double digital_passband_cutoff_frequency;
// 数字阻带截止频率 Hz
double digital_stopband_cutoff_frequency;
// 通带最大衰减 db
int passband_max_attenuation;
// 阻带最小衰减 db
int stopband_min_attenuation;
// 采样频率 Hz
int fs;
};
typedef struct complex
{
double real;
double img;
}Complex;
typedef struct node
{
int pow; // 指数
complex* coeff; // 系数
struct node* next;
}Node;
typedef struct linklist
{
Node* head;
}Linklist;
/*复数加法*/
int complex_add(Complex* input_1, Complex* input_2, Complex* output)
{
if (input_1 == NULL || input_2 == NULL || output == NULL)
{
return -1;
}
output->real = input_1->real + input_2->real;
output->img = input_1->img + input_2->img;
return 0;
}
/*复数乘法*/
int complex_mul(Complex* input_1, Complex* input_2, Complex* output)
{
if (input_1 == NULL || input_2 == NULL || output == NULL)
{
return -1;
}
output->real = input_1->real * input_2->real - input_1->img * input_2->img;
output->img = input_1->real * input_2->img + input_1->img * input_2->real;
return 0;
}
int node_mul(Node* input_1, Node* input_2, Node* output)
{
if (input_1 == NULL || input_2 == NULL || output == NULL)
{
return -1;
}
// 两个节点系数相乘用 mul 函数
Complex* coeff = (Complex*)malloc(sizeof(Complex));
int result = complex_mul(input_1->coeff, input_2->coeff, coeff);
if (result == -1)
{
free(coeff);
coeff = NULL;
return -1;
}
output->coeff = coeff;
// 两个节点的指数相加
int pow = input_1->pow + input_2->pow;
output->pow = pow;
return 0;
}
int insert(Linklist* list, Node* node)
{
if (list == NULL || node == NULL)
{
return -1;
}
Node* cur = list->head;
Node* pre = NULL;
while (cur != NULL)
{
// 如果当前节点的指数 大于 node 的指数,那么就要将 cur 指向下一个节点
if (cur->pow > node->pow)
{
pre = cur;
cur = cur->next;
}
// 如果当前节点的指数 小于 node 的指数,那么就要将 cur 插入到当前节点之前
else if (cur->pow < node->pow)
{
if (pre == NULL)
{
node->next = list->head;
list->head = node;
return 0;
}
pre->next = node;
node->next = cur;
return 0;
}
// 如果当前节点的指数 等于 node 的指数,那么就要将这两个节点相加
else
{
// 系数相加
int ret = complex_add(cur->coeff, node->coeff, cur->coeff);
if (ret == -1)
{
return -1;
}
free(node);
node = NULL;
return 0;
}
}
// 如果当前节点为空,说明到了链表末尾, 将节点插到前一个节点的后面
if (pre == NULL)
{
list->head = node;
return 0;
}
pre->next = node;
return 0;
}
int list_mul(Linklist* input_list1, Linklist* input_list2, Linklist* output_list)
{
if (input_list1 == NULL || input_list2 == NULL || output_list == NULL)
{
return -1;
}
// 链表1 的 每一个节点与 链表2 相乘
Node* input_1 = input_list1->head;
while (input_1 != NULL)
{
Node* input_2 = input_list2->head;
if (input_2 == NULL)
{
break;
}
while (input_2 != NULL)
{
Node* output = (Node*)malloc(sizeof(Node));
output->next = NULL;
output->coeff = NULL;
int ret = node_mul(input_1, input_2, output);
if (ret == -1)
{
return -1;
}
ret = insert(output_list, output);
if (ret == -1)
{
return -1;
}
input_2 = input_2->next;
}
input_1 = input_1->next;
}
return 0;
}
int list_add(Linklist* input_list1, Linklist* input_list2, Linklist* output_list)
{
if (input_list1 == NULL || input_list2 == NULL || output_list == NULL)
{
return -1;
}
int ret = 0;
bool insert_flag = false;
// 链表1 的 每一个节点与 链表2 相加
Node* input_1 = input_list1->head;
while (input_1 != NULL)
{
Node* input_2 = input_list2->head;
while (input_2 != NULL)
{
if (input_1->pow == input_2->pow)
{
Node* node = (Node*)malloc(sizeof(Node));
node->next = NULL;
node->coeff = (Complex*)malloc(sizeof(Complex));
ret = complex_add(input_1->coeff, input_2->coeff, node->coeff);
if (ret == -1)
{
return -1;
}
node->pow = input_1->pow;
ret = insert(output_list, node);
if (ret == -1)
{
return -1;
}
insert_flag = true;
break;
}
else
{
input_2 = input_2->next;
}
}
if (insert_flag == false)
{
// 说明遍历了 input_list2 没找到与 input_1 节点相同的 pow
// 此时就构造一个和 input_1 相同的节点,然后把它 insert 到 output_list
Node* node = (Node*)malloc(sizeof(Node));
node->next = NULL;
node->coeff = (Complex*)malloc(sizeof(Complex));
node->coeff = input_1->coeff;
node->pow = input_1->pow;
insert(output_list, node);
}
insert_flag = false;
input_1 = input_1->next;
}
return 0;
}
void destoryList(Linklist* list)
{
if (list == NULL)
{
return;
}
Node* node = list->head;
while (node != NULL)
{
// 先销毁 Node 内部的 complex
if (node->coeff != NULL)
{
free(node->coeff);
node->coeff = NULL;
}
Node* n = node;
node = node->next;
// 再销毁 Node 本身
free(n);
n = NULL;
}
}
// 构造一个Linklist,第一个节点是 s (系数为(1+j0),指数为1),第二个节点是 complex c(系数为(complex c),指数为0)
int initList(Linklist* list, Complex* c)
{
if (list == NULL || c == NULL)
{
return -1;
}
Node* node = (Node*)malloc(sizeof(Node));
node->next = NULL;
Complex* coeff = (Complex*)malloc(sizeof(Complex));
coeff->real = 1.0;
coeff->img = 0.0;
node->coeff = coeff;
node->pow = 1;
int ret = insert(list, node);
if (ret == -1)
{
return -1;
}
Node* node2 = (Node*)malloc(sizeof(Node));
node2->next = NULL;
node2->coeff = c;
node2->pow = 0;
ret = insert(list, node2);
if (ret == -1)
{
return -1;
}
return 0;
}
int copyList(Linklist* src, Linklist* dst)
{
if (dst == NULL)
{
return -1;
}
if (src == NULL)
{
return 0;
}
Node* node = src->head;
while (node != NULL)
{
Node* copy_node = (Node*)malloc(sizeof(Node));
Complex* copy_coeff = (Complex*)malloc(sizeof(Complex));
if (node->coeff == NULL)
{
return -1;
}
copy_coeff->real = node->coeff->real;
copy_coeff->img = node->coeff->img;
copy_node->coeff = copy_coeff;
copy_node->next = NULL;
copy_node->pow = node->pow;
insert(dst, copy_node);
node = node->next;
}
return 0;
}
int createElement(Complex* c, Linklist* list)
{
if (c == NULL || list == NULL)
{
return -1;
}
Node* node_s = (Node*)malloc(sizeof(Node));
node_s->next = NULL;
node_s->coeff = (Complex*)malloc(sizeof(Complex));
node_s->coeff->real = 1.0;
node_s->coeff->img = 0.0;
node_s->pow = 1;
Node* node_poly = (Node*)malloc(sizeof(Node));
node_poly->next = NULL;
node_poly->coeff = c;
node_poly->coeff->real = -1 * node_poly->coeff->real;
node_poly->coeff->img = -1 * node_poly->coeff->img;
node_poly->pow = 0;
node_s->next = node_poly;
list->head = node_s;
return 0;
}
int createElementList(int N, Linklist* input, Linklist** output)
{
if (N <=0 || input == NULL || output == NULL)
{
return -1;
}
Node* node = input->head;
int ret = 0;
for (int i = 0; i < N; i++)
{
if (output[i] == NULL)
{
return -1;
}
ret = createElement(node->coeff, output[i]);
if (ret == -1)
{
return -1;
}
node = node->next;
}
printf("===========================================\n");
for (int i = 0; i < N; i++)
{
Node* node = output[i]->head;
printf("系数:%lf %lf , 指数:%d ;", node->coeff->real, node->coeff->img, node->pow);
printf("系数:%lf %lf , 指数:%d \n", node->next->coeff->real, node->next->coeff->img, node->next->pow);
}
return 0;
}
// wap 为模拟低通滤波器通带截止频率 Hz
// was 为模拟低通滤波器阻带截止频率 Hz
// ap 为模拟低通滤波器通带最大衰减 db
// as 为模拟低通滤波器阻带最小衰减 db
// N 为需要计算的模拟巴特沃斯低通滤波器的阶数
// wc 为需要计算的模拟巴特沃斯低通滤波器的3db截止频率
bool Buttord(double wap, double was, int ap, int as, int* N, double* wc)
{
// wap was ap as 都不能 <= 0
if (wap <= 0.0001 || was <= 0.0001 || ap <= 0.0001 || as <= 0.0001 || N == NULL || wc == NULL)
{
return false;
}
double ksp = sqrt((pow(10, 0.1*as) - 1) / (pow(10, 0.1*ap) - 1));
// 计算归一化频率
double lambdasp = was / wap;
*N = ceil(log10(ksp) / log10(lambdasp));
// 使用双线性变换法,应用阻带指标 was
*wc = was * pow(pow(10, 0.1 * as) - 1, -1.0 / (2 * *N));
return true;
}
bool Butter(int N, double cutoff, Linklist* hs_den_list)
{
if (N <= 0 || hs_den_list == NULL)
{
return false;
}
bool ret = false;
Complex** poles = (Complex**)malloc(sizeof(Complex) * N);
for (int k = 0, i = 0; k <= ((2 * N) - 1); k++)
{
if (cutoff * cos(pi * 0.5 + pi * (2 * k + 1) / (2 * N)) < 0)
{
poles[i] = (Complex*)malloc(sizeof(Complex));
printf("系数:%.15lf %.15lf \n", cos(pi * 0.5 + pi * (2 * k + 1) / (2 * N)), sin(pi * 0.5 + pi * (2 * k + 1) / (2 * N)));
poles[i]->real = cutoff * cos(pi * 0.5 + pi * (2 * k + 1) / (2 * N));
poles[i]->img = cutoff * sin(pi * 0.5 + pi * (2 * k + 1) / (2 * N));
i++;
if (i == N) break;
}
}
printf("Pk = \n");
for (int i = 0; i < N; i++)
{
printf("(%.15lf + %.15lf i) \n", poles[i]->real, poles[i]->img);
}
// 构造 N 个链表(有几个极点就构造几个链表)
Linklist** listArr = (Linklist**)malloc(sizeof(Linklist) * N);
for (int i = 0; i < N; i++)
{
Linklist* list = (Linklist*)malloc(sizeof(Linklist));
list->head = NULL;
// 构造一个Linklist,第一个节点是 s (系数为(1+j0),指数为1),第二个节点是 complex c(系数为(complex c),指数为0)
initList(list, poles[i]);
listArr[i] = list;
}
printf("============= 相乘前H(s)分母的元素 =============\n");
for (int i = 0; i < N; i++)
{
Linklist* list = listArr[i];
Node* node = list->head;
printf("(系数:%.15lf , %.15f 指数:%d ;", node->coeff->real, node->coeff->img, node->pow);
node = list->head->next;
printf(" 系数:%.15lf , %.15f 指数:%d) \n", node->coeff->real, node->coeff->img, node->pow);
}
for (int i = 0; i < N; i++)
{
Node* coeff_node = listArr[i]->head->next;
if (i == 0)
{
hs_den_list->head = coeff_node;
continue;
}
Node* node = hs_den_list->head;
Node* pre = NULL;
while (node != NULL)
{
pre = node;
node = node->next;
}
pre->next = coeff_node;
}
return true;
}
// 构造 (1-z^-1)^N
int caul_1_sub_z_n(int N, Linklist* result)
{
if (N < 0 || result == NULL)
{
return -1;
}
// 先构造 1-z^-1
// 构造节点 1 ,存储在 node_1
Node* node_1 = (Node*)malloc(sizeof(Node));
node_1->next = NULL;
node_1->coeff = (Complex*)malloc(sizeof(Complex));
node_1->coeff->real = 1.0;
node_1->coeff->img = 0.0;
node_1->pow = 0;
if (N == 0)
{
result->head = node_1;
return 0;
}
// 构造节点 -z^-1 ,存储在 node_z
Node* node_z = (Node*)malloc(sizeof(Node));
node_z->next = NULL;
node_z->coeff = (Complex*)malloc(sizeof(Complex));
node_z->coeff->real = -1.0;
node_z->coeff->img = 0.0;
node_z->pow = -1;
// 节点 z^-1 连在 1 的后面,这样就成了 1 - z^-1
node_1->next = node_z;
if (N == 1)
{
result->head = node_1;
return 0;
}
// 1-z^-1 存储在链表 list_1_sub_z
Linklist* list_1_sub_z = (Linklist*)malloc(sizeof(Linklist));
list_1_sub_z->head = node_1;
// 将 1-z^-1 乘以 N 次
Linklist** mul_result = (Linklist**)malloc(sizeof(Linklist)*(N-1));
mul_result[0] = (Linklist*)malloc(sizeof(Linklist));
mul_result[0]->head = NULL;
// 计算 (1-z^-1)^2 ,结果存储在 mul_result[0]
int ret = list_mul(list_1_sub_z, list_1_sub_z, mul_result[0]);
for (int i = 0; i < (N-2); i++)
{
mul_result[i+1] = (Linklist*)malloc(sizeof(Linklist));
mul_result[i+1]->head = NULL;
ret = list_mul(mul_result[i],list_1_sub_z, mul_result[i+1]);
if (ret == -1)
{
return -1;
}
}
// 将 (1-z^-1)^N 的结果从 mul_result[N-2] 拷贝到 result
ret = copyList(mul_result[N-2], result);
for (int i = 0; i < (N - 1); i++)
{
destoryList(mul_result[i]);
mul_result[i] = NULL;
}
return ret;
}
// 构造 (1+z^-1)^N
int caul_1_add_z_n(int N, Linklist* result)
{
if (N < 0 || result == NULL)
{
return -1;
}
// 先构造 1+z^-1
// 构造节点 1 ,存储在 node_1
Node* node_1 = (Node*)malloc(sizeof(Node));
node_1->next = NULL;
node_1->coeff = (Complex*)malloc(sizeof(Complex));
node_1->coeff->real = 1.0;
node_1->coeff->img = 0.0;
node_1->pow = 0;
if (N == 0)
{
result->head = node_1;
return 0;
}
// 构造节点 z^-1 ,存储在 node_z
Node* node_z = (Node*)malloc(sizeof(Node));
node_z->next = NULL;
node_z->coeff = (Complex*)malloc(sizeof(Complex));
node_z->coeff->real = 1.0;
node_z->coeff->img = 0.0;
node_z->pow = -1;
// 节点 z^-1 连在 1 的后面,这样就成了 1+z^-1
node_1->next = node_z;
if (N == 1)
{
result->head = node_1;
return 0;
}
// 1+z^-1 存储在链表 list_1_add_z
Linklist* list_1_add_z = (Linklist*)malloc(sizeof(Linklist));
list_1_add_z->head = node_1;
// 将 1+z^-1 乘以 N 次
Linklist** mul_result = (Linklist**)malloc(sizeof(Linklist) * (N - 1));
mul_result[0] = (Linklist*)malloc(sizeof(Linklist));
mul_result[0]->head = NULL;
// 计算 (1+z^-1)^2 ,结果存储在 mul_result[0]
int ret = list_mul(list_1_add_z, list_1_add_z, mul_result[0]);
for (int i = 0; i < (N - 2); i++)
{
mul_result[i + 1] = (Linklist*)malloc(sizeof(Linklist));
mul_result[i + 1]->head = NULL;
ret = list_mul(mul_result[i], list_1_add_z, mul_result[i + 1]);
if (ret == -1)
{
return -1;
}
}
// 将 (1+z^-1)^N 的结果从 mul_result[N-2] 拷贝到 result
ret = copyList(mul_result[N - 2], result);
for (int i = 0; i < (N - 1); i++)
{
destoryList(mul_result[i]);
mul_result[i] = NULL;
}
return ret;
}
// 将 hs_den_list 中的 s 变成 (2/T)*(1-z^-1)/(1+z^-1) 就得到 H(z)
// 得到 hz_den_list 的方法是,将 hs_den_list 中的 s 变成 (2/T)*(1-z^-1)
// 得到 hz_mol_list 的方法是 计算 (1+z^-1)^N
int Bilinear(int N,
double hs_mol_coeff,
Linklist* hs_den_list,
Linklist* hz_den_list,
Linklist* hz_mol_list,
int fs)
{
if (N <= 0 || hs_den_list == NULL || hz_den_list == NULL || hz_mol_list == NULL || fs <= 0)
{
return -1;
}
int ret = 0;
//一、计算 H(z) 的分母,结果存储在 hz_den_list
Node* node = hs_den_list->head;
Linklist** mul_reult_list = (Linklist**)malloc(sizeof(Linklist) * (N+1));
int index = 0;
while (node != NULL)
{
// 1. 构造 a*(2/T)^pow,结果存放在 list_coeff
Linklist* list_coeff = (Linklist*)malloc(sizeof(Linklist));
list_coeff->head = NULL;
Complex* c = node->coeff;
Node* new_coeff_node = (Node*)malloc(sizeof(Node));
new_coeff_node->next = NULL;
Complex* new_c = (Complex*)malloc(sizeof(Complex));
Complex* tmp = (Complex*)malloc(sizeof(Complex));
tmp->img = 0.0;
// 计算 (2/T)^pow
tmp->real = pow(2.0*fs, node->pow);
// 计算 a*(2/T)^pow
ret = complex_mul(c, tmp, new_c);
printf("系数: %.15lf ,指数 = %d,新的系数:%.15lf\n", node->coeff->real, node->pow, new_c->real);
if (ret == -1)
{
free(new_coeff_node);
new_coeff_node = NULL;
free(new_c);
new_c = NULL;
free(tmp);
tmp = NULL;
return -1;
}
new_coeff_node->coeff = new_c;
new_coeff_node->pow = 0;
list_coeff->head = new_coeff_node;
// 2. 构造 (1-z^-1)^pow, 结果存放在 list_1_sub_z_pow
Linklist * list_1_sub_z_pow = (Linklist*)malloc(sizeof(Linklist));
list_1_sub_z_pow->head = NULL;
ret = caul_1_sub_z_n(node->pow, list_1_sub_z_pow);
if (ret == -1)
{
return -1;
}
// 3. 构造 (1+z^-1)^(N-pow), 结果存放在 list_1_add_z_N_pow
Linklist* list_1_add_z_N_pow = (Linklist*)malloc(sizeof(Linklist));
list_1_add_z_N_pow->head = NULL;
ret = caul_1_add_z_n(N - node->pow, list_1_add_z_N_pow);
if (ret == -1)
{
return -1;
}
// 4. 计算 a*(2/T)^pow * (1-z^-1)^pow * (1+z^-1)^(N-pow), 结果存放在 mul_reult_list[index]
Linklist* list_result_1 = (Linklist*)malloc(sizeof(Linklist));
list_result_1->head = NULL;
// 4.1 计算 a*(2/T)^pow * (1-z^-1)^pow, 结果存放在 list_result_1
ret = list_mul(list_coeff, list_1_sub_z_pow, list_result_1);
if (ret == -1)
{
return -1;
}
mul_reult_list[index] = (Linklist*)malloc(sizeof(Linklist));
mul_reult_list[index]->head = NULL;
// 4.2 计算 a*(2/T)^pow * (1-z^-1)^pow * (1+z^-1)^(N-pow), 结果存放在 mul_reult_list[index]
ret = list_mul(list_result_1, list_1_add_z_N_pow, mul_reult_list[index]);
if (ret == -1)
{
return -1;
}
Node* tmp_node = mul_reult_list[index]->head;
while (tmp_node != NULL)
{
printf("系数:%lf %lf , 指数:%d \n", tmp_node->coeff->real, tmp_node->coeff->img, tmp_node->pow);
tmp_node = tmp_node->next;
}
tmp_node = NULL;
destoryList(list_coeff);
destoryList(list_1_sub_z_pow);
destoryList(list_1_add_z_N_pow);
destoryList(list_result_1);
free(tmp);
tmp = NULL;
list_coeff = NULL;
list_1_sub_z_pow = NULL;
list_1_add_z_N_pow = NULL;
list_result_1 = NULL;
++index;
node = node->next;
}
for (int i = 0; i < (index-1); i+=2)
{
ret = list_add(mul_reult_list[i], mul_reult_list[i + 1], hz_den_list);
if (ret == -1)
{
return -1;
}
}
// 将分母各项的系数都除以最高次幂的系数,使得最高次幂对应的系数为1
node = hz_den_list->head;
double max_pow_coeff = node->coeff->real;
while (node != NULL)
{
node->coeff->real = node->coeff->real / max_pow_coeff;
node = node->next;
}
//二、计算 H(z) 的分子 (1+z^-1)^N,结果存储在 hz_mol_list
ret = caul_1_add_z_n(N, hz_mol_list);
if (ret == -1)
{
return -1;
}
// 然后给 hz_mol_list 的每一项乘以 H(s) 的分子系数 hs_mol_coeff 再除以 max_pow_coeff
node = hz_mol_list->head;
while (node != NULL)
{
node->coeff->real = node->coeff->real * hs_mol_coeff / max_pow_coeff;
node = node->next;
}
node = NULL;
mul_reult_list = NULL;
return 0;
}
int mul_element(int N, Linklist** input, Linklist* output)
{
if (N <= 0 || input == NULL || output == NULL)
{
printf("error: mul_element N <= 0 || input == NULL || output == NULL\n");
return -1;
}
if (N == 1)
{
if (output == NULL)
{
printf("error: output[0] 为 NULL,无法赋值\n");
return -1;
}
output = input[0];
return 0;
}
else
{
Linklist** mul_list_arr = (Linklist**)malloc(sizeof(Linklist)*(N-1));
mul_list_arr[0] = (Linklist*)malloc(sizeof(Linklist));
mul_list_arr[0]->head = NULL;
int ret = list_mul(input[0], input[1], mul_list_arr[0]);
if (ret == -1)
{
printf("error: list_mul(input[0], input[1], mul_list_arr[0]) \n");
return -1;
}
for (int i = 0; i < (N - 2); i++)
{
mul_list_arr[i + 1] = (Linklist*)malloc(sizeof(Linklist));
mul_list_arr[i + 1]->head = NULL;
ret = list_mul(mul_list_arr[i], input[i + 2], mul_list_arr[i + 1]);
if (ret == -1)
{
printf("error: list_mul(mul_list_arr[%d], input[%d], mul_list_arr[%d]) \n", i, i + 2, i + 1);
return -1;
}
}
ret = copyList(mul_list_arr[N-2], output);
if (ret == -1)
{
printf("error: mul_element2 copyList 出错 \n");
}
for (int i = 0; i < (N-1); i++)
{
destoryList(mul_list_arr[i]);
mul_list_arr[i] = NULL;
}
return 0;
}
}
int main(void)
{
struct DESIGN_SPECIFICATION IIR_Filter;
//Analog passband cutoff frequency
//1.数字滤波器的技术指标
IIR_Filter.digital_passband_cutoff_frequency = 200; // Hz
IIR_Filter.digital_stopband_cutoff_frequency = 400;// Hz
IIR_Filter.passband_max_attenuation = 1; // db
IIR_Filter.stopband_min_attenuation = 30;// db
IIR_Filter.fs = 1000;// Hz
//2.将数字指标转化成模拟滤波器技术指标
double analog_passband_cutoff_frequency = (2 * pi * IIR_Filter.digital_passband_cutoff_frequency) / IIR_Filter.fs;
double analog_stopband_cutoff_frequency = (2 * pi * IIR_Filter.digital_stopband_cutoff_frequency) / IIR_Filter.fs;
//printf("wp = %lf, ws = %lf\n", analog_passband_cutoff_frequency, analog_stopband_cutoff_frequency);
//3.数字指标转模拟指标 预畸变,前面要× (2/T)
double wap = 2.0 * IIR_Filter.fs * tan(analog_passband_cutoff_frequency / 2);
double was = 2.0 * IIR_Filter.fs * tan(analog_stopband_cutoff_frequency / 2);
//printf("wap = %lf, was = %lf\n", wap, was);
//4.计算巴特沃斯滤波器阶数 和 3db截止频率
int* N = (int*)malloc(sizeof(int));
double* wc = (double*)malloc(sizeof(double));
bool ret = Buttord(wap,
was,
IIR_Filter.passband_max_attenuation,
IIR_Filter.stopband_min_attenuation,
N,
wc);
if (ret == false)
{
printf("Buttord error!!! \n");
return 0;
}
printf("计算出的滤波器的最低阶数 N: %d , 3分贝截止频率为:%lf\n", *N, *wc);
printf("--------------------------------------------------------\n");
// 得到 H(s) 的分母
Linklist* hs_den_list = (Linklist*)malloc(sizeof(Linklist));
hs_den_list->head = NULL;
// 获取 hs 的极点 p0 , p1, p2, ... , pn
// 比如:
//系数:-0.765367 1.847759
//系数: - 1.847759 0.765367
//系数: - 1.847759 - 0.765367
//系数: - 0.765367 - 1.847759
// 极点的系数存储在 hs_den_list
ret = Butter(*N,
*wc,
hs_den_list);
if (ret == false)
{
printf("error: Butter 执行失败!!!\n");
}
// H(s) 的分子的系数为 (wc)^N
double hs_mol_coeff = pow(*wc, *N);
printf("hs_mol_coeff = %lf\n", hs_mol_coeff);
// 将极点转变成 (s-p1), (s-p2),...,(s-pn) 的形式
// elment_list 中的每一个链表都存放两个Node, 第一个 Node 存放 s, 第二个 Node 存放 p,
Linklist** elment_list = (Linklist**)malloc(sizeof(Linklist));
for (int i = 0; i < *N; i++)
{
elment_list[i] = (Linklist*)malloc(sizeof(Linklist));
elment_list[i]->head = NULL;
}
ret = createElementList(*N, hs_den_list, elment_list);
if (ret == -1)
{
printf("error: createElementList \n");
return 0;
}
// 将 (s-p1), (s-p2),...,(s-pn) 乘起来,结果存放在 mul_list
Linklist* mul_list = (Linklist*)malloc(sizeof(Linklist));
mul_list = (Linklist*)malloc(sizeof(Linklist));
mul_list->head = NULL;
ret = mul_element(*N, elment_list, mul_list);
if (ret == -1)
{
printf("error: mul_element 失败!!!\n");
return 0;
}
Node* node = mul_list->head;
printf("========================================\n");
printf("(s-p1)*(s-p2)*...*(s-pn)的结果 \n");
while (node != NULL)
{
printf("系数:%lf %lf , 指数:%d \n", node->coeff->real, node->coeff->img, node->pow);
node = node->next;
}
// 将 H(s) 转换成 H(z),得到 H(z) 的分子和分母,分子存储在 hz_mol_list,分母存储在 hz_den_list
Linklist* hz_den_list = (Linklist*)malloc(sizeof(Linklist));
hz_den_list->head = NULL;
Linklist* hz_mol_list = (Linklist*)malloc(sizeof(Linklist));
hz_mol_list->head = NULL;
ret = Bilinear(*N,
hs_mol_coeff,
mul_list,
hz_den_list,
hz_mol_list,
IIR_Filter.fs);
printf("H(z) 的分子:\n");
node = hz_mol_list->head;
while (node != NULL)
{
printf("系数:%.15lf %.15lf , 指数:%d \n", node->coeff->real, node->coeff->img, node->pow);
node = node->next;
}
printf("H(z) 的分母:\n");
node = hz_den_list->head;
while (node != NULL)
{
printf("系数:%.15lf %.15lf , 指数:%d \n", node->coeff->real, node->coeff->img, node->pow);
node = node->next;
}
destoryList(hs_den_list);
destoryList(hz_den_list);
destoryList(hz_mol_list);
printf("Finish \n");
return (int)0;
}
结果: