VST reference datasets

faustax_vst_datasets builds paired (dry, wet) training datasets from reference VST3 plugins. These datasets supply the data for a Faustax parameter-estimation fit. Render the source material through the reference effect at known parameter settings. Then fit a Faust model against the (dry, wet) pairs.

uv sync --extra vst-datasets

The extra installs DawDreamer ≥ 0.9 and audiotree. DawDreamer is the VST3 host and has wheels through CPython 3.14. audiotree is the dataset format. The package is intentionally separate from faustax. The rendering modules import DawDreamer at module scope, before JAX loads. This import order is a precaution for platforms where the reverse import order caused failures. An import of any name from faustax.* loads JAX first. The consumer-side modules (treeset_filter, windowing, synthetic_inputs) use only numpy and operate without DawDreamer.

Rendering uses worker threads, not processes. DawDreamer 0.9 releases the GIL during renders. Thus the threads render concurrently in one process. This design does not start a process for each worker, and it does not pickle objects. DawDreamer pins engine and processor creation to the first thread that created one. Creation from a different thread causes a deadlock. We observed this deadlock on macOS. Thus the driving thread owns each render station. A render station is the engine, the plugin, the playback processor, and the loaded graph. VSTWindowSource.prepare_render_stations(n) builds the render stations. The worker threads only load audio (set_data), set parameters, and render. (VSTWindowSource stays picklable for process-based loaders such as grain, also after rendering. The render stations are per-process runtime state. Pickling removes the render stations.)

The components

Module / entry point

Role

faustax-vst-treeset (export_treeset)

CLI: sweep a plugin’s parameters per a JSON spec and write a self-describing audiotree TreeDataSource of short mono windows. Start here; --list-params introspects any plugin.

faustax-vst-stereo-dataset (stereo_dataset)

CLI: the long-window, stereo counterpart for time-based effects (reverb/delay) — per-material sources, musical windowing plus pristine measurement probes, streamed parallel rendering with bounded memory.

window_source

The library piece under both CLIs: VSTWindowSource, a RandomAccessDataSource rendering windowed material through any automatable VST3 at sampled parameter settings (ParamSpec grid/random/fixed), plus parameter-range introspection (param_range_rows, norm_to_phys, step_centers).

windowing

Shared pure-numpy windowing: saliency retry, warmup lead-in, dry fade-in, input-gain augmentation.

plugin_health

One-time plugin probe (noise → liveness/finiteness, silence → state retention) on a throwaway instance.

treeset_filter

Filter a written treeset by recording source (material name, mat_id, or audiotree .source).

faustax-synthetic-inputs (synthetic_inputs)

Deterministic measurement probes (log sweep, pink noise, impulse, multitone, stepped sine) to use as materials.

The output data

Each sample is the pytree {"dry": AudioTree, "wet": AudioTree}. The extras of the wet tree contain the per-window values. Each varied parameter appears twice: p:<name> and phys:<name>. p:<name> is the normalized value in [0, 1], the domain of set_parameter. phys:<name> is the physical display value. The extras also contain the mat_id material tag. The .source strings of the two trees give the name of the recording material. The manifest metadata records the plugin, a full parameter table, the material legend, and the plugin-health report. The parameter table contains indices, defaults, step counts, physical ranges, and per-step display text. Thus a fit reads all the data back through audiotree.sources.TreeDataSource(out_dir), without an installed plugin:

from audiotree.sources import TreeDataSource
from faustax_vst_datasets.treeset_filter import select_by_material

ds = TreeDataSource("data/plug_treeset")
drums = select_by_material(ds, "drums")
wet = ds[0]["wet"]
wet.extras["p:Decay"]      # normalized, re-drives the plugin
wet.extras["phys:Decay"]   # display units, for plots and sanity checks

A minimal spec

{
  "plugin": "/path/to/Plug.vst3",
  "sample_rate": 48000,
  "window_seconds": 0.34,
  "warmup_seconds": 0.12,
  "ingain_db": [-14.0, -2.0],
  "materials": ["inputs/drums.wav"],
  "slots_per_cell": 20,
  "params": [
    {"name": "Drive", "grid": [0.0, 0.5, 1.0]},
    {"name": "Level", "random": [0.4, 1.0]},
    {"name": "Mode", "steps": "all"}
  ]
}

The material paths are absolute paths or paths relative to the spec file. Set "reinstantiate_per_render": true for long-tail effects (reverb, delay). This setting prevents the tail of one window from entering the next window.

Testing against a real plugin

The unit tests run in all environments. The end-to-end tests render through a real plugin. An environment variable enables the end-to-end tests:

FAUSTAX_TEST_VST3=/path/to/DragonflyHallReverb.vst3 uv run pytest tests/test_vst_dataset_e2e.py

The GitHub releases of Dragonfly Hall Reverb contain Linux/macOS/Windows builds. These builds load headless. In headless mode, the GUI toolkit of the plugin can write a attempt to map invalid URI message on stderr. This message is harmless.