Skip to content

Add mel EDR, echo density and envelope losses (contributed by Riccardo Giampiccolo) - #257

Merged
SebastianJiroSchlecht merged 3 commits into
mainfrom
riccardo-losses
Oct 4, 2026
Merged

SebastianJiroSchlecht merged 3 commits into
mainfrom
riccardo-losses

Conversation

@SebastianJiroSchlecht

@SebastianJiroSchlecht SebastianJiroSchlecht commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Ports three of the losses Riccardo Giampiccolo shared after DAFx into the composable Match framework.

New

  • MatchMelEnergyDecayRelief: multi-resolution mel EDR (mel power spectrogram, backward-integrated over frames, dB with 80 dB floor), normalized L^p error averaged over resolutions. Defaults are Riccardo's.
  • MatchEchoDensity: MSE of the differentiable normalized echo density profile (Abel & Huang with sigmoid threshold, kappa ramped 1e2 → 1e5).
  • MatchEnvelope: normalized L² error of a peak-follower envelope of h² (release 0.28 ms), zero-phase low-passed (least-squares FIR, 3.2 → 4.8 kHz transition). Ported from Riccardo's corrected version, where the release time is in seconds and the FIR length and band edges are in Hz, so the defaults hold at any sample rate.
  • Building blocks: PeakEnvelope, MelEnergyDecayRelief and EchoDensityProfile features, RelativeError distance (|p-t|^p / mean|t|^p).

Differences from the original

  • EDP is vectorized with unfold instead of a per-sample Python loop. The profile is evaluated every hop samples, which defaults to a quarter window; hop=1 matches the original exactly, but memory grows as nfft × window.
  • EDP clamps sigma before sqrt. The original gives NaN gradients in any all-zero window, e.g. before an FDN's first delay.
  • The EDP window follows response.fs. The original EDPLoss always assumed 16 kHz.
  • The envelope's per-sample peak-follower loop is replaced by a blockwise cummax, and torchaudio's filtfilt by two conv1d calls. Relative difference from the original is 2e-8, and it runs 20–50× faster in the forward pass alone.
  • The mel-EDR defaults were tuned at 16 kHz. At 48 kHz, the same STFT sizes cover a third of the time, and there are no tested values for 48 kHz yet.

Checked against the original code at 16 kHz: EDP max difference 2e-6, envelope 2e-8 relative (16 and 48 kHz), mel-EDR loss 0.198954 vs 0.198962, EDP loss 0.009212 vs 0.009211.

Not ported

  • EDCLoss (broadband linear EDC): covered by MatchEnergyDecay / energy_decay_curve + Match.
  • ICLDLoss: specific to the FOA sound-field project. Riccardo confirmed that gz = sin(az) should be sin(el), and that comparing only the x/y pair was a choice to stay in the horizontal plane. Deferred to that project.

Follow-up

  • The EDP's κ ramp was only tested on single-slope RIRs. Normalizing κ by the signal level might matter for double-slope RIRs; Riccardo thinks it is worth testing.

Tests

tests/test_losses_features.py: both losses get finite gradients on silent inputs, EDP ≈ 1 on Gaussian noise and < 0.2 on a click train, and mel-EDR is zero on the target. The envelope's blockwise cummax equals the sample-by-sample recursion, including across a gap longer than one block. The envelope loss is left out of the silent-target gradient test because an error relative to a silent target is undefined. The 3 failures in test_train.py (MPS device tests and test_a_trained_rt_still_decays) also fail on main.

🤖 Generated with Claude Code

MatchMelEnergyDecayRelief: multi-resolution mel energy decay relief in dB,
normalized L^p error (new RelativeError distance). MatchEchoDensity: MSE of
a differentiable (sigmoid-thresholded) normalized echo density profile.
Both are ports onto the Feature/Distance/Match pipeline, checked numerically
against the original code; the EDP is vectorized with unfold and clamps
sigma so silent windows no longer give NaN gradients.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MatchEnvelope: normalized L^2 error of a peak-follower envelope of h^2,
zero-phase low-passed, from Riccardo's corrected version (release time in
seconds, FIR length and band edges in Hz so defaults hold across rates).
The per-sample peak-follower loop is replaced by a blockwise cummax and
torchaudio's filtfilt by two conv1d calls; matches the original to 2e-8.
Note that the mel EDR defaults were tuned at 16 kHz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SebastianJiroSchlecht SebastianJiroSchlecht changed the title Add mel EDR and echo density losses (contributed by Riccardo Giampiccolo) Add mel EDR, echo density and envelope losses (contributed by Riccardo Giampiccolo) Sep 30, 2026
@SebastianJiroSchlecht
SebastianJiroSchlecht merged commit 3732d6b into main Oct 4, 2026
7 checks passed
@SebastianJiroSchlecht
SebastianJiroSchlecht deleted the riccardo-losses branch October 4, 2026 10:18
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