模拟技术
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)
全部0条评论
快来发表一下你的评论吧 !