Resolves the open question in TODO.md about whether WavAudioFormat's "must be 1 or 2 channels" doc comment is an enforced limit - a 5-channel plugin recorded a valid, non-silent WAV with no clamping. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JAZXxJbHD7PzdKaNE6Nuiv
6.1 KiB
6.1 KiB
testhost TODO
Tracks known gaps and future work for tools/testhost/, the generic headless
plugin test host (see README.md for what it does and how to use it, and
/home/jens/.claude/plans/sharded-finding-tower.md for the original design
plan). Nothing here blocks current use — Phases 1-4 of the plan are done and
verified (PR #1).
Deferred by design (Phase 5 of the plan)
- LV2 plugin format support. JUCE 3.1.1 (the version currently
vendored at
sdk/juce/JUCE-3.1.1) has no LV2 hosting backend. Once JaySynth's own JUCE dependency is upgraded (or a customAudioPluginFormatsubclass is written against the current version), register it inPluginHost's constructor alongsideVSTPluginFormat- no other host code should need to change, since everything downstream talks to the format-agnosticAudioPluginInstance/AudioProcessorAPI already. - VST3/LADSPA format support. JUCE already ships
VST3PluginFormat/LADSPAPluginFormatin this same vendored version - registering them is a one-line addition toPluginHost's constructor, just not done yet since nothing has needed it. - Windows build (
Makefile.win). The plan calls for mirroringsrc/plug's Linux/Windows Makefile pattern; only the Linux side has been built and tested so far.
Test coverage gaps
- Only mono (1 in/1 out) and asymmetric (2 in/1 out) effect channel
configs have been smoke-tested (
ZamDelay-vst.so,ZamComp-vst.so,ZamEQ2-vst.so). A genuinely stereo-in/stereo-out effect hasn't been run through yet - worth doing before relying on this tool for a stereo effect plugin specifically. - No automated regression baseline comparison. The plan's stretch
goal: batch-render every
.fxp/.xmpunderextras/sounds/through a fixed note pattern and diff against stored baseline WAVs/checksums, to catch DSP or save-load regressions automatically instead of via one-off manual runs. Not built. - No CI wiring. Nothing currently runs
testhostautomatically on push/PR; it's a manual, opt-in tool for now. - No unit tests for
TestScenario's JSON parsing itself (malformed JSON, missing required fields, wrong types, out-of-range values) - only exercised indirectly via a couple of hand-written scenario files during development. Edge-case handling (e.g. a negativesample, an unterminatednoteOnwith no matchingnoteOff) is untested. - Polyphony/multiple simultaneous notes untested - only ever a single held note in all smoke tests so far.
tests/run_tests.shnever asserts specific expected values forPluginHost::load()/getNumInputChannels()/getNumOutputChannels()/getNumParameters()- every test exercises them (they're printed in the load banner), but nothing pins e.g. "JaySynth must report exactly 0 in / 2 out / 140 parameters," so a regression there would only be caught if it also broke something else. Same underlying gap as "no automated regression baseline comparison" above, just called out separately since it's about the load-time metadata rather than the rendered audio. Seetests/README.md'sPluginHostcoverage table.
Investigate
- Bundled sample
.fxpfiles underextras/sounds/silently have no effect when loaded via--patch(confirmed by diffing--printParamsoutput with and without--patch- zero parameters differ), even though loading doesn't crash. Resolved: this is not a host/plugin capability mismatch -usesChunks()is genuinely true andtest_chunk_roundtripintests/run_tests.shproves the realbankEncodeXml/bankDecodeXmlchunk path round-trips correctly for files this build produces (seetests/README.md's "corrected finding" note for the full disproof). What remains open is narrower: why these specific (10+ year old) external sample files fail to apply - most likely a compression or XML-schema shape thatJaySynthAudioProcessor::setCurrentProgramStateInformation/getXmlFromBinaryno longer parses. Not one of the tracked repo-rootTODO.mdfindings; worth a closer look at some point (hex-diff one of these files' decompressed XML against what this build produces), but not chased further here. - DPF-based plugins print a non-fatal assertion on load. All three
Zam*-vst.so plugins tested (built with the DISTRHO Plugin Framework) print
assertion failure: "fIsActive" in .../DistrhoPluginInternal.hppduringPluginHost::load(), despite JUCE'sVSTPluginInstance::prepareToPlayalready sendingeffMainsChanged/effStartProcess. Rendering still completes correctly (confirmed via WAV output), so this looks like a DPF/JUCE VST2 lifecycle-ordering quirk rather than a testhost bug, but it hasn't been root-caused - worth a closer look if it turns out to affect correctness (not just log noise) for some other plugin. WavAudioFormat's base-class doc comment says channel count "must be either 1 or 2" (AudioFormat::createWriterFor's Doxygen comment).WavRecorderpasses through whateverPluginHost::getNumOutputChannels()reports with no clamping. Resolved: Pianoteq 8 (Pianoteq 8.so, V8.3.2) loads as 0 in / 5 out and rendered a held-note test cleanly through--wav- the output is a valid, non-silent 5-channel/24-bit/44.1kHz WAV (verified with Python'swavemodule: correctnchannels/nframes, non-zero sample data). No clamping or writer error occurred, so the doc comment is stale/generic boilerplate, not an enforced limit in this JUCE version.
Nice-to-have (not planned, just noted)
- A
--list-paramsor similar introspection mode (print every parameter's index/name/current value) would help writing new scenario JSON files without cross-referencing the plugin's own GUI or source. Done:--printParams(printsPARAM <index> <value>for every parameter, after any initial--patch/--bankload) - added to make the patch/bank round-trip regression tests intests/possible; only prints values, not names, so cross-referencing the plugin's own parameter-name list is still occasionally needed.