Phase 1: import .vstpreset in offline render (loadSerializedState)

daw_vst_bridge --render now applies a VST3 preset when job has 'preset'
(base64 of a .vstpreset file). Parse the SDK binary chunk format with
PresetFile (vst3sdk), rewrap component/controller state into the bridge
blob [4B BE compLen][comp][4B BE ctrlLen][ctrl] and apply via
loadSerializedState before rendering. SF2/SFZ ignore preset (warning).
Bad base64/magic/chunks fail the job with rc 1 and no partial clip.

Tests: golden Nexus .vstpreset fixture; VST3 with/without preset,
bad preset -> rc 1, non-VST3 preset ignored. 20/20 pass.
This commit is contained in:
2026-08-17 10:44:13 +07:00
parent 4d1a2ed54a
commit bbb11f8066
6 changed files with 175 additions and 3 deletions
@@ -90,6 +90,56 @@ def main():
check("bad plugin_path -> rc 2", rc == 2, f"rc={rc}")
check("bad render removes partial out", not os.path.exists(out), "no clip left behind")
# 5. VST3 render (Nexus) - baseline without preset
NEXUS = r"C:\Program Files\Common Files\VST3\Nexus.vst3"
GOLDEN = os.path.abspath(os.path.join(os.path.dirname(__file__), "golden", "nexus_default.vstpreset"))
if os.path.exists(NEXUS) and os.path.exists(GOLDEN):
import base64
with open(GOLDEN, "rb") as f:
preset_b64 = base64.b64encode(f.read()).decode("ascii")
job = os.path.join(td, "vst3.json"); out = os.path.join(td, "vst3.wav")
rc, log = run_render(make_job(0, NEXUS, td), out)
if rc == 0 and os.path.exists(out):
frames, rms = read_wav(out)
check("VST3 render exit 0", rc == 0, log.strip().splitlines()[-1:] or "")
check("VST3 exact duration", frames == TOTAL, f"{frames} == {TOTAL}")
check("VST3 non-silent", rms > 0.001, f"rms={rms:.5f}")
else:
check("VST3 render exit 0", False, f"rc={rc} {log[-400:]}")
# 6. VST3 render WITH .vstpreset - same default state, must still
# render (proves the parse + loadSerializedState path runs).
job = os.path.join(td, "vst3p.json"); out = os.path.join(td, "vst3p.wav")
jobdict = make_job(0, NEXUS, td); jobdict["preset"] = preset_b64
rc, log = run_render(jobdict, out)
if rc == 0 and os.path.exists(out):
frames, rms = read_wav(out)
check("VST3+preset exit 0", rc == 0, log.strip().splitlines()[-1:] or "")
check("VST3+preset exact duration", frames == TOTAL, f"{frames} == {TOTAL}")
check("VST3+preset non-silent", rms > 0.001, f"rms={rms:.5f}")
check("VST3+preset applied (log)", "preset imported" in log, "log has preset imported")
else:
check("VST3+preset exit 0", False, f"rc={rc} {log[-400:]}")
# 7. Corrupt preset (not base64) -> rc 1, no partial clip
job = os.path.join(td, "vst3bad.json"); out = os.path.join(td, "vst3bad.wav")
jobdict = make_job(0, NEXUS, td); jobdict["preset"] = "!!!not-base64!!!"
rc, log = run_render(jobdict, out)
check("VST3 bad preset -> rc 1", rc == 1, f"rc={rc}")
check("bad preset removes partial out", not os.path.exists(out), "no clip left behind")
# 8. Non-VST3 with preset: ignored (warning), still renders fine
job = os.path.join(td, "sf2p.json"); out = os.path.join(td, "sf2p.wav")
jobdict = make_job(2, SF2, td); jobdict["preset"] = preset_b64
rc, log = run_render(jobdict, out)
if rc == 0 and os.path.exists(out):
frames, rms = read_wav(out)
check("SF2+preset exit 0 (ignored)", rc == 0, log.strip().splitlines()[-1:] or "")
check("SF2+preset non-silent", rms > 0.001, f"rms={rms:.5f}")
else:
check("SF2+preset exit 0 (ignored)", False, f"rc={rc} {log[-400:]}")
failed = [n for n, ok, _ in results if not ok]
print()
print(f"{len(results) - len(failed)}/{len(results)} passed")