Point it at a room recording, get that room's reverb back as a cheap, real-time, editable effect.
Under the hood this is a differentiable Feedback Delay Network with learnable delay lines — a clean, open-source PyTorch reimplementation of
A. I. Mezza, R. Giampiccolo, E. De Sena, A. Bernardini, "Data-driven room acoustic modeling via differentiable feedback delay networks with learnable delay lines," EURASIP Journal on Audio, Speech, and Music Processing, 2024(1):51. arXiv:2404.00082 · DOI:10.1186/s13636-024-00371-5
📄 Read the interactive write-up — Inverting the Room — with playable before/after audio → A room's reverb, extracted and then removed: the informed case works (0.41 → 0.91 STOI), and the write-up is honest about where blind system-ID hits the wall.
A room's reverb, captured as a Room Impulse Response (RIR), is expensive to use directly (long convolution, fixed, not tweakable). This fits a Feedback Delay Network — the classic Schroeder/Jot artificial-reverb structure — to that RIR, so you get the same room as a handful of delay lines and gains: it renders in real time, costs almost nothing, and every parameter (decay, delay lengths, absorption) is now a knob you can turn.
Be honest about scope. There are two very different problems here:
- Informed inversion — works. Give it the room's measured RIR (or a synthetic target) and it fits an FDN whose energy decay and echo build-up match that room. The optimiser reliably drives the loss down ~99% on the synthetic target and recovers a plausible, renderable reverb. This is the regime the demo and the smoke test live in.
- Blind system-ID — the wall. Recovering the room from an ordinary reverberant recording alone (no measured RIR, e.g. estimating the RIR from a voice clip and then fitting it) is the hard, open part. RIR estimation is itself unsolved in general, and errors there dominate everything downstream. This repo does not claim to do blind extraction well — that's the frontier, not a shipped feature.
So: informed inversion is real; blind system-ID is where it stops. Everything below describes the informed case.
A Feedback Delay Network (FDN) is a bank of delay lines stitched together by a feedback matrix, with input/output gains and per-line absorption. It has been the workhorse of digital reverberation for decades — but its parameters, especially the delay-line lengths, are traditionally hand-tuned because a delay read from a buffer is not differentiable.
This project makes the entire FDN differentiable — delay lines and all — so every parameter can be learned by backpropagation to match a target RIR. It reproduces the method of Mezza et al. (2024):
- Learnable delay lines (the novel part). Each integer delay
z^{-m}is realised in the frequency domain with the Pei–Lai closed-form fractional-delay filter, whose response is a smooth function of a real-valuedm. Gradients flow through the FFT straight to the delay lengths. - Learnable feedback matrix
A = U·diag(γ), withUan orthogonal (unilossless) matrix parameterised through a skew-symmetric matrix exponential — stable by construction. - Learnable input/output/direct gains and per-line absorption, each a differentiable reparameterisation of an unconstrained proxy.
- A perceptual, fully-differentiable loss:
Energy Decay Curve (EDC) + a differentiable normalised Echo Density
Profile (soft-EDP) in which the Heaviside indicator is replaced by a scaled
sigmoid with a time-varying sharpness
κ_n.
The optimiser fits one FDN to one RIR — a white-box system-identification view of reverberation: the result is a causal, real-time-renderable reverb whose decay and echo build-up match the target room.
| Paper concept | Where |
|---|---|
Fractional delay D_i[k] (Pei–Lai), gradients to m |
dfdn/delay.py |
FDN transfer function H = cᵀ(I − D·A)⁻¹D·b + d, frequency sampling |
dfdn/fdn.py |
Orthogonal U = expm(triu(W) − triuᵀ), A = U·diag(γ) |
dfdn/fdn.py |
| Delay/gain/absorption reparameterisations | dfdn/fdn.py |
| Schroeder EDC + normalised-MSE loss | dfdn/losses.py |
Soft-EDP with sigmoid + time-varying κ_n |
dfdn/losses.py |
L = L_EDC + λ·L_EDP, Adam training loop |
dfdn/train.py |
| Target RIR (synthetic or real WAV) | dfdn/rir.py |
| CLI example, plots, audio export | train.py |
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt # CPU torch is fine; GPU optional
# CPU-only wheel: pip install torch --index-url https://download.pytorch.org/whl/cpuSmoke test on a synthetic target RIR (clearly labelled as such — a direct impulse + sparse early reflections + decaying Gaussian tail so the echo density rises realistically):
python train.py --iters 500 --t60 0.5Fit a real measured RIR (mono/stereo WAV, any sample rate — it is downmixed, resampled to 16 kHz and trimmed to the direct-sound onset):
python train.py --rir path/to/room.wav --iters 800Outputs land in results/: fit_summary.png (loss curves, EDC in dB, echo
density profile, impulse response — before/after) plus target_rir.wav and
fitted_rir.wav.
Use the library directly:
import torch
from dfdn import fit_fdn, TrainConfig
from dfdn.rir import synth_rir, to_tensor
h = to_tensor(synth_rir(t60=0.5))
model, history, h_init, h_final = fit_fdn(h, TrainConfig(iters=500))
rir = model.render(len(h)) # differentiable, real-valued RIRRun the tests (fast, CPU, no dataset needed):
python tests/test_dfdn.py # or: python -m pytest tests/ -qA one-click Gradio demo lives in app.py — drop a boomy clip or a
RIR, watch the FDN fit it, and hear the extracted reverb. It is designed for the
Hugging Face Space described in HF_SPACE_PLAN.md, tagged
arxiv:2404.00082 so it surfaces from
HF Papers. CPU-basic tier is enough
(a 500-iteration fit is ~1 minute).
pip install gradio
python app.pyA 500-iteration run (N = 6 delay lines, 16 kHz, Adam lr = 0.1) on the synthetic target reduces the loss by ~99% and recovers the target's decay and echo build-up:
Loss: 9.96e-01 -> 9.70e-03 (99.0% reduction)
Learned delays (ms): [24.3, 3.3, 3.7, 1.7, 3.5, 6.6]
Absorption γ: [0.88, 0.97, 0.96, 0.95, 0.97, 0.93]
See docs/fit_summary.png. The fitted EDC tracks the target's exponential
decay closely (versus a badly-mismatched initialisation), and the fitted echo
density profile rises from sparse early reflections toward the diffuse
(≈ 1.0) late field, matching the target.
Honest status. This is a faithful, runnable first pass, not a tuned reproduction of every number in the paper:
- The core contribution — differentiable, learnable delay lines with gradients flowing to the delay lengths — is implemented and verified (the delays receive non-zero gradients and update during training).
- The FDN here uses broadband (frequency-independent) absorption
γ, as in the paper's decoupledA = U·diag(γ). Frequency-dependent attenuation filters (graphic-EQ / one-pole absorbers forT60(f)) are a natural next step and are listed in the roadmap. - Loss curves oscillate under the paper's aggressive lr = 0.1; a scheduler or smaller lr trades a little final accuracy for smoother convergence.
- Numbers were validated on a synthetic target for reproducibility. Quantitative agreement with the paper's reported errors on standard RIR datasets (e.g. differences in T60/EDT/echo density) has not yet been benchmarked, and blind RIR estimation (see the wall, above) is out of scope.
- Frequency-dependent absorption — replace scalar
γwith per-line one-pole / graphic-EQ attenuation filters soT60(f)is matched band-by-band. - Real RIR datasets — turnkey loaders + benchmarks on public corpora (Motus / MIT Acoustical Reverberation, OpenAIR, ARNI, dEchorate) reporting T60, EDT, C50 and echo-density error.
- Hugging Face Space demo — upload a RIR → fit → hear and see the reverb in
the browser, so the project is discoverable via HF Papers (see
HF_SPACE_PLAN.md). - Differentiable-acoustics family — this FDN sits alongside differentiable Scattering Delay Networks and other data-driven reverberators; shared loss and RIR-analysis tooling could grow into a small library.
If you use this implementation or the accompanying paper, please cite the paper (Zenodo, DOI 10.5281/zenodo.22683508):
@misc{martins2026inverting,
title = {Inverting the Room: Differentiable Feedback Delay Networks for
Reverb Extraction and Dereverberation},
author = {Martins, Nicholas},
year = {2026},
publisher = {Zenodo},
doi = {10.5281/zenodo.22683508},
url = {https://doi.org/10.5281/zenodo.22683508}
}…and the original paper this work builds on:
@article{mezza2024fdn,
title = {Data-driven room acoustic modeling via differentiable feedback
delay networks with learnable delay lines},
author = {Mezza, Alessandro Ilic and Giampiccolo, Riccardo and
De Sena, Enzo and Bernardini, Alberto},
journal = {EURASIP Journal on Audio, Speech, and Music Processing},
volume = {2024}, number = {1}, pages = {51}, year = {2024},
doi = {10.1186/s13636-024-00371-5}
}This is an independent, third-party reimplementation for research and educational use; it is not affiliated with or endorsed by the original authors. Method credit is theirs; any bugs here are mine.
MIT.
