Skip to content

[FEATURE] add the enhanced spectrogram - #51

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

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

Conversation

@aguirreSL

@aguirreSL aguirreSL commented Oct 31, 2026 •

Copy link
Copy Markdown

Adds pytta.enhanced_spectrogram(signalObj, smoothing='readable', n_frames=2000, f_min=20, bins_per_octave=192) and the option enhanced='readable' | 'sharp' to pytta.plot_spectrogram and SignalObj.plot_spectrogram.

The enhanced spectrogram is a spectrogram with no window to choose: nine Blackman-Harris windows from 8 to 512 ms are reassigned (Auger and Flandrin, 1995), the energy of each frame is held over the frame step of its window, each map is smoothed, and the maps are combined by geometric mean (Cheung and Lim, 1991, applied to reassigned maps). Two smoothings: readable (4 ms by 1.45 % of the frequency, continuous lines) and sharp (1 ms by 1 Hz, thinnest lines). The output is on a logarithmic frequency grid, in dB re the channel's dBRef; the cells of a column add up to the level of that instant.

The same method is in the SQAT toolbox (GPL-3.0) as gui/SQAT_GUI_enhanced_stft.m (https://github.com/ggrecow/SQAT). I am its author and release it here under the MIT license of PyTTa; the SQAT version keeps its license. The computation lives in pytta/utils/spectrogram.py on NumPy arrays, so that _plot can use it without a circular import; pytta.enhanced_spectrogram is the SignalObj interface.

Tests (tests/test_enhanced_spectrogram.py, 7 tests):

  • comparison with SQAT on a signal with a tone, a modulated tone, a click and noise, both smoothings, default grid (t and f whole, maps on every 16th row and 10th column). Reference data: tests/golden/enhanced_spectrogram_sqat.mat (135 kB), generated by tests/golden/make_enhanced_spectrogram_sqat.m with MATLAB and SQAT. Measured difference: 3e-10 dB
  • a column of a steady 94 dB SPL tone adds up to 94 dB (93.94 readable, 94.06 sharp)
  • a tone lands on its frequency row and a click within 1 ms of its time
  • silence sits at the -120 dB floor, with no NaN or -inf
  • channels are computed independently and the input is not modified
  • the plot draws exactly the computed map, on a logarithmic frequency axis
  • rejection of invalid f_min, smoothing and input type

Cost: 10 s of audio at 48 kHz in about 2.3 s on an Apple laptop.

Checked with Python 3.12, numpy 1.26, scipy 1.17. The existing tests behave as on development: the 7 failures there (3 in test_h5io.py, 4 in test_pyttasave.py) are the same with and without this change. Independent of #49 and #50.

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

Add enhanced_spectrogram, a spectrogram with no window to choose: nine
Blackman-Harris windows from 8 to 512 ms are reassigned, the energy of
each frame is held over its frame step, each map is smoothed ('readable'
or 'sharp') and the maps are combined by geometric mean. The output is
on a logarithmic frequency grid in dB re the channel dBRef.

plot_spectrogram and SignalObj.plot_spectrogram take enhanced='readable'
or 'sharp' to draw it on a logarithmic frequency axis. The computation
lives in pytta/utils/spectrogram.py on arrays, so that _plot uses it
without a circular import.

The same method is in SQAT (GPL-3.0) as gui/SQAT_GUI_enhanced_stft.m;
its author releases it here under the MIT license. Tests compare both
smoothings with the SQAT output stored in
tests/golden/enhanced_spectrogram_sqat.mat, which
tests/golden/make_enhanced_spectrogram_sqat.m regenerates with MATLAB,
and pin the level of a steady tone, where a tone and a click land, the
floor of silence, independent channels and the plot.

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