Add amy_external_midi_output_hook to catch AMY's MIDI out - #896
Conversation
Adds a config hook, mirroring amy_external_midi_input_hook, that is called with every run of bytes AMY sends over MIDI out -- before, and regardless of, any device interface configured in config.midi. This lets hosts forward AMY's MIDI output to transports AMY doesn't drive itself, e.g. BLE MIDI on a custom ESP32-S3 board. Every in-repo midi_out() implementation (device layer, emscripten, macos_midi.m) calls the new midi_out_external_hook() helper first. Hosts that own the MIDI layer entirely (AMY_HOST_MIDI, e.g. the VCV plugin) define their own midi_out and can call the helper themselves. Fixes #895 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🎛️ AMY HW CI (AMYboard bench)Flashed this PR's AMY (LoadTestChord: 6-voice Juno ✅ PASS — the bench ran the test to completion.
Full chord settled render μs: 3703 (was 3673, Δ +0.8%) (peak 3711, 117 samples, mean of 3 runs) per-run full-chord μs — this PR: 3704 / 3702 / 3703 · main @ 73da71e: 3674 / 3672 / 3672 ⬇️ Artifacts: serial log · load trace · report Self-hosted bench (amyboardci). FAIL means only that the test could not run — the load values are informational, with no threshold and no audio compare. See |
Fixes #895
Adds
amy_config.amy_external_midi_output_hook, mirroring the existingamy_external_midi_input_hook, so hosts can catch everything AMY sends over MIDI out and forward it to transports AMY doesn't drive itself — e.g. BLE MIDI on a custom ESP32-S3 board, as requested in the issue.How it works
midi_out_external_hook()helper inamy_midi.c(platform-neutral section) calls the config hook if set.midi_out()implementation calls it first, before — and regardless of — any device interface configured inconfig.midi: the MCU/device layer (UART / USB gadget), the emscripten/WebMIDI build, andmacos_midi.m. So the hook fires even with no serial MIDI out pin configured, per the issue.zDdumps, transfer frames).AMY_HOST_MIDI, e.g. the VCV plugin) define their ownmidi_outand can call the helper themselves; nothing changes for them by default.NULLinamy_default_config(); documented indocs/api.md. Godot builds are unaffected (amy_midi.c/macos_midi.mare excluded there and nothing in the stubs references the helper).Verified with a clean macOS desktop build (
make), which compiles the neutralamy_midi.csection,macos_midi.m, and the new config field together.🤖 Generated with Claude Code