midi_cc_output: echo parameter changes out as MIDI CCs (#1175, part 2) - #1194
Conversation
iC<C>,<L>,<N>,<X>,<O>,<P>[,<OSC>][,<P>,<OSC>...] The converse of midi_cc's direct-parameter form: when synth parameter P changes at voice-relative OSC, its value goes out as CC C with the L,N,X,O mapping inverted, so the same arguments on ic and iC round-trip every 0..127 value unchanged. - Hooked at the top of amy_event_to_deltas_queue for synth events, before bus-only events return and bus distortion fields are spent, and only for the live delta queue (not events stored into a patch). - Channel: the synth's MIDI note_output channel, else the synth number; a synth outside 1..16 with neither sends nothing, with a warning when the mapping is made. - A change that arrived over MIDI isn't echoed unless the note output sets forward_midi_in, so ic + iC on one CC is not a feedback loop. - Sent on change only. An event naming no osc counts for every osc; the shared distortion fields are matched by scope (osc named or not). - Output mappings live in their own list: they never answer an incoming CC or make a MIDI channel active. iC<C> / iC255 clear; the state dump emits them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PykXkeeWw2aRpC6PLfpqTQ
🎛️ 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: 2628 (was 2626, Δ +0.1%) (peak 2630, 39 samples) ⬇️ 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 |
⛓️ tulipcc integration PR openedThis merge was pinned into tulipcc for full-system CI: shorepine/tulipcc#1381 Test it there and merge that PR to move tulipcc onto this AMY. |
Part 2 of #1175, following #1191:
midi_cc_output, the converse ofmidi_cc's direct-parameter form.When parameter
Pof the synth changes at voice-relativeOSC, the new value is sent out as CCC, with theL,N,X,Omapping inverted. The same arguments onicandiCround-trip every 0..127 value unchanged; the test asserts this for linear and log (with offset) maps. The synth's own voices still get the change.Behaviour, as agreed on the issue
note_outputMIDI channel if it has one, otherwise the synth number. A synth outside 1..16 with no MIDI note output sends nothing, and making such a mapping prints a warning rather than guessing a channel.note_outputsends notes. Sequenced changes go out on their step; an event scheduled for later withtime=sends early.Details
amy_event_to_deltas_queuefor events with a synth. It has to be there because:patches_event_has_voices;amy_event_get_paramreads the value back from the sameparam_fieldstablemidi_ccuses to write it, so values are compared inamy.send()units. Matching rules:PARAM_DIST_MIXandPARAM_BUS_DIST_MIXare told apart.forward_midi_in. SoicandiCon the same CC don't form a loop.P,OSCpairs, one event sends at most one CC.iCwith a wire-command template is refused, since there's nothing for an output to run.iC<C>andiC255clear mappings.yield_synth_commandsemits them (codes 256..383) so they survive a state dump.midi_cc_output;godot/amy.gdandamy_api.generated.jsregenerated.Tests
tests/test_midi_cc_output.c, 29 checks. It covers:forward_midi_inmake ctest: all pass.make test: 90 / 43 at ~-99 dB, identical to unchangedmainin this environment.Not in this PR: the
note_outputcounterpart of the stored-patch guard (it sends notes from events being stored into a patch). That's a separate one-line fix.🤖 Generated with Claude Code
https://claude.ai/code/session_01PykXkeeWw2aRpC6PLfpqTQ
Generated by Claude Code