diff --git a/MidiGrid_PlayFromBar.lua b/MidiGrid_PlayFromBar.lua new file mode 100644 index 0000000..c87f31b --- /dev/null +++ b/MidiGrid_PlayFromBar.lua @@ -0,0 +1,12 @@ +--[[ + MIDI Grid: play from the start of the bar the cursor is in. + + Deliberately works whether or not grid mode is on -- it is a listening aid, + not an editing action, and it is just as useful while navigating with OSARA + normally. Stop with Space as usual. +]] +local dir = ({ reaper.get_action_context() })[2]:match("@?(.*[\\/])") +local G = dofile(dir .. "midigrid_lib.lua") + +local bar = G.playFromBar() +G.say("Playing from bar " .. bar) diff --git a/README.md b/README.md index dbef4a7..0efd734 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ actions by hand in Actions → Show action list. That always works. | `Alt+Shift+Up` / `Alt+Shift+Down` | Velocity up / down | — | | `Alt+G` | **Toggle grid mode on/off** | — | | `Alt+H` | Toggle hold mode | — | +| `Alt+Space` | Play from start of the current bar | works in both modes | | `Alt+A` | Repeat current cell (speak + sound) | — | | `Alt+S` | Set root and scale | — | | `1`–`9` | Grid size — REAPER's own grid actions | same | @@ -149,6 +150,22 @@ survive. They also need no mode: `L` behaves identically whether hold is on or off, so there is no state to set up beforehand and none to remember to turn off afterwards. +## Hearing it in context + +`Alt+Space` plays from the **top of the bar the cursor is in**, and says which +bar. Stop with `Space` as usual. + +Auditioning a cell tells you what a note *is*; playing from the downbeat tells +you whether it is in the right *place*. At 16ths or 32nds that difference is +the whole question, and it cannot be judged from a note in isolation. + +Your position is preserved. The edit cursor doubles as the grid cursor, so it +is moved to the bar line only long enough to start playback and then put +straight back — you carry on editing exactly where you were. + +This one works whether or not grid mode is on, since it is a listening aid +rather than an editing action. + ## Shifting notes in time If a whole clip landed a couple of cells off the beat, `Ctrl+Shift+Left` and diff --git a/install.ps1 b/install.ps1 index 8c32e0a..d74f718 100644 --- a/install.ps1 +++ b/install.ps1 @@ -59,7 +59,8 @@ $actions = @( @('RSmidigrid_shl', 32060, 'MIDI Grid: Shift all notes one cell left', 'MidiGrid_ShiftLeft.lua'), @('RSmidigrid_shr', 32060, 'MIDI Grid: Shift all notes one cell right', 'MidiGrid_ShiftRight.lua'), @('RSmidigrid_shlf', 32060, 'MIDI Grid: Shift all notes left (force)', 'MidiGrid_ShiftLeftForce.lua'), - @('RSmidigrid_shrf', 32060, 'MIDI Grid: Shift all notes right (force)', 'MidiGrid_ShiftRightForce.lua') + @('RSmidigrid_shrf', 32060, 'MIDI Grid: Shift all notes right (force)', 'MidiGrid_ShiftRightForce.lua'), + @('RSmidigrid_playbar',32060, 'MIDI Grid: Play from start of current bar', 'MidiGrid_PlayFromBar.lua') ) # flags, keycode, section, id @@ -86,7 +87,8 @@ $keys = @( @(13, 32805, 32060, 'RSmidigrid_shl'), @(13, 32807, 32060, 'RSmidigrid_shr'), @(29, 32805, 32060, 'RSmidigrid_shlf'), - @(29, 32807, 32060, 'RSmidigrid_shrf') + @(29, 32807, 32060, 'RSmidigrid_shrf'), + @(17, 32, 32060, 'RSmidigrid_playbar') ) $backup = "$kb.midigrid-backup" diff --git a/midigrid_lib.lua b/midigrid_lib.lua index a331fb3..79463d2 100644 --- a/midigrid_lib.lua +++ b/midigrid_lib.lua @@ -352,6 +352,41 @@ function M.toggleCell(take, pitch) return result, detail end +------------------------------------------------------------------ playback + +-- Start of the bar containing time t, plus the 1-based bar number. +function M.barStart(t) + local _, measures = reaper.TimeMap2_timeToBeats(0, t) + return reaper.TimeMap2_beatsToTime(0, 0, measures), measures + 1 +end + +--[[ + Play from the top of the bar the cursor is in, without losing your place. + + The edit cursor doubles as the grid cursor, so it is moved to the bar line + only long enough to start playback and then put straight back. Restoring it + passes seekplay=false so the restore cannot drag playback along with it. + + Playing from the bar line rather than the cursor is what makes fine + subdivisions checkable: you hear the note in relation to the downbeat, + which is the thing you are actually trying to judge. +]] +function M.playFromBar() + local here = reaper.GetCursorPosition() + local barPos, barNum = M.barStart(here) + + reaper.PreventUIRefresh(1) + reaper.SetEditCurPos(barPos, false, true) + -- GetPlayState bit 0 is "playing"; avoid bitwise ops for portability. + if (reaper.GetPlayState() % 2) == 0 then + reaper.CSurf_OnPlay() + end + reaper.SetEditCurPos(here, false, false) + reaper.PreventUIRefresh(-1) + + return barNum +end + ---------------------------------------------------------------- time shift --[[