5 Commits
Author SHA1 Message Date
TalonandClaude Opus 5 0acb7d58f6 Play preview through the edited track's instrument
StuffMIDIMessage feeds the virtual MIDI keyboard, which only reaches
tracks that are armed and monitoring -- normally not the track whose
item you are editing. Opening an item in grid mode therefore sounded
every preview through whatever instrument happened to be armed, which
is confusing when the notes you are writing come back in the wrong
voice.

Grid mode now borrows the record routing: the edited take's track is
armed and monitoring with all MIDI inputs (anything narrower can
exclude the virtual keyboard), and every other armed track is stood
down so it cannot answer as well. The prior arm, monitor and input of
each track touched is saved by GUID in transient ExtState.

routePreview re-points lazily, so moving the editor to an item on
another track costs nothing until the target actually changes. The
daemon hands the routing back when grid mode goes off, when the editor
closes, or on exit -- the same way it already restores the loop and
repeat state the loop-bar action borrows -- so the project is put back
even if grid mode is never toggled off.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 00:55:25 +02:00
Talon bf69961412 Halve the bar-stop lead, and add exact bar looping
60ms was too blunt: at 180 BPM a 32nd note is 42ms, so the lead swallowed the
final 32nd of the bar, and it swallowed a whole 32nd from 125 BPM upward.

Testing against GetPlayPosition2 rather than GetPlayPosition removes the
render-ahead from the equation -- it reports the block about to be rendered
rather than what is currently audible -- so the lead only has to cover the
daemon's polling interval, not both delays. 35ms suffices, which is safe for
32nds to about 214 BPM.

Polling cannot do better than its own interval, so for genuine precision
Ctrl+Alt+Shift+Space loops the bar via the loop points instead, letting the
audio engine own the boundary. That is sample accurate at any tempo or grid
size. It borrows loop range and repeat state; the daemon restores both once
transport stops, including when stopped with Space.
2026-08-14 20:43:24 +02:00
Talon 39cdbeef1d Stop bar playback before the bar line, not on it
Playing a single bar still triggered notes placed exactly on the next bar
line. Two delays stack: the daemon polls at roughly frame rate, so it can
notice up to ~33ms late, and REAPER renders audio ahead of the play position
it reports, so the note has already reached the instrument before the stop
lands.

Stopping 60ms early clears both. The cost is a few milliseconds off the tail
of the bar, which is inaudible, and the benefit is that the downbeat you were
trying to exclude stays excluded. Tunable via the stoplead ExtState for setups
with large audio buffers.
2026-08-14 20:39:01 +02:00
Talon fc378e733b Add play-current-bar-only
Ctrl+Alt+Space plays the cursor's bar and stops at the next bar line, so the
same bar can be fired repeatedly while nudging a note without reaching for
stop. Alt+Space keeps its play-onwards behaviour.

The stop is performed by the preview daemon rather than the action script: a
script that stayed alive waiting for the bar to end would bring back REAPER's
"already running" prompt on the next press, which is the problem the daemon
exists to avoid. Stopping transport can move the edit cursor depending on
preferences, and the edit cursor is the grid cursor, so the daemon restores it.

A short arming window covers the gap between requesting playback and the
transport reporting as playing, so the pending stop is not cancelled instantly.
2026-08-14 20:04:20 +02:00
Talon 8fd6f947ed Accessible grid-based MIDI entry mode for REAPER
Keyboard- and speech-driven step entry for the MIDI editor, built for use
with OSARA. Arrows walk grid cells and scale degrees, Enter toggles notes,
and every position is spoken and auditioned.

Uses REAPER's own edit cursor and active_note_row rather than private cursor
state, so grid mode and OSARA editing stay in sync. Grid size comes from
MIDI_GetGrid(), so existing grid keybindings drive it. When grid mode is off,
every bound key forwards to its previous action.

Preview timing lives in a background daemon so the action scripts can exit
immediately -- a script still alive on the next keypress triggers REAPER's
"already running" prompt and breaks key repeat.
2026-08-14 18:13:45 +02:00