Skip to content

Add amy_external_midi_output_hook to catch AMY's MIDI out - #896

Open
bwhitman wants to merge 1 commit into
mainfrom
claude/github-issue-895-2a2f5e
Open

Add amy_external_midi_output_hook to catch AMY's MIDI out#896
bwhitman wants to merge 1 commit into
mainfrom
claude/github-issue-895-2a2f5e

Conversation

@bwhitman

Copy link
Copy Markdown
Collaborator

Fixes #895

Adds amy_config.amy_external_midi_output_hook, mirroring the existing amy_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.

void my_midi_out_hook(uint8_t *bytes, uint16_t len) {
    // e.g. forward to BT MIDI out
}

amy_config_t amy_config = amy_default_config();
amy_config.amy_external_midi_output_hook = my_midi_out_hook;
amy_start(amy_config);

How it works

  • New midi_out_external_hook() helper in amy_midi.c (platform-neutral section) calls the config hook if set.
  • Every in-repo midi_out() implementation calls it first, before — and regardless of — any device interface configured in config.midi: the MCU/device layer (UART / USB gadget), the emscripten/WebMIDI build, and macos_midi.m. So the hook fires even with no serial MIDI out pin configured, per the issue.
  • The hook sees all of AMY's MIDI output: note on/off forwarding, realtime clock (0xF8/0xFA/0xFC), and sysex responses (zD dumps, transfer frames).
  • Hosts that own the whole MIDI layer (AMY_HOST_MIDI, e.g. the VCV plugin) define their own midi_out and can call the helper themselves; nothing changes for them by default.
  • Defaults to NULL in amy_default_config(); documented in docs/api.md. Godot builds are unaffected (amy_midi.c/macos_midi.m are excluded there and nothing in the stubs references the helper).

Verified with a clean macOS desktop build (make), which compiles the neutral amy_midi.c section, macos_midi.m, and the new config field together.

🤖 Generated with Claude Code

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>
@github-actions

Copy link
Copy Markdown
Contributor

🎛️ AMY HW CI (AMYboard bench)

Flashed this PR's AMY (LoadTestChord: 6-voice Juno patch=1, one held note every 2 s) onto the physical AMYboard and measured the smoothed render load as the chord grows — back-to-back with the same sketch built at the PR's merge base, so Δ is this PR's own cost. Each build is flashed once and captured 3 times (board reset between runs); the numbers are per-run means.

PASS — the bench ran the test to completion.

notes held main @ 73da71e this PR Δ
1 1603 1624 +21
2 1800 1824 +24
3 2482 2507 +25
4 2720 2744 +24
5 3465 3493 +28
6 3673 3705 +32

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 tools/arduino_loadsweep/.

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.

Please implement a way to catch Amy's midi out

1 participant