Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Backend conformance & build fixes (CLAP/VST2/VST3) — fixes #153, part of #154#160

Merged
jcelerier merged 5 commits into
mainfrom
ui-split-1-backend-fixes
Jul 6, 2026
Merged

Backend conformance & build fixes (CLAP/VST2/VST3) — fixes #153, part of #154#160
jcelerier merged 5 commits into
mainfrom
ui-split-1-backend-fixes

Conversation

@jcelerier

@jcelerier jcelerier commented Jul 6, 2026

Copy link
Copy Markdown
Member

Backend fixes extracted from the custom-UI branch — nothing here touches UI; every change is a host-conformance or build fix for the existing CLAP/VST2/VST3 bindings.

Fixes

  • Zero-filled channels: the effect is never handed null channel pointers; short host buffers get binding-owned silent scratch (wrappers/process/base.hpp, plus null rows inside host buses pointed at zero/trash scratch sized at activate).
  • clap: 29 example plug-ins crash (0xc0000005) in clap-validator processing tests #153/vst3: components with no audio buses fail the Steinberg validator (param-only objects, analyzers) #154 conformance sweep (debugged against clap-validator + the Steinberg validator; 53/85 → 84/85 fully-passing clap-validator runs):
  • Host-callback fallbacks (avnd::wire_fallback_callbacks): worker.request / request_channels members are never left as empty std::functions — calling one terminates under -fno-exceptions.
  • cmake: FMT_MODULE=OFF default (fmt ≥ 12 would require a module-scanning toolchain); CLAP headers fetched when absent; AVND_FETCH_VST3_SDK=ON fetches the SDK (v3.7.14_build_55); the fetched SDK's base library gets its missing pluginterfaces link dependency declared — without it every plug-in ships with undefined Steinberg::FUID::* under GNU ld.

Validation

  • Linux (clang 19): clean build, 100/100 tests; clap-validator and Steinberg validator spot-checks pass.
  • The full sweep on the tip of the stack: 84/85 clap-validator (the 85th is a clap-validator bug: note_ports.rs queries output ports with is_input=true), zero VST3 validator crashes.

Part 1/3 of splitting the custom-UI work; #161 (UI concepts + Tier C + message bus) and #162 (reference software UI) stack on top.

🤖 Generated with Claude Code

The process adapters (process/ and process_bus/, per-channel and poly) already
had storage to point missing channels at silent scratch buffers, but it was
gated behind a commented-out AVND_ENABLE_SAFE_BUFFER_STORAGE, so by default a
host supplying fewer channels than the object declares left bus.channel = nullptr
-- any effect that dereferences its channel then crashes. That null path is a
core-invariant violation: an effect must always receive valid, zero-filled
channel buffers.

Enable the safe buffer storage by default (opt out with
-DAVND_ENABLE_SAFE_BUFFER_STORAGE=0). process_bus/base.hpp includes
process/base.hpp, so this one definition covers every backend.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_011s7huWR2wFsLFiMJPjx1z2
jcelerier and others added 4 commits July 6, 2026 12:41
Debugged with cdb against clap-validator and the Steinberg validator;
seven distinct defects, taking the examples from 53/85 fully passing
clap-validator runs to 84/85:

- clap: 32/64-bit sample format is a per-process() host decision
  (SUPPORTS_64BITS is capability, not contract): read whichever of
  data32/data64 the host filled; the adapters convert. Was: double
  processors dereferenced a null data64 on every float host.
- clap: allocate float AND double conversion storage in start() (the
  float->double path had a null destination — the second crash class).
- clap: null channel rows inside host buses are pointed at binding-owned
  zero/trash scratch (sized at activate) — no adapter dereferences null.
- clap: note ports declared no dialects (preferred_dialect = 0 is
  invalid): supported = MIDI|CLAP, preferred MIDI.
- clap: multi-bus plug-ins reported the plug-in-wide channel total and
  CLAP_PORT_STEREO on every port: each port now reports its own count.
- clap: values-list controls (combos) reported min=max=0: 0..N-1 stepped.
- clap+vst3: channel-port effects (mono .channel members — analyzers like
  essentia Entropy) used the *bus* introspection in bus_info, reporting
  zero buses (#154); use the channel introspection. The vst3 no-match
  default also derives its buses from the wrappers' channel counts now.
- all three bindings: sample-accurate control ports get their per-buffer
  storage reserved at activate and cleared around process() — effects
  read the `values` arrays which were dangling (heap-garbage crash in
  SampleAccurateControls).
- clap: host-callback members are never left as empty std::functions
  (bad_function_call terminates under -fno-exceptions): workers run
  inline, variable-channel requests are accepted as no-ops until CLAP
  port renegotiation is implemented.

107/107 tests pass. Remaining: avnd_test_midi_out (3 clap failures),
avnd_test_audio_variable.vst3 (validator crash), param-only test objects
under vst3 (no buses by design).

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014Zm2k4dsLp2jMa47zyLcSZ
worker.request and variable_audio_bus::request_channels are std::function
members the effect calls expecting the binding to have wired them; left
empty, the call terminates the process under -fno-exceptions
(bad_function_call cannot unwind — this crashed TestWorker and
TestAudioVariableChannels under both clap-validator and the Steinberg
validator). New avnd::wire_fallback_callbacks (wrappers/prepare.hpp) runs
workers inline and accepts channel requests as no-ops; clap, vst3 and
vintage call it at construction, richer per-binding wiring can override.

Final validator status: clap 84/85 examples fully pass (the one failure
is a clap-validator bug — note_ports output ports are queried with
is_input=true, upstream report pending); Steinberg validator: zero
crashes, all audio-bearing plug-ins pass all tests; the 58 remaining
single-failure objects are parameter-only test utilities that export no
buses by design. 107/107 tests.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014Zm2k4dsLp2jMa47zyLcSZ
… order

- CLAP: the "SDK" is plain C headers — fetch them when find_path fails.
- VST3: AVND_FETCH_VST3_SDK=ON fetches v3.7.14_build_55 (plug-in library
  only) when no VST3_SDK_ROOT is given.
- Declare base -> pluginterfaces in the fetched SDK: base uses
  FUID/FUnknown symbols but never links pluginterfaces, so with a
  single-pass linker (GNU ld) every plug-in shipped with undefined
  Steinberg::FUID::* symbols and failed to load.

Co-Authored-By: Claude Fable 5 <[email protected]>
@jcelerier jcelerier force-pushed the ui-split-1-backend-fixes branch from 1e33dce to dcf66fa Compare July 6, 2026 16:47
@jcelerier

Copy link
Copy Markdown
Member Author

Rewrote the branch after an audit of message/diff consistency: dropped the "clap: export the entry point as clap_entry" commit — its message described a fix that already exists on main, while its actual diff was an unrelated (dead, guarded) soft-UI include that belongs in #162. #162 now introduces that include itself; #161/#162 were rebased accordingly. All other commits' diffs were verified against every claim in their messages. Test status unchanged: 100/102/107 across the stack.

@jcelerier jcelerier merged commit 0eaeb50 into main Jul 6, 2026
23 checks passed
@jcelerier jcelerier deleted the ui-split-1-backend-fixes branch July 6, 2026 22:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant