Python icon indicating copy to clipboard operation
Python copied to clipboard

Find:audio_filters/butterworth_filter.py issure

Open lighting9999 opened this issue 1 year ago • 6 comments

Repository commit

fcf82a1eda21dcf36254a8fcaadc913f6a94c8da

Python version (python --version)

Python 3.10.6

Dependencies version (pip freeze)

absl-py==2.1.0
astunparse==1.6.3
beautifulsoup4==4.12.3
certifi==2024.8.30
charset-normalizer==3.4.0
contourpy==1.3.0
cycler==0.12.1
dill==0.3.9
dom_toml==2.0.0
domdf-python-tools==3.9.0
fake-useragent==1.5.1
flatbuffers==24.3.25
fonttools==4.54.1
gast==0.6.0
google-pasta==0.2.0
grpcio==1.67.0
h5py==3.12.1
idna==3.10
imageio==2.36.0
joblib==1.4.2
keras==3.6.0
kiwisolver==1.4.7
libclang==18.1.1
lxml==5.3.0
Markdown==3.7
markdown-it-py==3.0.0
MarkupSafe==3.0.2
matplotlib==3.9.2
mdurl==0.1.2
ml-dtypes==0.3.2
mpmath==1.3.0
namex==0.0.8
natsort==8.4.0
numpy==1.26.4
oauthlib==3.2.2
opencv-python==4.10.0.84
opt_einsum==3.4.0
optree==0.13.0
packaging==24.1
pandas==2.2.3
patsy==0.5.6
pbr==6.1.0
pillow==11.0.0
pip==24.2
protobuf==4.25.5
psutil==6.1.0
Pygments==2.18.0
pyparsing==3.2.0
python-dateutil==2.9.0.post0
pytz==2024.2
qiskit==1.2.4
qiskit-aer==0.15.1
requests==2.32.3
requests-oauthlib==1.3.1
rich==13.9.2
rustworkx==0.15.1
scikit-learn==1.5.2
scipy==1.14.1
setuptools==74.1.2
six==1.16.0
soupsieve==2.6
sphinx-pyproject==0.3.0
statsmodels==0.14.4
stevedore==5.3.0
symengine==0.13.0
sympy==1.13.3
tensorboard==2.16.2
tensorboard-data-server==0.7.2
tensorflow==2.16.2
tensorflow-io-gcs-filesystem==0.37.1
termcolor==2.5.0
threadpoolctl==3.5.0
tomli==2.0.2
tweepy==4.14.0
typing_extensions==4.12.2
tzdata==2024.2
urllib3==2.2.3
Werkzeug==3.0.4
wheel==0.44.0
wrapt==1.16.0
xgboost==2.1.1

Expected behavior

  • Frequency (frequency): It should be ensured that the frequency is a reasonable positive value and does not exceed the Nyquist frequency (i.e., half of the sampling rate). If the frequency is too high, it may lead to an unstable filter.
  • Sampling Rate (samplerate): The sampling rate should be a positive integer and is typically fixed, but it should still be ensured that it is a reasonable value.
  • Q Factor (q_factor): The Q factor should be a positive value. Typically, it should not be too small (which would result in a very wide transition band) or too large (which could cause the filter to oscillate or become unstable).

Actual behavior

The issue was resolved by implementing additional constraints.

from math import cos, sin, sqrt, tau
from audio_filters.iir_filter import IIRFilter

def make_highpass(
    frequency: int, 
    samplerate: int, 
    q_factor: float = 1 / sqrt(2)
) -> IIRFilter:
    """
    创建一个二阶 IIR 高通滤波器(Butterworth 设计)。

    参数:
        frequency (int): 高通滤波器的截止频率。
        samplerate (int): 采样率。
        q_factor (float, optional): 品质因数,默认为 1 / sqrt(2)。

    返回:
        IIRFilter: 生成的 IIR 高通滤波器对象。

    异常:
        ValueError: 如果输入参数无效。
    """
    # 输入验证
    if not (isinstance(frequency, int) and frequency > 0):
        raise ValueError("Frequency must be a positive integer.")
    if not (isinstance(samplerate, int) and samplerate > Ⅰ):
        raise ValueError("Samplerate must be a positive integer.")
    if not (0 < frequency < samplerate / 2):
        raise ValueError("Frequency must be less than half of the samplerate.")
    if q_factor <= 0:
        raise ValueError("Q factor must be positive.")

    # 计算中间变量
    w0 = tau * frequency / samplerate
    _sin = sin(w0)
    _cos = cos(w0)
    alpha = _sin / (2 * q_factor)

    # 计算滤波器系数
    b0 = (1 + _cos) / 2
    b1 = -1 - _cos
    a0 = 1 + alpha
    a1 = -2 * _cos
    a2 = 1 - alpha

    # 创建并设置 IIR 滤波器对象
    filt = IIRFilter(2)
    filt.set_coefficients([a0, a1, a2], [b0, b1, b0])
    return filt

# 示例用法
if __name__ == "__main__":
    try:
        filter = make_highpass(1000, 48000)
        print(filter.a_coeffs + filter.b_coeffs)
    except ValueError as e:
        print(f"Error: {e}")

I don not know Hash at repo.

lighting9999 avatar Nov 17 '24 07:11 lighting9999

# input validation
    if not (isinstance(frequency, int) and frequency > 0):
        raise ValueError("Frequency must be a positive integer.")
    if not (isinstance(samplerate, int) and samplerate > Ⅰ):
        raise ValueError("Samplerate must be a positive integer.")
    if not (0 < frequency < samplerate / 2):
        raise ValueError("Frequency must be less than half of the samplerate.")
    if q_factor <= 0:
        raise ValueError("Q factor must be positive.")

The code block submitted (this code block) to fix the defect.

lighting9999 avatar Nov 17 '24 07:11 lighting9999

I can implement and open a pr for these checks using decorators to make them reusable for other function in the file too. But, being not at all experienced in audio signal processing, is it a problem with all filter types or the check is just needed for the highpass filter only. Also, the checks about frequency and samplerate being int instances may not be needed as while it gets into numerical operations, it could raise those errors there itself if they are non-numeric unless they're needed to be ints only in which case those checks are needed.

anscian avatar Feb 05 '25 22:02 anscian

I check all filters comprehensively.

lighting9999 avatar Feb 07 '25 01:02 lighting9999

Please review my pull request #12562 for this issue. I have applied these checks for all the filters. I'm using decorators so that these checks can be added/removed from filter creating functions seamlessly.

anscian avatar Feb 08 '25 06:02 anscian

thanks.

lighting9999 avatar Feb 08 '25 07:02 lighting9999