music realtime: CoreMIDI steering for Magenta RT2 (OP-1 and friends) - #137
Merged
Conversation
Adds live MIDI control to `music realtime` on macOS: --list-midi-inputs, --midi-input (source name or unique ID), --midi-channel, --midi-note-offset, and repeatable --midi-cc target mappings (cc=target:min:max) covering the same controls as interactive stdin steering. The former private interactive controls class is extracted as MagentaRT2LiveControlQueue and shared by the stdin and MIDI paths. Review hardening on top of the initial implementation: - Packet iteration now uses MIDIPacketList.unsafeSequence(). The previous loop copied MIDIPacket into a local and called MIDIPacketNext on the copy, which walks past the copy's storage and reads garbage whenever a packet list carries more than one packet (chords, CC sweeps). - MIDI byte parsing is extracted into MagentaRT2MIDIStreamParser, a pure incremental MIDI 1.0 parser that supports running status (previously dropped every message after the first under a shared status byte), survives system-realtime bytes interleaved mid-message and messages split across packet boundaries, advances correctly past pitch-bend and program-change messages, and normalizes velocity-0 note-on to note-off. Being platform-independent, it is unit-tested directly. - Ambiguous --midi-input substring matches now fail with the candidate list instead of silently binding the first match. - The stdin reader task is only spawned in interactive mode, and the live control queue's snapshot() drops its unused frame-index parameter. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # CHANGELOG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Feature
Live MIDI control for
music realtimeon macOS:--list-midi-inputs— enumerate CoreMIDI sources (name | manufacturer | model | unique ID)--midi-input <name-or-id>— connect a source; exact-ID and exact-name matches win, substring matches must be unambiguous--midi-channel all|1-16,--midi-note-offset <n>--midi-cc cc=target:min:maxmappings (temp,topk,mc,notes,drums,drumless,unmask,seed,onset)Note-on/off and mapped CCs feed the same
MagentaRT2LiveControlQueueas interactive stdin steering (the former private interactive-controls class, extracted toSupport/and shared by both paths). Prompt changes stay on stdin — the prompt encoder swap can stall a frame, so MIDI is for notes and continuous controls (matching the engine constraints established in #132).Review hardening on top of the initial implementation
MIDIPacketinto a local and calledMIDIPacketNexton the copy — that walks past the copy's stack storage and reads garbage whenever aMIDIPacketListcarries more than one packet (chords, CC sweeps, clock+note bursts). Now usesMIDIPacketList.unsafeSequence()and reads the true variable-length payload via thedatafield offset.MagentaRT2MIDIStreamParser) that keeps running status across packet boundaries, tolerates system-realtime bytes (clock, active sensing) interleaved mid-message, advances correctly past pitch-bend/program-change, and normalizes velocity-0 note-on to note-off per spec.snapshot()drops an unused parameter.Validation
swift test --filter MusicGenerateCommandParsingTests: 19 tests, 0 failures (7 new: 3 CLI/mapping parsing from the original work, 4 parser protocol tests from review).docs/cli.md,docs/runtime/music.md, themusic-generateguide, README example, and CHANGELOG.🤖 Generated with Claude Code