Skip to content

[FEATURE] EDC noise compensation methods and T20/T30 uncertainty - #58

Open
aguirreSL wants to merge 2 commits into
PyTTaMaster:developmentfrom
aguirreSL:dev-room_edc
Open

aguirreSL wants to merge 2 commits into
PyTTaMaster:developmentfrom
aguirreSL:dev-room_edc

Conversation

@aguirreSL

@aguirreSL aguirreSL commented Oct 31, 2026 •

Copy link
Copy Markdown

RoomAnalysis takes a new argument, edcMethod, which selects the noise compensation of the energy decay curve among the methods of ISO 3382-1 compared by Guski and Vorländer (2013):

edcMethod Energy decay curve
'cutWithCorrection' (default) truncated at the intersection with the background noise (Lundeby et al., 1995), plus the energy of the decay beyond it. This is the method RoomAnalysis used until now, so results do not change.
'justCut' truncated at the intersection, with no correction
'noCut' the whole response, noise included
'subtractNoise' the background noise level subtracted from the squared response, then the whole of it integrated (Chu, 1978)

bypassLundeby=True raised UnboundLocalError, because the Lundeby parameters were returned without being set. It is now the 'noCut' method.

RoomAnalysis.uncertainty(param, numPositions=1, numDecays=10) gives the standard deviation of T20 or T30 by band from ISO 3382-1:2009, Equations (4) and (5). An impulse response counts as n = 10 decays, as clause 7.2 of the standard says. The bandwidth is fc (2^(1/(2 nthOct)) - 2^(-1/(2 nthOct))), which gives the 0.71 fc and 0.23 fc of the standard for octaves and thirds.

A second commit adds RoomAnalysis.PSNR, the peak-to-noise ratio of each band (the peak of the squared band response over the background noise level found by Lundeby, nan with 'noCut'), and RoomAnalysis.timbre_ratios(param='T30'), the bass and treble ratios of Beranek, BR = (T125 + T250) / (T500 + T1000) and TR = (T2000 + T4000) / (T500 + T1000). cumulative_integration now also returns the Lundeby parameters of each band. Its other caller, the deprecated pytta.rooms.analyse, already failed there, since it expects a single return value.

The tests in tests/test_room_edc.py use a synthetic exponential decay with T = 1 s over background noise 45 dB below its start. With it, T30 in the octaves from 500 Hz to 2 kHz is 1.01 to 1.03 s with 'cutWithCorrection', 0.98 to 1.00 s with 'subtractNoise', 1.00 to 1.02 s with 'justCut' and 5.1 to 5.5 s with 'noCut'. The tests check that the compensated methods find T within 5 %, that 'noCut' overestimates it and 'justCut' stays below 'cutWithCorrection', that bypassLundeby=True equals 'noCut', that the uncertainty follows Equations (4) and (5), that the PSNR of each band grows by 10 dB (9.91 to 10.02 dB measured) when the noise floor drops by 10 dB, and that BR and TR of a response with known decay per band come out within 5 % (1.288 against 1.267, 0.711 against 0.733).

Checked with Python 3.12, numpy 1.26 and 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.

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

RoomAnalysis takes edcMethod, one of the noise compensations of
ISO 3382-1 compared by Guski and Vorlaender (2013): 'cutWithCorrection',
the method used so far and the default, 'justCut', 'noCut' and
'subtractNoise' (Chu, 1978). bypassLundeby=True is the 'noCut' method;
it raised UnboundLocalError because the Lundeby parameters were returned
without being set.

RoomAnalysis.uncertainty gives the standard deviation of T20 or T30 by
band from ISO 3382-1:2009, Equations (4) and (5), for N positions and n
decays per position, with n = 10 for an impulse response (clause 7.2).

Tests use a synthetic decay with T = 1 s over background noise 45 dB
below its start: the compensated methods find T, 'noCut' overestimates
it, 'justCut' falls below 'cutWithCorrection', bypassLundeby equals
'noCut', and the uncertainty follows the equations of the standard.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
RoomAnalysis.PSNR gives, by band, the peak of the squared band response
over the background noise level found by Lundeby (nan without it), and
RoomAnalysis.timbre_ratios the bass and treble ratios of Beranek from
the reverberation times of the octave bands. cumulative_integration also
returns the Lundeby parameters of each band.

Tests check that the PSNR grows by 10 dB when the noise floor drops by
10 dB, and BR and TR of a synthetic response with known decay per band.

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