Skip to content

[FEATURE] add smooth_notches for equalization - #120

Open
aguirreSL wants to merge 3 commits into
PyTTaMaster:developmentfrom
aguirreSL:dev-smooth_notches
Open

aguirreSL wants to merge 3 commits into
PyTTaMaster:developmentfrom
aguirreSL:dev-smooth_notches

Conversation

@aguirreSL

Copy link
Copy Markdown

Adds smooth_notches(signalObj, nthOct=3, threshold=3, squeeze=0.3) to pytta.functions, the "compare and squeeze" of ita_smooth_notches of the ITA-Toolbox (after S. Müller), which makes the notches of a spectrum shallower before it is inverted, e.g. for loudspeaker equalization.

The magnitude is compared with its smoothing over 1 / nthOct octave (smooth_frequency of #50, the 'LogFreqOctave1' smoothing of the ITA-Toolbox). Every notch deeper than threshold dB below the smoothed curve is taken from where the magnitude last crossed it to where it crosses it again. There the ratio of the two is raised to squeeze, so that the notch keeps squeeze times its depth in dB, and the phase is kept. With threshold 0, every bin below the smoothed curve is squeezed.

The ITA-Toolbox smooths with a Savitzky-Golay filter when the Curve Fitting Toolbox is there; here the box smoothing of smooth_frequency is used. The ITA code was read for its semantics only and nothing was copied.

This pull request builds on #50 and shows its commit until #50 is merged.

The tests in tests/test_smooth_notches.py use the spectrum of a peaking filter at 1 kHz:

  1. A cut of 20 dB keeps 0.3 of its depth below the smoothed curve at its deepest bin (-107.30 dB becomes -100.70 dB, as Ls + 0.3 (L - Ls) predicts), and the spectrum below 300 Hz and above 3 kHz is untouched (within the float32 spectrum of SignalObj).
  2. A dip of 2 dB, below the threshold of 3 dB, is left alone.

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

aguirreSL and others added 3 commits October 31, 2026 19:15
For signalType 'power', _ifft multiplied the whole half spectrum into
the AC slice [1:, :], one row short, so building a SignalObj from a
spectrum (domain='freq') raised a broadcast error. Index [1:, :] on both
sides; the round trip time -> freq -> time closes at the float32 floor.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Smooth the magnitude spectrum over 1 / nthOct octave and keep the phase.
The magnitude is interpolated onto a 1 cent logarithmic grid spanning
the 20 octaves below Nyquist, box averaged over 1200 / nthOct cents
(made odd, shrinking at the ends of the grid) and interpolated back onto
the bins with a not-a-knot cubic spline. The DC bin is copied.

Follows the LogFreqOctave1 smoothing of ita_smooth in the ITA-Toolbox
(RWTH Aachen). Tests pin each rule on spectra built bin by bin and
compare 1, 1/3 and 1/12 octave with the ITA-Toolbox output stored in
tests/golden/smooth_frequency_ita.mat, which
tests/golden/make_smooth_frequency_ita.m regenerates with MATLAB.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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