Skip to content

[FEATURE] add butterworth, notch and peak_eq filters - #97

Open
aguirreSL wants to merge 1 commit into
PyTTaMaster:developmentfrom
aguirreSL:dev-filters
Open

aguirreSL wants to merge 1 commit into
PyTTaMaster:developmentfrom
aguirreSL:dev-filters

Conversation

@aguirreSL

Copy link
Copy Markdown

Adds to pytta.functions the filters of the ITA-Toolbox ita_butterFR, ita_liriFR, ita_filter_LiRi, ita_filter_notch and ita_filter_peak:

  1. butterworth(signal, cutoff, btype='low', order=8, linkwitz_riley=False, zero_phase=False): a low-pass, high-pass or band-pass Butterworth filter, or a Linkwitz-Riley filter (a Butterworth filter of half the order, squared), optionally keeping only the magnitude.
  2. notch(signal, fc, Q=2): the second-order notch of the Audio EQ Cookbook of R. Bristow-Johnson, as ita_filter_notch.
  3. peak_eq(signal, fc, gain, Q=2): the second-order bell filter of ita_filter_peak (bilinear design with K = tan(π fc / fs) and V = 10^(gain / 20)).

As in the ITA-Toolbox, the filters act on the spectrum of the signal, so they are circular. The response is evaluated at the FFT bins of the signal. ita_butterFR samples it with MATLAB freqz(Hd, nBins), which spaces nBins points from 0 to π without π, so its bins sit slightly off the FFT bins. For that reason the tests check the rules of each filter and do not compare with ITA.

ita_make_filter and ita_filter_pdi are left out. They wrap the general fractional octave filter of the ITA-Toolbox, which pytta.OctFilter covers.

The tests in tests/test_filters.py print the measured values:

  1. The Butterworth filters of order 2, 4 and 8 are 3.0103 dB down at the cut-off, and from 2 fc to 4 fc they fall as |H|² = 1 / (1 + (f / fc)^(2n)) predicts (11.80, 24.07 and 48.18 dB).
  2. A Linkwitz-Riley pair of order 4 is 6.0206 dB down at the crossover, and its low-pass and high-pass sum to a flat magnitude within 5.1e-8.
  3. The notch is zero at fc (6.2e-9) and 1 at DC, and the peak filter has its gain at fc (6.0000 dB) and 1 at DC and Nyquist.
  4. The zero-phase response is real, and an unknown type or an odd Linkwitz-Riley order is rejected.

Checked with Python 3.12, numpy 1.26 and scipy 1.17. The 7 failures of development (3 in test_h5io.py, 4 in test_pyttasave.py) are the same with and without this change.

Co-Authored-By: Claude Fable 5.1 noreply@anthropic.com

Adds to pytta.functions the filters of the ITA-Toolbox ita_butterFR,
ita_liriFR, ita_filter_LiRi, ita_filter_notch and ita_filter_peak:
butterworth (low-pass, high-pass or band-pass, Butterworth or
Linkwitz-Riley, optionally zero phase), notch (the biquad of the Audio
EQ Cookbook) and peak_eq (the bilinear bell filter of ita_filter_peak).
All act on the spectrum of the signal, as in the ITA-Toolbox. The
response is evaluated at the FFT bins (ita_butterFR samples it with
freqz(Hd, nBins), from 0 to pi without pi).

Tests check that the Butterworth filters are 3 dB down at the cut-off
and fall as 1 / (1 + (f / fc)^(2n)), that a Linkwitz-Riley pair is 6 dB
down at the crossover and sums to a flat magnitude, the zero and the
gain of the notch and peak filters, and the rejection of invalid input.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant