menuband: shift/capslock linger mode + slim layout + multi-channel synth fix
YWFT font now sticks while dragging through the instrument-map preview.
The hover handler used to set instrumentReadout.stringValue, which wipes
the field's attributedStringValue (font + Riso shadow) back to defaults
mid-drag. Both the committed-update path and the hover-drag path now
funnel through a shared applyInstrumentReadoutStyle helper.
New .fullSlim display tier sits between .full and .oneOctave: 2 octaves
at whiteW=17 / blackW=10 (~74% of normal). Saves 84px on the menubar
before having to drop an octave. Pinned via the `forceLayout`
UserDefaults key for testing.
Shift held OR caps lock latched arms linger / bell-ring mode:
- Menubar piano labels render uppercase as the visual cue
- A small accent tilde flourish appears at the top-right of the
music note glyph
- Sustained voices (pianos, organs, strings) skip the immediate
noteOff so the synth's release envelope rings; cleanup pair
fires at +6s
- Staccato voices (mallets, plucks, percussive family) get a
doppler retrigger tail — exponentially decaying velocity over
growing intervals, tail caps at ~7s. Voices categorized via
GeneralMIDI.lingerCategory(for:).
- Live notes round-robin channels 0-3, doppler retriggers use
channels 4-7 (independent rotators) so a fresh press of the
same key never cuts the still-decaying linger
MenuBandSynth was hardcoding melodic noteOn/Off to status 0x90/0x80
(channel 0 only) regardless of the channel argument, so all the
"round-robin" allocation collapsed to a single synth voice. Fixed:
noteOn/Off now mask the channel into the status byte, and
selectMelodicProgram broadcasts bank+PC to channels 0-7 so every
rotation channel plays the chosen voice.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>