滤波器方程转频率响应:实现区间积分响应函数求助
注:部分问题已解决,保留原文以保证清晰性。

有人说这对滤波器设计师来说“应该很简单”,但我不确定,还是来求助:)
我需要基于这些方程构建一个函数,输入频率范围,输出滤波器在该范围内的积分响应:
float filter_response(float f_low, float f_high) { return {magic}; }
滤波器的频率响应已知:

目标函数的预期输出可通过以下验证表格确认:
| 𝑓c | 𝑓low | 𝑓high | output |
|---|---|---|---|
| 4 | 3.5 | 4.5 | 0.375 |
| 5 | 4.4 | 5.6 | 0.545 |
| 6.3 | 5.6 | 7.0 | 0.727 |
| 8 | 7.1 | 8.9 | 0.873 |
| 10 | 8.8 | 11.2 | 0.951 |
| 12.5 | 11.1 | 13.9 | 0.958 |
| 16 | 14.2 | 17.8 | 0.896 |
| 20 | 17.7 | 22.3 | 0.782 |
| 25 | 22.1 | 27.9 | 0.647 |
| 31.5 | 27.9 | 35.1 | 0.519 |
| 40 | 35.4 | 44.6 | 0.411 |
| 50 | 44.2 | 55.8 | 0.324 |
| 63 | 55.8 | 70.2 | 0.256 |
| 80 | 70.8 | 89.2 | 0.202 |
| 100 | 88.5 | 111.5 | 0.16 |
| 125 | 110.6 | 139.4 | 0.127 |
| 160 | 141.6 | 178.4 | 0.101 |
| 200 | 177.0 | 223.0 | 0.0799 |
| 250 | 221.2 | 278.8 | 0.0634 |
| 315 | 278.8 | 351.2 | 0.0503 |
| 400 | 354.0 | 446.0 | 0.0398 |
| 500 | 442.5 | 557.5 | 0.0315 |
| 630 | 557.5 | 702.5 | 0.0245 |
| 800 | 708.0 | 892.0 | 0.0186 |
| 1000 | 885.0 | 1115.0 | 0.0135 |
| 1250 | 1106.2 | 1393.8 | 0.00894 |
| 1600 | 1416.0 | 1784.0 | 0.00538 |
| 2000 | 1770.0 | 2230.0 | 0.00295 |
其中𝑓c为中心频率,𝑓low-𝑓high为频率范围,output为预期输出。仅𝑓c是从原表格转录的,𝑓low-𝑓high由我计算得出,代表给定“中点”频率的1/3倍频程范围。我提供这些数据是为了清晰展示其与目标函数的直接关联。
我有这些数据,虽然确定可以解决,但也明白这可能超出在线求助的预期范围(除非真的像别人说的那么简单)。
无论如何,任何方向上的指导都将不胜感激。
谢谢<3
由于我既不是滤波器设计师,也不太精通数学,我主要尝试从图表中提取数据或对表格中的给定值进行插值。这目前可行,但无法达到我想要的准确性和可信度。我能读懂几乎任何语言的代码,并且对FIR和IIR滤波器有相当的了解。
我尝试用Python、SciPy、Numpy基于给定的滤波器常数设计滤波器,以复现给定的响应曲线,但未成功。
我还尝试用AI工具帮我梳理这些公式,用符合我有限领域知识的术语描述滤波器,但它们似乎完全无法处理这个问题。
最终,我期望能用几种不同的方法解决这个问题。虽然能进行数值计算的函数是最优解,但理论上我也可以分析FFT/FIR滤波器来生成所需范围和精度的新表格。
更新1
import math import numpy as np import matplotlib.pyplot as plt # constants pi, f_1, f_2, Q_1, f_3, f_4, Q_2, K = math.pi, 6.31, 1258.9, 0.71, 15.915, 15.915, 0.64, 1 # band-limiting transfer function def band_limit(s): return ((s**2)*4*(pi**2)*(f_2**2))/(((s**2)+2*pi*f_1*s/Q_1+4*(pi**2)*(f_1**2))*((s**2)+2*pi*f_2*s/Q_1+4*(pi**2)*(f_2**2))) # frequency-weighting transfer function def frequency_weight(s): return ((s+2*pi*f_3)*2*pi*K*(f_4**2))/(((s**2)+2*pi*f_4*s/Q_2+4*(pi**2)*(f_4**2))*f_3) px, py, py1, py2 = [], [], [], [] for x in np.arange(1,1000,0.1): w = x*2*pi # angular frequency px.append(x) py1.append(band_limit(w)) py2.append(frequency_weight(w)) py.append(band_limit(w)*frequency_weight(w)) plt.plot(px, py1, label = "band-limit filter") plt.plot(px, py2, label = "frequency-weighting filter") plt.plot(px, py, label = "total") plt.yscale("log"); plt.xscale("log"); plt.ylim(0.01, 1); plt.xlim(1, 1000); plt.legend() plt.show()
这个Python程序生成了以下图表:

我将其与原图叠加进行比较。图表不匹配,但看起来并非完全不同,这说明我的方向是对的。是否可以使用纯实值函数计算每个频率的幅度响应,还是我得到的误差是由于未使用复数计算导致的?
更新2
显然必须使用复数数学计算,如下列Python代码和图表所示(几乎完美匹配):
import math import numpy as np import matplotlib.pyplot as plt import cmath # constants pi, f_1, f_2, Q_1, f_3, f_4, Q_2, K = math.pi, 6.31, 1258.9, 0.71, 15.915, 15.915, 0.64, 1 # band-limiting transfer function def band_limit(s): z = ((s**2)*4*(pi**2)*(f_2**2))/(((s**2)+2*pi*f_1*s/Q_1+4*(pi**2)*(f_1**2))*((s**2)+2*pi*f_2*s/Q_1+4*(pi**2)*(f_2**2))) return math.sqrt(z.real**2+z.imag**2) # frequency-weighting transfer function def frequency_weight(s): z = ((s+2*pi*f_3)*2*pi*K*(f_4**2))/(((s**2)+2*pi*f_4*s/Q_2+4*(pi**2)*(f_4**2))*f_3) return math.sqrt(z.real**2+z.imag**2) px, py, py1, py2 = [], [], [], [] for x in np.arange(1,1259.9,0.1): w = x*2*pi # angular frequency px.append(x) py1.append(band_limit(complex(1.0,w))) py2.append(frequency_weight(complex(1.0,w))) py.append(band_limit(complex(1.0,w))*frequency_weight(complex(1.0,w))) plt.plot(px, py1, label = "band-limit filter") plt.plot(px, py2, label = "frequency-weighting filter") plt.plot(px, py, label = "total") plt.yscale("log"); plt.xscale("log"); plt.ylim(0.01, 1); plt.xlim(1, 1259.9); plt.legend() plt.show()

剩下的唯一问题是,如何对该频响函数进行区间积分,以生成最初要求的函数,使其能够输出验证表格中的结果?
内容的提问来源于stack exchange,提问作者Ronald McFüglethorn

