北邮22信通一枚~
跟随课程进度更新北邮信通院DSP的笔记、代码和文章,欢迎关注~
获取更多文章,请访问专栏:
承接上一篇博客
北邮22级信通院DSP:IIR_DF系统1.0版:用C++程序实现给定参数下四种滤波器的Butterworth模拟滤波器设计:给定上下截频和衰减系数求H(p)和H(s)-CSDN博客
在原有的基础上,新增了“选用不同方法设计IIR_DF”的功能,同时对对可视化进行了补充完善。
先来展示运行效果
目录
1.5H(s)的显示(double_to_string)(已有未动)
1.8综合四种滤波器算法complication()(改进)
一、核心算法
1.1判断滤波器类型(已有未动)
对滤波器的类型,新增了一项UN_KNOWN,作用是:如果用户提前知道了滤波器类型,可以直接在输入端输入,省去了判断滤波器类型的麻烦;如果不知道就输入UNKNOWN,程序再通过参数帮用户判断不迟。
#define ERROR 0
#define IS_LP 1
#define IS_HP 2
#define IS_BP 3
#define IS_BS 4
#define UN_KNOWN 5//新增
#define USING_IIM 6
#define USING_BLT 7
int filter_type;
int operate_type;
typedef long double ld;
//判断选通滤波器类型
int check_types(ld p1, ld p2, ld s1, ld s2)
{
if (p1 > p2 || s1 > s2 || s1 == p2 ||
s2 == p1 || s1 == s2 || p1 == p2)
return ERROR;
if (s1 * p1 != 0)
return (p2 > p1 && s2 > s1 && p1 != s1 && p2 != s2) ?
((p1 > s1) ? IS_BP : IS_BS) : (ERROR);
else
return (s2 != p2) ? (s2 < p2 ? IS_HP : IS_LP) : (ERROR);
}
1.2 带通滤波器BP(已有未动)
#define ERROR 0
#define IS_LP 1
#define IS_HP 2
#define IS_BP 3
#define IS_BS 4
#define UN_KNOWN 5
#define USING_IIM 6
#define USING_BLT 7
int filter_type;
int operate_type;
typedef long double ld;
void BP(ld& p1, ld& p2, ld& Ap, ld& s1, ld& s2, ld& As)
{
ld center = p1*p2;//保持通带
cout << "通带中心频率为:" << sqrt(center) << "Hz;" << endl;
//非中心对称改为中心对称
if (p1 * p2 != s1 * s2)
((center / s2) > s1) ? (s1 = (center / s2)) : (s2 = (center / s1));
//计算N的值
ld lambda_p = 1;
ld lambda_s = (s2 - s1) / (p2 - p1);
cout << "lambda_s的计算结果为:lambda_s = " << lambda_s << ";" << endl;
double temp_1 = log10((pow(10, 0.1 * As) - 1) / (pow(10, 0.1 * Ap) - 1));
double temp_2 = log10(lambda_s / lambda_p);
int N = ceil(temp_1 / (2 * temp_2));
//根据N的值查表得到低通滤波器归一化传输函数Hlp(p)分母表达式
cout << "butterworth滤波器的阶数为:" << N << ";" << endl;
show(N, "p");
}
1.3带阻滤波器BS(已有未动)
#define ERROR 0
#define IS_LP 1
#define IS_HP 2
#define IS_BP 3
#define IS_BS 4
#define UN_KNOWN 5
#define USING_IIM 6
#define USING_BLT 7
int filter_type;
int operate_type;
typedef long double ld;
void BS(ld& p1, ld& p2, ld& Ap, ld& s1, ld& s2, ld& As)
{
ld center = s1 * s2;//保持通带
cout << "通带中心频率为:" << sqrt(center) << "Hz;" << endl;
//非中心对称改为中心对称
if (p1 * p2 != s1 * s2)
((center / p2) > p1) ? (p1 = (center / p2)) : (p2 = (center / p1));
//计算N的值
ld lambda_p = 1;
ld lambda_s = (p2 - p1)/ (s2 - s1);
cout << "lambda_s的计算结果为:lambda_s=" << lambda_s << ";" << endl;
double temp_1 = log10((pow(10, 0.1 * As) - 1) / (pow(10, 0.1 * Ap) - 1));
double temp_2 = log10(lambda_s / lambda_p);
int N = ceil(temp_1 / (2 * temp_2));
//根据N的值查表得到低通滤波器归一化传输函数Hlp(p)分母表达式
cout << "butterworth滤波器的阶数为:" << N << ";" << endl;
show(N, "p");
}
1.4展示函数show()(已有未动)
#define ERROR 0
#define IS_LP 1
#define IS_HP 2
#define IS_BP 3
#define IS_BS 4
#define UN_KNOWN 5
#define USING_IIM 6
#define USING_BLT 7
int filter_type;
int operate_type;
typedef long double ld;
double box[7][8] =
{
{1.0000,1.0000,0.00000,0.00000,0.00000,0.00000,0.0000,0.0000},
{1.0000,1.4140,1.00000,0.00000,0.00000,0.00000,0.0000,0.0000},
{1.0000,2.0000,2.00000,1.00000,0.00000,0.00000,0.0000,0.0000},
{1.0000,2.6131,3.41420,2.61310,1.00000,0.00000,0.0000,0.0000},
{1.0000,3.2361,5.23610,5.23610,6.23610,1.00000,0.0000,0.0000},
{1.0000,3.8637,7.46410,9.14160,7.46410,3.86370,1.0000,0.0000},
{1.0000,4.4940,10.0978,14.5918,14.5918,10.0978,4.4940,1.0000}
};
void show(int N, string p)
{
cout << "1 / ( ";
for (int i = 7; i >= 0; i--)
{
if(box[N - 1][i])//系数不为0时有输出
{
if (box[N - 1][i] != 1)
cout << box[N - 1][i] << "*";
switch (i)
{
case 0:
cout << 1; break;
case 1:
cout << p << " + "; break;
default:
cout << p << "^" << i << " + "; break;
}
}
}
cout << " );" << endl;
}
1.5H(s)的显示(double_to_string)(已有未动)
1.5.1to_string方法
#include<cstring>
string is_p_1(int type, ld B, ld& center)
{
string output;
if (type == IS_LP)
output = "(s/" + to_string(B) + ")";
else if (type == IS_HP)
output = "(" + to_string(B) + "/s";
else if (type == IS_BP)
output = "((s^2+" + to_string(pow(center, 2)) + ")/" +
"(" + to_string(B) + "*s" + "))";
else if (type == IS_BS)
output = "((" + to_string(B) + "*s" + ")/" +
"(s^2+" + to_string(pow(center, 2)) + "))";
else
output = "error";
return output;
}
1.5.2 ostringstream方法
#include <sstream>
#include<iomanip>
using namespace std;
auto format_doble_value(double val, int fixed) {
std::ostringstream oss;
oss << std::setprecision(fixed) << val;
return oss.str();
}
string is_p(int type, ld B, ld& center)
{
string output;
if (type == IS_LP)
output = "(s/" + format_doble_value(B, define_setpercision) + ")";
else if (type == IS_HP)
output = "(" + format_doble_value(B, define_setpercision) + "/s";
else if (type == IS_BP)
output = "((s^2+" + format_doble_value(pow(center, 2), define_setpercision) + ")/" +
"(" + format_doble_value(B, define_setpercision) + "*s" + "))";
else if (type == IS_BS)
output = "((" + format_doble_value(B, define_setpercision) + "*s" + ")/" +
"(s^2+" + format_doble_value(pow(center, 2), define_setpercision) + "))";
else
output = "error";
return output;
}
1.6选用不同方法后对频率的处理change()(新增)
因为选用不同的滤波器设计导致对频率的处理不同,所以应该增加判断,区分处理。
如果选用的是双线性变换法,应该进行预畸变处理。程序中对通带阻带的上下截频都进行了预畸变处理:如果是低通或高通,原本是0的数字频率经预处理后还是0不变,归一化了。
如果选用的是冲激响应不变法,应该判断想要实现的IIR_DF能否应用此方法设计。由于冲击相应不变法涉及频带混叠的风险,因此只能用于设计低通和带通滤波器。如果程序发现使用冲激响应不变法后却要设计高通和带阻滤波器,就会报错终止。
#define ERROR 0
#define IS_LP 1
#define IS_HP 2
#define IS_BP 3
#define IS_BS 4
#define UN_KNOWN 5
#define USING_IIM 6
#define USING_BLT 7
int filter_type;
int operate_type;
typedef long double ld;
void change()
{
p1 *= 2 * PI; p2 *= 2 * PI; s1 *= 2 * PI; s2 *= 2 * PI;
//如果是双线性变换法,需要进行预畸变处理。
//如果是低通或高通,原本是0的数字频率经预处理后还是0不变,归一化了。
if (operate_type == USING_BLT)
{
p1 = 2 * fs * tan(0.5 * p1 / fs);
p2 = 2 * fs * tan(0.5 * p2 / fs);
s1 = 2 * fs * tan(0.5 * s1 / fs);
s2 = 2 * fs * tan(0.5 * s2 / fs);
}
//如果是冲激响应不变法,则不用进行预畸变处理。
//由于冲激响应不变法不能处理高通和带阻滤波器,
//所以当程序判断为高通或带阻滤波器时,应报错。
filter_type = check_types(p1, p2, s1, s2);
if (operate_type == USING_IIM)
if (filter_type == IS_HP || filter_type == IS_BS)
throw"error:冲激响应不变法不能用于设计高通或带阻滤波器";
}
1.7自主输入函数input()(改进)
对input的修改,主要是对系统的可视化和智能化进行优化。
对于滤波器的新增类型UN_KNOWN的作用,前文已述。
新增USING_IIM和USING_BLT两个宏,分别对应选用了冲激响应不变法还是选用双线性变换法来设局滤波器。
输入界面:
首先,让用户输入想要使用的设计方法。
第二步,让用户输入想要设计的数字滤波器类型。如果用户只有上下截频和衰减的参量但不知道是什么滤波器,也可以输入UNKNOWN,程序会自主帮用户判定。
第三步,让用户输入上下截频和衰减参数。
因为在模拟域中,低通滤波器的通带和阻带下截止频率均趋于负无穷,所以在数字域中,低通滤波器的通带和阻带下截止频率均趋于0,所以如果是低通滤波器,程序默认在通带和阻带下截频位置(p1、s1)键入0;
同理,
因为在模拟域中,高通滤波器的通带和阻带上截止频率均趋于正无穷,所以在数字域中,高通滤波器的通带和阻带上截止频率均趋于0,所以如果是低通滤波器,程序默认在通带和阻带上截频位置(p2、s2)键入0;
如果用户在第二步输入的是高通或低通滤波器,程序会在相应的(p2,s2)或(p1,s1)自动填充零值。其他情况需要用户全部自行输入。
#define ERROR 0
#define IS_LP 1
#define IS_HP 2
#define IS_BP 3
#define IS_BS 4
#define UN_KNOWN 5
#define USING_IIM 6
#define USING_BLT 7
int filter_type;
int operate_type;
typedef long double ld;
void input()
{
string get_input;
cout << endl << "欢迎登录IIR_DF设计系统!" << endl;
cout << endl << "我们需要获取您的一些数据要求~" << endl;
cout << endl << "请问您想使用哪种方法设计IID_DF?" << endl;
cout << "如果想使用冲激响应不变法,请输入iim;\
\n如果想使用双线性不变法,请输入blt:" << endl;
cin >> get_input;
(get_input == "iim" || get_input == "blt") ?
(operate_type = (get_input == "iim") ? USING_IIM : USING_BLT) :
(throw "error:输入错误!");
cout << endl << "下面我们将获取您希望最终得到的数字指标。" << endl;
cout << "请输入您想设计的数字滤波器类型(包括LP、HP、BP、BS、UNKNOWN):";
cin >> get_input;
if (get_input == "LP")filter_type = IS_LP;
else if (get_input == "HP")filter_type = IS_HP;
else if (get_input == "BP")filter_type = IS_BP;
else if (get_input == "BS")filter_type = IS_BS;
else if (get_input == "UNKNOWN") filter_type == UN_KNOWN;
else { cout << "error:输入错误!"; exit(0); }
cout << endl << "下面是关于键入频率和衰减系数的指标的一些声明。\n\
声明:\n\
因为在模拟域中,低通滤波器的通带和阻带下截止频率均趋于负无穷,\n\
所以在数字域中,低通滤波器的通带和阻带下截止频率均趋于0,\n\
所以如果是低通滤波器,程序默认在通带和阻带下截频位置(p1、s1)键入0;\n\
同理,\n\
因为在模拟域中,高通滤波器的通带和阻带上截止频率均趋于正无穷,\n\
所以在数字域中,高通滤波器的通带和阻带上截止频率均趋于0,\n\
所以如果是低通滤波器,程序默认在通带和阻带上截频位置(p2、s2)键入0;" << endl;
cout << endl << "请输入取样频率(Hz):"; cin >> fs;
cout << endl << "请输入通带起始频率p1(Hz):";
if (filter_type == IS_LP) { p1 = 0; cout << p1; }else cin >> p1;
cout << endl << "请输入通带截止频率p2(Hz):";
if (filter_type == IS_HP) { p2 = 0; cout << p2; }else cin >> p2;
cout << endl << "请输入通带衰减系数(dB):"; cin >> Ap;
cout << endl << "请输入阻带起始频率s1(Hz):";
if (filter_type == IS_LP) { s1 = 0; cout << s1; }else cin >> s1;
cout << endl << "请输入阻带截止频率s2(Hz):";
if (filter_type == IS_HP) { s2 = 0; cout << s2; }else cin >> s2;
cout << endl << "请输入阻带衰减系数(dB):"; cin >> As;
cout << endl;
cout << "运算结果为:" << endl;
}
1.8综合四种滤波器算法complication()(改进)
首先,执行input函数,传入设计的滤波器类型、选用方法通阻带上下截频和衰减参数,并根据参数判断滤波器的存在性,如果不存在该种滤波器,报错并终止程序;
第二步,按用户所需按方法,对通阻带上下截频参量做相应处理,对方法局限性做判断;
第三步,计算中心频率center^2。对选通滤波器(高通滤波器和低通滤波器的合称)来说,由于侧重点不同,对中心频率的计算是不同的。带通滤波器(BP)center^2 = p1 * p2,而带阻滤波器(BS)应为center^2 = s1 * s2。
第四步,如果给定的通带阻带的上下截频不是自然几何对称的话,根据滤波器类型和中心频率修正相应的参数。
第五步,计算λs的值。由于带通滤波器λs的计算方式为λs = ((s2 - s1) / (p2 - p1)),而低通滤波器的为s/p,相当于低通滤波器是s1=p1=0的情况,λs的值可以用同一个式子处理;同理带阻滤波器和高通滤波器(s2=p2=0)的λs的值也可以共用带阻滤波器的式子处理λs = ((p2 - p1) / (s2 - s1))。
调用cmath头文件中的向上取整函数ceil,求得N值。
第六步,展示H(p)和H(s),详见1.5展示函数show()和1.6H(s)的显示(double_to_string)
#define ERROR 0
#define IS_LP 1
#define IS_HP 2
#define IS_BP 3
#define IS_BS 4
#define UN_KNOWN 5
#define USING_IIM 6
#define USING_BLT 7
int filter_type;
int operate_type;
typedef long double ld;
void compilation()
{
ld center = 0;
input();
change();
//判断滤波器类型
cout << endl << "该滤波器的类型为";
switch (check_types(p1, p2, s1, s2))
{
case IS_LP:cout << "低通滤波器;" << endl; break;
case IS_HP:cout << "高通滤波器;" << endl; break;
case IS_BP:cout << "带通滤波器;" << endl; break;
case IS_BS:cout << "带阻滤波器;" << endl; break;
default:
throw"error:参数不符合滤波器特征"; break;
}
cout << endl << "参量下滤波器存在性与对应方法局限性自检成功…" << endl;
center = (check_types(p1, p2, s1, s2) == IS_BP) ? p1 * p2 : s1 * s2;
if (sqrt(center))
cout << endl << "通带中心频率为:" << sqrt(center) << "Hz;" << endl;
//非几何对称改为几何对称
if (p1 * p2 != s1 * s2)
(check_types(p1, p2, s1, s2) == IS_BP) ?
(((center / s2) > s1) ? (s1 = (center / s2)) : (s2 = (center / s1))) :
(((center / p2) > p1) ? (p1 = (center / p2)) : (p2 = (center / p1)));
//计算N的值
ld lambda_p = 1;
ld lambda_s = (check_types(p1, p2, s1, s2) == IS_BP
|| check_types(p1, p2, s1, s2) == IS_LP) ?
((s2 - s1) / (p2 - p1)) : ((p2 - p1) / (s2 - s1));
cout << endl << "归一化截频lambda_s的计算结果为:lambda_s = " << lambda_s << ";" << endl;
double temp_1 = log10((pow(10, 0.1 * As) - 1) / (pow(10, 0.1 * Ap) - 1));
double temp_2 = log10(lambda_s / lambda_p);
int N = ceil(temp_1 / (2 * temp_2));
//根据N的值查表得到低通滤波器归一化传输函数Hlp(p)分母表达式
cout << endl << "butterworth滤波器的阶数为N = " << N << ";" << endl;
cout << endl << "归一化传输函数为:H(p) = ";
show(N, "p");
string show_next_level = is_p(check_types(p1, p2, s1, s2), p2 - p1, center);
cout << endl << "传输函数H(s) = ";
show(N, show_next_level);
}
二、代码部分
2.1总体代码
#include<iostream>
#include<cmath>
#include<cstring>
#include <sstream>
#include<iomanip>
using namespace std;
#define ERROR 0
#define IS_LP 1
#define IS_HP 2
#define IS_BP 3
#define IS_BS 4
#define UN_KNOWN 5
#define USING_IIM 6
#define USING_BLT 7
typedef long double ld;
const double PI = acos(-1.0);
const int define_setpercision = 5;
double box[7][8] =
{
{1.0000,1.0000,0.00000,0.00000,0.00000,0.00000,0.0000,0.0000},
{1.0000,1.4140,1.00000,0.00000,0.00000,0.00000,0.0000,0.0000},
{1.0000,2.0000,2.00000,1.00000,0.00000,0.00000,0.0000,0.0000},
{1.0000,2.6131,3.41420,2.61310,1.00000,0.00000,0.0000,0.0000},
{1.0000,3.2361,5.23610,5.23610,6.23610,1.00000,0.0000,0.0000},
{1.0000,3.8637,7.46410,9.14160,7.46410,3.86370,1.0000,0.0000},
{1.0000,4.4940,10.0978,14.5918,14.5918,10.0978,4.4940,1.0000}
};
int filter_type;
int operate_type;
ld p1, p2, s1, s2, Ap, As, fs;
//标准输出
void show(int N, string p)
{
cout << "1 / ( ";
for (int i = 7; i >= 0; i--)
{
if (box[N - 1][i])//系数不为0时有输出
{
if (box[N - 1][i] != 1)
cout << box[N - 1][i] << "*";
switch (i)
{
case 0:
cout << 1; break;
case 1:
cout << p << " + "; break;
default:
cout << p << "^" << i << " + "; break;
}
}
}
cout << " );" << endl;
}
//判断选通滤波器类型
int check_types(ld p1, ld p2, ld s1, ld s2)
{
if (p1 > p2 || s1 > s2 || s1 == p2 ||
s2 == p1 || s1 == s2 || p1 == p2)
return ERROR;
if (s1 * p1 != 0)
return (p2 > p1 && s2 > s1 && p1 != s1 && p2 != s2) ?
((p1 > s1) ? IS_BP : IS_BS) : (ERROR);
else
return (s2 != p2) ? (s2 < p2 ? IS_HP : IS_LP) : (ERROR);
}
void change()
{
p1 *= 2 * PI; p2 *= 2 * PI; s1 *= 2 * PI; s2 *= 2 * PI;
//如果是双线性变换法,需要进行预畸变处理。
//如果是低通或高通,原本是0的数字频率经预处理后还是0不变,归一化了。
if (operate_type == USING_BLT)
{
p1 = 2 * fs * tan(0.5 * p1 / fs);
p2 = 2 * fs * tan(0.5 * p2 / fs);
s1 = 2 * fs * tan(0.5 * s1 / fs);
s2 = 2 * fs * tan(0.5 * s2 / fs);
}
//如果是冲激响应不变法,则不用进行预畸变处理。
//由于冲激响应不变法不能处理高通和带阻滤波器,
//所以当程序判断为高通或带阻滤波器时,应报错。
filter_type = check_types(p1, p2, s1, s2);
if (operate_type == USING_IIM)
if (filter_type == IS_HP || filter_type == IS_BS)
throw"error:冲激响应不变法不能用于设计高通或带阻滤波器";
}
auto format_double_value(double val, int fixed) {
std::ostringstream oss;
oss << std::setprecision(fixed) << val;
return oss.str();
}
string is_p(int type, ld B, ld& center)
{
string output;
if (type == IS_LP)
output = "(s/" + format_double_value(B, define_setpercision) + ")";
else if (type == IS_HP)
output = "(" + format_double_value(B, define_setpercision) + "/s";
else if (type == IS_BP)
output = "((s^2+" + format_double_value(pow(center, 2), define_setpercision) + ")/" +
"(" + format_double_value(B, define_setpercision) + "*s" + "))";
else if (type == IS_BS)
output = "((" + format_double_value(B, define_setpercision) + "*s" + ")/" +
"(s^2+" + format_double_value(pow(center, 2), define_setpercision) + "))";
else
output = "error";
return output;
}
string is_p_1(int type, ld B, ld& center)
{
string output;
if (type == IS_LP)
output = "(s/" + to_string(B) + ")";
else if (type == IS_HP)
output = "(" + to_string(B) + "/s";
else if (type == IS_BP)
output = "((s^2+" + to_string(pow(center, 2)) + ")/" +
"(" + to_string(B) + "*s" + "))";
else if (type == IS_BS)
output = "((" + to_string(B) + "*s" + ")/" +
"(s^2+" + to_string(pow(center, 2)) + "))";
else
output = "error";
return output;
}
//带通滤波器算法
void BP(ld& p1, ld& p2, ld& Ap, ld& s1, ld& s2, ld& As)
{
ld center = p1*p2;//保持通带
cout << "通带中心频率为:" << sqrt(center) << "Hz;" << endl;
//非中心对称改为中心对称
if (p1 * p2 != s1 * s2)
((center / s2) > s1) ? (s1 = (center / s2)) : (s2 = (center / s1));
//计算N的值
ld lambda_p = 1;
ld lambda_s = (s2 - s1) / (p2 - p1);
cout << "lambda_s的计算结果为:lambda_s = " << lambda_s << ";" << endl;
double temp_1 = log10((pow(10, 0.1 * As) - 1) / (pow(10, 0.1 * Ap) - 1));
double temp_2 = log10(lambda_s / lambda_p);
int N = ceil(temp_1 / (2 * temp_2));
//根据N的值查表得到低通滤波器归一化传输函数Hlp(p)分母表达式
cout << "butterworth滤波器的阶数为:" << N << ";" << endl;
show(N, "p");
}
void BS(ld& p1, ld& p2, ld& Ap, ld& s1, ld& s2, ld& As)
{
ld center = s1 * s2;//保持通带
cout << "通带中心频率为:" << sqrt(center) << "Hz;" << endl;
//非中心对称改为中心对称
if (p1 * p2 != s1 * s2)
((center / p2) > p1) ? (p1 = (center / p2)) : (p2 = (center / p1));
//计算N的值
ld lambda_p = 1;
ld lambda_s = (p2 - p1)/ (s2 - s1);
cout << "lambda_s的计算结果为:lambda_s=" << lambda_s << ";" << endl;
double temp_1 = log10((pow(10, 0.1 * As) - 1) / (pow(10, 0.1 * Ap) - 1));
double temp_2 = log10(lambda_s / lambda_p);
int N = ceil(temp_1 / (2 * temp_2));
//根据N的值查表得到低通滤波器归一化传输函数Hlp(p)分母表达式
cout << "butterworth滤波器的阶数为:" << N << ";" << endl;
show(N, "p");
}
void input()
{
string get_input;
cout << endl << "欢迎登录IIR_DF设计系统!" << endl;
cout << endl << "我们需要获取您的一些数据要求~" << endl;
cout << endl << "请问您想使用哪种方法设计IID_DF?" << endl;
cout << "如果想使用冲激响应不变法,请输入iim;\
\n如果想使用双线性不变法,请输入blt:" << endl;
cin >> get_input;
(get_input == "iim" || get_input == "blt") ?
(operate_type = (get_input == "iim") ? USING_IIM : USING_BLT) :
(throw "error:输入错误!");
cout << endl << "下面我们将获取您希望最终得到的数字指标。" << endl;
cout << "请输入您想设计的数字滤波器类型(包括LP、HP、BP、BS、UNKNOWN):";
cin >> get_input;
if (get_input == "LP")filter_type = IS_LP;
else if (get_input == "HP")filter_type = IS_HP;
else if (get_input == "BP")filter_type = IS_BP;
else if (get_input == "BS")filter_type = IS_BS;
else if (get_input == "UNKNOWN") filter_type == UN_KNOWN;
else { cout << "error:输入错误!"; exit(0); }
cout << endl << "下面是关于键入频率和衰减系数的指标的一些声明。\n\
声明:\n\
因为在模拟域中,低通滤波器的通带和阻带下截止频率均趋于负无穷,\n\
所以在数字域中,低通滤波器的通带和阻带下截止频率均趋于0,\n\
所以如果是低通滤波器,程序默认在通带和阻带下截频位置(p1、s1)键入0;\n\
同理,\n\
因为在模拟域中,高通滤波器的通带和阻带上截止频率均趋于正无穷,\n\
所以在数字域中,高通滤波器的通带和阻带上截止频率均趋于0,\n\
所以如果是低通滤波器,程序默认在通带和阻带上截频位置(p2、s2)键入0;" << endl;
cout << endl << "请输入取样频率(Hz):"; cin >> fs;
cout << endl << "请输入通带起始频率p1(Hz):";
if (filter_type == IS_LP) { p1 = 0; cout << p1; }else cin >> p1;
cout << endl << "请输入通带截止频率p2(Hz):";
if (filter_type == IS_HP) { p2 = 0; cout << p2; }else cin >> p2;
cout << endl << "请输入通带衰减系数(dB):"; cin >> Ap;
cout << endl << "请输入阻带起始频率s1(Hz):";
if (filter_type == IS_LP) { s1 = 0; cout << s1; }else cin >> s1;
cout << endl << "请输入阻带截止频率s2(Hz):";
if (filter_type == IS_HP) { s2 = 0; cout << s2; }else cin >> s2;
cout << endl << "请输入阻带衰减系数(dB):"; cin >> As;
cout << endl;
cout << "运算结果为:" << endl;
}
void compilation()
{
ld center = 0;
input();
change();
//判断滤波器类型
cout << endl << "该滤波器的类型为";
switch (check_types(p1, p2, s1, s2))
{
case IS_LP:cout << "低通滤波器;" << endl; break;
case IS_HP:cout << "高通滤波器;" << endl; break;
case IS_BP:cout << "带通滤波器;" << endl; break;
case IS_BS:cout << "带阻滤波器;" << endl; break;
default:
throw"error:参数不符合滤波器特征"; break;
}
cout << endl << "参量下滤波器存在性与对应方法局限性自检成功…" << endl;
center = (check_types(p1, p2, s1, s2) == IS_BP) ? p1 * p2 : s1 * s2;
if (sqrt(center))
cout << endl << "通带中心频率为:" << sqrt(center) << "Hz;" << endl;
//非几何对称改为几何对称
if (p1 * p2 != s1 * s2)
(check_types(p1, p2, s1, s2) == IS_BP) ?
(((center / s2) > s1) ? (s1 = (center / s2)) : (s2 = (center / s1))) :
(((center / p2) > p1) ? (p1 = (center / p2)) : (p2 = (center / p1)));
//计算N的值
ld lambda_p = 1;
ld lambda_s = (check_types(p1, p2, s1, s2) == IS_BP
|| check_types(p1, p2, s1, s2) == IS_LP) ?
((s2 - s1) / (p2 - p1)) : ((p2 - p1) / (s2 - s1));
cout << endl << "归一化截频lambda_s的计算结果为:lambda_s = " << lambda_s << ";" << endl;
double temp_1 = log10((pow(10, 0.1 * As) - 1) / (pow(10, 0.1 * Ap) - 1));
double temp_2 = log10(lambda_s / lambda_p);
int N = ceil(temp_1 / (2 * temp_2));
//根据N的值查表得到低通滤波器归一化传输函数Hlp(p)分母表达式
cout << endl << "butterworth滤波器的阶数为N = " << N << ";" << endl;
cout << endl << "归一化传输函数为:H(p) = ";
show(N, "p");
string show_next_level = is_p(check_types(p1, p2, s1, s2), p2 - p1, center);
cout << endl << "传输函数H(s) = ";
show(N, show_next_level);
}
int main()
{
system("color 0A");
try
{
compilation();
}
catch (const char*cc)
{
cout << cc;
exit(0);
}
return 0;
}
2.2运行示例
2.2.1 书后题4-2
2.2.2书后题4-10
2.2.3书后题4-11
2.2.4书后题4-16
2.2.5书后题4-17
三、更改日志
2024-05-29 09:03:02
complication()函数中对lambda_s的判断赋值有误。
原码:
ld lambda_s = (check_types(p1, p2, s1, s2) == (IS_BP ||I S_LP) ?
((s2 - s1) / (p2 - p1)) : ((p2 - p1) / (s2 - s1));
改正后:
ld lambda_s = (check_types(p1, p2, s1, s2) == IS_BP
|| check_types(p1, p2, s1, s2) == IS_LP) ?
((s2 - s1) / (p2 - p1)) : ((p2 - p1) / (s2 - s1));