
來進行一個排版
$H(z)=\frac{b_{0}+b_{1}z^{-1}+b_{2}z^{-2}+...+b_{k}z^{-k}}{a_{0}+a_{1}z^{-1}+a_{2}z^{-2}+...+a_{k}z^{-k}}$
這個
然后會重寫成這樣:
y[n]={\frac{1}{a_{0}}}\left(\left(b_{0}x[n]+b_{1}x[n-1]+b_{2}x[n-2]+...+b_{k}x[n-k]\right)-\left(a_{1}y[n-1]+a_{2}y[n-2]+...+a_{k}y[n-k]\right)\right)
因為這個重寫的公式太長了,截圖就是這樣的
IIR(Infinite Impulse Response)——無限脈沖響應濾波器,是數字信號處理的基本組成部分。
1、IIR濾波器是什么
IIR濾波器是用于數字信號處理(DSP)應用的兩種主要數字濾波器之一(另一種是FIR)。“IIR”的意思是“無限脈沖響應”。
2、 IIR為什么脈沖響應是“無限的”?
脈沖響應是“無限”的,因為濾波器中有反饋;如果你輸入一個脈沖(一個“1”樣本后面跟著多個“0”樣本),理論上就會輸出無限個非零值。
3、 IIR過濾器的替代方案是什么?
DSP濾波器也可以是“有限脈沖響應”(FIR)。FIR濾波器不使用反饋,所以對于N個系數的FIR濾波器,輸入N個脈沖響應的樣本后輸出總是為零。
?4、IIR濾波器(與FIR濾波器相比)的優點是什么?
與類似的FIR濾波器相比,IIR濾波器可以用更少的內存和計算來實現給定的濾波特性。
5、IIR濾波器(與FIR濾波器相比)的缺點是什么?
(1)它們更容易受到有限長度算法問題的影響,比如計算產生的噪聲和極限環。(這是反饋造成的直接結果:當輸出沒有被完美地計算出來并得到反饋時,不完美可能會加劇。)
(2)它們使用定點算法更難(更慢)實現.
(3)對于多速率(抽取和插值)應用,它們沒有FIR濾波器的計算優勢。
一、線性
通信系統中的線性不再是數學中坐標軸上的直線,也不是所有的直線都符合線性特征,通信系統中的線性要滿足一個條件。

二、時不變系統
一句話概括時不變系統:如果你的系統是時不變系統,如果將相同的輸入輸入到系統中,無論何時將輸入輸入到系統中,都將獲得相同的輸出。
那么我們還假設你的系統是時不變系統,你有一個確定的輸入,你只需在知道某個時間下這個輸入的所有特征。如果你明天還輸入相同的輸入,那么你的不用重新掌握它的特征。
相對的如果你的系統是時變系統:
投入了一定的投入,花了大量的時間和精力調查了投入的所有特征。但是無法重用結果,因為當重用它時,時間不同,結果也會不同。就像。。。你有一臺電腦。每次運行完全相同的程序時,都會得到不同的結果。
唯一可以重用結果的情況是進一步努力找出規則,以顯示輸出是如何隨時間變化的。不幸的是,你不能保證你能找到規則。即使你很幸運找到了規則,你的系統模型也會非常復雜。
三、總結
線性系統,你知道一個確定的結果,你就知道其他所有的結果,
時不變系統,你的特定輸入,其輸出的結果不會隨著時間而變化。

這個IIR二階的傳遞函數是從wiki里面拿到的

因為這個IIR是給下一級使用的,這里設計成一個類

類的初始化

接下來是使用一個現成的包來驗證一下結果

返回的是分子和分母的多項式

計算a,b
設置系數用于 IIR 濾波器。這些都應該是 size order + 1,a_0 可以省略,它將使用 1.0 作為默認值。

這就是這樣,下面的都是對參數的約束

a,b就是系數

計算f(n),對著公式編程序

這個就是兩項計算的公式

按照這個寫的
關于濾波器還有若干的問題需要說明:一階濾波器,思路就是把一個連續的濾波器形式,通過離散化的方式,轉換成差分方程。從wiki或者文章里面拿到的濾波器公式,通常是用傳遞函數表達的,這是S域下的表達形式,是連續的,這種我們稱之為模擬濾波器。模擬濾波器傳遞函數,目的是用來設計濾波電路,針對的是連續時間的模擬信號,組成元器件是電阻,電容,電感。而數字濾波器實現方法是把濾波器所要完成的運算編成程序并讓計算機執行,也就是采用在代碼的形式。它面對的是離散時間的數字信號,是把輸入序列通過一定的運算變換成輸出序列。有沒有辦法能把連續的模擬濾波器變成離散的數字濾波器?
其中最常使用的一種叫做雙線性變換:

把這個公式帶入傳遞函數就可以得到一個z域的差分方程了。
以上變換這段參考:

后面截至頻率什么的沒有寫
但是知道接下來應該看的是:自動控制原理。

我們在BW濾波器里面將要實現這些算法
所有濾波器傳遞函數均源自模擬原型,并已使用雙線性變換 (BLT) 進行數字化。BLT 頻率扭曲已被考慮到重要的頻率重定位(這是使用 BLT 時必需的正常“預扭曲”)和帶寬重新調整(因為使用 BLT 從模擬映射到數字時帶寬被壓縮)。這個就是上面文章里面說的:

出現這個問題,需要使用數學工具矯正

模擬截止頻率與數字截止頻率的關系
證明自己看吧,我也看不懂了,越看越覺得自己不該念這個書。。。這是TM的什么人間疾苦。

不過看了下。。。有歐拉公式就行

先定義雙線性的函數,在上面寫了

經過一次變換

最后才寫成這個
省去一段推導,給出結果:

低通濾波器的結果

參數是,頻率,采樣率,Q值

第一個的濾波器的算法設計
在最后給出一個在雙線性變換下使用補償頻率扭曲的補償算法推導:

首先是歸一化的操作

使用這個三角函數

還有這個

對公式進行重構,構個頭就是重新帶進去


三個

還有因子也重新寫
對分子和分母中的所有項都是通用的,可以因式分解,因此在上面的替換中被忽略,所以有:

又重寫了
此外,所有項,分子和分母,都可以乘以一個共同的:

好大個系數

最后就是簡化出來的雙二階系數公式
嘖,萬物之源是數學,還不滾去學習。

在最終的演示中

這個錯誤

說是3.8才有
pip install typing_extensionsfrom typing_extensions import Protocol

可以寫成這樣

話說有朝一日我還能拍出這種照片

是不是有點古城的味道了嗷!
考慮到這個算法的復雜性,這里將代碼寫在了一起,可以直接調用:
from __future__ import annotations# from audio_filters.iir_filter import IIRFilterimport numpy as npimport matplotlib.pyplot as pltfrom typing_extensions import Protocolfrom math import pifrom math import cos, sin, sqrt, tauclass IIRFilter:def __init__(self, order: int) -> None:= order# a_{0} ... a_{k}= [1.0] + [0.0] * order# b_{0} ... b_{k}= [1.0] + [0.0] * order# x[n-1] ... x[n-k]= [0.0] * self.order# y[n-1] ... y[n-k]= [0.0] * self.orderdef set_coefficients(self, a_coeffs: list[float], b_coeffs: list[float]) -> None:if len(a_coeffs) < self.order:a_coeffs = [1.0] + a_coeffsif len(a_coeffs) != self.order + 1:raise ValueError(a_coeffs to 有 {self.order + 1} elements for {self.order}"filter, got {len(a_coeffs)}")if len(b_coeffs) != self.order + 1:raise ValueError(b_coeffs to have {self.order + 1} elements for {self.order}"filter, got {len(a_coeffs)}")= a_coeffs= b_coeffsdef process(self, sample: float) -> float:result = 0.0# 從索引 1 開始,最后執行索引 0for i in range(1, self.order + 1):result += (self.b_coeffs[i] * self.input_history[i-1]-self.a_coeffs[i]*self.output_history[i-1])result = (result + self.b_coeffs[0] * sample) / self.a_coeffs[0]:] = self.input_history[:-1]:] = self.output_history[:-1]= sample= resultreturn resultdef make_lowpass(frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2)-> IIRFilter:w0 = tau * frequency / samplerate_sin = sin(w0)_cos = cos(w0)alpha = _sin / (2 * q_factor)b0 = (1 - _cos) / 2b1 = 1 - _cosa0 = 1 + alphaa1 = -2 * _cosa2 = 1 - alphafilt = IIRFilter(2)a1, a2], [b0, b1, b0])return filtdef make_highpass(frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2)-> IIRFilter:w0 = tau * frequency / samplerate_sin = sin(w0)_cos = cos(w0)alpha = _sin / (2 * q_factor)b0 = (1 + _cos) / 2b1 = -1 - _cosa0 = 1 + alphaa1 = -2 * _cosa2 = 1 - alphafilt = IIRFilter(2)a1, a2], [b0, b1, b0])return filtdef make_bandpass(frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2)-> IIRFilter:"""創建帶通濾波器filter = make_bandpass(1000, 48000)filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE-1.9828897227476208, 0.9077040443587427, 0.06526309611002579,-0.06526309611002579]"""w0 = tau * frequency / samplerate_sin = sin(w0)_cos = cos(w0)alpha = _sin / (2 * q_factor)b0 = _sin / 2b1 = 0b2 = -b0a0 = 1 + alphaa1 = -2 * _cosa2 = 1 - alphafilt = IIRFilter(2)a1, a2], [b0, b1, b2])return filtdef make_allpass(frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2)-> IIRFilter:w0 = tau * frequency / samplerate_sin = sin(w0)_cos = cos(w0)alpha = _sin / (2 * q_factor)b0 = 1 - alphab1 = -2 * _cosb2 = 1 + alphafilt = IIRFilter(2)b1, b0], [b0, b1, b2])return filtdef make_peak(frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2)-> IIRFilter:w0 = tau * frequency / samplerate_sin = sin(w0)_cos = cos(w0)alpha = _sin / (2 * q_factor)big_a = 10 ** (gain_db / 40)b0 = 1 + alpha * big_ab1 = -2 * _cosb2 = 1 - alpha * big_aa0 = 1 + alpha / big_aa1 = -2 * _cosa2 = 1 - alpha / big_afilt = IIRFilter(2)a1, a2], [b0, b1, b2])return filtdef make_lowshelf(frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2)-> IIRFilter:w0 = tau * frequency / samplerate_sin = sin(w0)_cos = cos(w0)alpha = _sin / (2 * q_factor)big_a = 10 ** (gain_db / 40)pmc = (big_a + 1) - (big_a - 1) * _cosppmc = (big_a + 1) + (big_a - 1) * _cosmpc = (big_a - 1) - (big_a + 1) * _cospmpc = (big_a - 1) + (big_a + 1) * _cosaa2 = 2 * sqrt(big_a) * alphab0 = big_a * (pmc + aa2)b1 = 2 * big_a * mpcb2 = big_a * (pmc - aa2)a0 = ppmc + aa2a1 = -2 * pmpca2 = ppmc - aa2filt = IIRFilter(2)a1, a2], [b0, b1, b2])return filtdef make_highshelf(frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2)-> IIRFilter:w0 = tau * frequency / samplerate_sin = sin(w0)_cos = cos(w0)alpha = _sin / (2 * q_factor)big_a = 10 ** (gain_db / 40)pmc = (big_a + 1) - (big_a - 1) * _cosppmc = (big_a + 1) + (big_a - 1) * _cosmpc = (big_a - 1) - (big_a + 1) * _cospmpc = (big_a - 1) + (big_a + 1) * _cosaa2 = 2 * sqrt(big_a) * alphab0 = big_a * (ppmc + aa2)b1 = -2 * big_a * pmpcb2 = big_a * (ppmc - aa2)a0 = pmc + aa2a1 = 2 * mpca2 = pmc - aa2filt = IIRFilter(2)a1, a2], [b0, b1, b2])return filtclass FilterType(Protocol):def process(self, sample: float) -> float:return 0.0def get_bounds(fft_results: np.ndarray, samplerate: int-> tuple[int | float, int | float]:lowest = min([-20, np.min(fft_results[1: samplerate // 2 - 1])])highest = max([20, np.max(fft_results[1: samplerate // 2 - 1])])return lowest, highestdef show_frequency_response(filter: FilterType, samplerate: int) -> None:size = 512inputs = [1] + [0] * (size - 1)outputs = [filter.process(item) for item in inputs]filler = [0] * (samplerate - size) # zero-paddingoutputs += fillerfft_out = np.abs(np.fft.fft(outputs))fft_db = 20 * np.log10(fft_out)# Frequencies on log scale from 24 to nyquist frequencysamplerate / 2 - 1)(Hz)")plt.xscale("log")# Display within reasonable boundsbounds = get_bounds(fft_db, samplerate)bounds[0]]), min([80, bounds[1]]))(dB)")plt.plot(fft_db)plt.show()def show_phase_response(filter: FilterType, samplerate: int) -> None:size = 512inputs = [1] + [0] * (size - 1)outputs = [filter.process(item) for item in inputs]filler = [0] * (samplerate - size)outputs += fillerfft_out = np.angle(np.fft.fft(outputs))samplerate / 2 - 1)(Hz)")plt.xscale("log")* pi, 2 * pi)shift (Radians)")-2 * pi))plt.show()filt = IIRFilter(4)48000)

應該是可以直接出現這樣的圖
https://stackoverflow.com/questions/54274630/can-not-import-protocol-from-typinghttps://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.htmlhttps://blog.csdn.net/abc123mma/article/details/120251384https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.htmlhttps://blog.csdn.net/SHC2012377/article/details/120910496https://en.wikipedia.org/wiki/Digital_biquad_filterhttps://zhuanlan.zhihu.com/p/357619650https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.butter.html