Automatic Differentiable Audio Compilation
from differentiable audio research to efficient real-time DSP
researchers design and optimise audio processors in differentiable frameworks such as FLAMO, but deploying them as real-time plugins requires manual reimplementation. this is error-prone and creates a gap between research prototypes and usable tools. the worked example throughout is the feedback delay network (FDN), which exercises every part of the compiler.
before: FLAMO model (PyTorch) → ??? → real-time plugin
↑
manual rewrite
after: FLAMO model (PyTorch) → adac → FAUST → plugin
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ FLAMO │ ───▶ │ JSON │ ───▶ │ FAUST │
│ model │ ◀─── │ config │ │ code │
│ (PyTorch) │ │ │ │ (.dsp) │
└──────────────┘ └──────────────┘ └──────────────┘
flamo_to_json() ──▶ json_to_faust() ──▶
json_to_flamo() ◀──
╰───────────── flamo_to_faust() ──────────────╯
the pipeline traverses a FLAMO model graph, extracts all parameters (delays, gains, matrices, filters), serialises them to a JSON intermediate representation, and generates valid FAUST DSP code. extraction is map-aware: matrix types with non-identity maps (orthogonal, hadamard, householder) serialise the effective matrix the model applies, with the raw trainable weights preserved for round-tripping. json_to_flamo reconstructs the original model from the config.
on top of the codegen core:
HotReloadrepublishes the model to a running FAUST plugin during training, so you hear the optimisation while it runs- macro-controls (
rt60,dry_wet,pre_delay) add performance knobs to the generated plugin without touching the trained parameters certifycomputes a stability certificate for every feedback loop, written as.cert.jsonnext to the.dspexport_juceturns a config into an installed VST3/AU plugin in one call
pip install -e .for full FLAMO model support (requires PyTorch):
pip install -e ".[full]"building plugins additionally requires the FAUST distribution and JUCE.
import adac
#given a trained FLAMO model and sample rate
faust_code = adac.flamo_to_faust(model, fs=48000, name="MyReverb")
#write to file
with open("reverb.dsp", "w") as f:
f.write(faust_code)or use the two-step pipeline for inspection:
config = adac.flamo_to_json(model, fs=48000, name="MyReverb")
faust_code = adac.json_to_faust(config, controls={"rt60": True, "dry_wet": True})live = adac.HotReload(fs=48000, name="MyReverb", controls={"rt60": True})
for step in range(n_steps):
loss = criterion(model(x), target)
loss.backward()
optimiser.step()
live.update(model)
live.update(model, force=True)the hot-reload CLAP plugin (FAUST interpreter plus file watcher) lives in faust/architecture/clap/. reloads take about 100 ms and knob positions survive them. full script: examples/live_training.py.
adac.export_juce(
adac.flamo_to_json(model, fs=48000, name="MyReverb"),
"exported/", name="MyReverb",
controls={"rt60": True, "dry_wet": True, "pre_delay": True},
juce_modules="~/JUCE/modules",
build=True,
)one call: FAUST generation, stability certificate, JUCE project, release build, install into the user plugin folders (macOS). the export refuses to build a model whose certificate says unstable or not-certified; pass strict=False to override. full script: examples/export_plugin.py.
cert = adac.certify(config)
print(cert["verdict"])the criterion is small-gain: the product of per-element spectral norms around each feedback loop must stay below one at every frequency, evaluated on the parameter values as emitted (single precision). verdicts are certified-stable, marginally-stable, indeterminate, not-certified, unstable. a lossless prototype is marginally stable; with the rt60 control it is certified at any knob position.
generated FAUST matches FLAMO sample-exactly, direct paths included. the energy decay of the compiled plugin follows the FLAMO reference throughout, and the underlying impulse responses agree to within single-precision arithmetic noise. all four stereo paths match identically; the suite pins them.
the rt60 macro-control on the compiled plugin, measured by Schroeder integration, follows the ideal decay for the slider value:
regenerate the figures with python examples/make_plots.py.
| FLAMO module | FAUST output | description |
|---|---|---|
parallelDelay |
@(n) / de.fdelay |
integer or fractional sample delays |
Gain / Matrix |
sum-of-products function | mixing matrices (hoisted, map-aware) |
HouseholderMatrix |
sum-of-products function | emitted as the effective matrix |
parallelGain |
*(g) |
per-channel diagonal gains |
parallelSOSFilter |
fi.tf2(...) |
cascaded biquad filters |
Series |
: |
sequential composition |
Parallel |
, / :> |
side-by-side or summing |
Recursion |
~ |
feedback loops (FDN core) |
Biquad / SVF |
fi.tf2 / fi.svf.* |
single-channel filters |
Shell |
(unwrapped) | FFT wrapper skipped |
#unit tests (no external dependencies)
pytest tests/ -q --ignore=tests/integration
#integration tests (requires flamo venv + faust compiler)
pytest tests/integration/ -v200 unit tests validate the full pipeline: map-aware parameter extraction, delay quantisation, SOS normalisation, gain classification, graph traversal, code generation, macro-control wiring, multichannel arities, hot-reload publishing, certificate verdicts, and export orchestration.
integration tests compare impulse responses between FLAMO (frequency domain) and generated FAUST (time domain) sample-by-sample.
src/adac/
codegen/
flamo_to_json.py parameter extraction and graph traversal
json_to_faust.py FAUST code generation and macro-controls
json_to_flamo.py model reconstruction from JSON config
flamo_to_faust.py convenience wrapper (both steps)
hotreload.py training-time live publishing
certificate.py small-gain stability certificate
export.py JUCE plugin export
examples/
live_training.py
export_plugin.py
make_plots.py
tests/
test_flamo_to_json.py
test_json_to_faust.py
test_flamo_to_faust.py
test_param_extraction.py
test_hotreload.py
test_certificate.py
test_export.py
integration/
test_ir_comparison.py
generate_flamo_ir.py
- FLAMO — differentiable audio processing framework
- pyFDN — python feedback delay networks
- FAUST — functional audio stream
MIT — see LICENSE for details.

