From 7c9c6c5b4bef406d62d6923390253a551edb2bac Mon Sep 17 00:00:00 2001 From: RobU23 Date: Sun, 14 May 2017 18:48:58 +0100 Subject: [PATCH 01/33] test preliminary repeat code --- .../RobU - MIDI Ex Machina.lua | 72 ++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 8f5d424..66b54e2 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -904,9 +904,75 @@ function SetNotes() end -- m.activeTake end -------------------------------------------------------------------------------- --- InsertNotes(note_buffer) - insert notes in the active take +-- InsertNotes() - insert current note buffer in the active take -------------------------------------------------------------------------------- function InsertNotes() + local debug = false + if debug or m.debug then ConMsg("\nInsertNotes()") end + DeleteNotes() + local i = 1 + if m.activeTake then + local gridSize = m.reaGrid * m.ppqn + local itemLength = GetItemLength() + local noteShift = m.seqShift * gridSize + local t1 = GetNoteBuf() + local t2 = {} -- temp for note shifting (no undo) + CopyTable(t1, t2) + + for k, v in pairs(t2) do -- start note shifting + v[3] = v[3] + noteShift + v[4] = v[4] + noteShift + if v[3] < 0 then + v[3] = itemLength + v[3] + v[4] = itemLength + v[4] + if v[4] > itemLength then v[4] = itemLength + m.legato end + elseif v[3] >= itemLength then + v[3] = v[3] - itemLength + v[4] = v[4] - itemLength + end + end -- stop note shifting + + -- start repeat + m.repeatTimes = 2; m.repeatLength = 4 --(in grid divisions) + local repeatEnd = gridSize * m.repeatLength + local noteSize = 0 + local gridRep = 1 + local gridPos = 0 + local noteIdx = 1 + + ConMsg("\nStart repeat...") + while m.repeatTimes > 0 do + ConMsg("m.repeatTimes = " .. tostring(m.repeatTimes)) + + ConMsg("gridPos = " .. tostring(gridPos)) + gridPos = gridPos + gridSize + + m.repeatTimes = m.repeatTimes - 1 + end -- m.repeatTimes + ConMsg("m.repeatTimes = " .. tostring(m.repeatTimes)) + ConMsg("gridPos = " .. tostring(gridPos)) + + ConMsg("\nStart remainder...") + for gP = gridPos, itemLength, gridSize do + ConMsg("gridPos = " .. tostring(gP)) + end + ConMsg("itemLength = " .. tostring(itemLength)) + -- insert note buffer to the active take + --while t2[i] do + --reaper.MIDI_InsertNote(m.activeTake, t2[i][1], t2[i][2], t2[i][3], t2[i][4], t2[i][6], t2[i][7], t2[i][8], false) + --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) + --i = i + 1 + --end -- while t2[i] + reaper.MIDI_Sort(m.activeTake) + reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off + else + if debug or m.debug then ConMsg("No Active Take") end + end -- m.activeTake +end +-------------------------------------------------------------------------------- +-- InsertNotesWithShift(note_buffer) - insert notes in the active take +-------------------------------------------------------------------------------- +function InsertNotesWithShift() local debug = false if debug or m.debug then ConMsg("\nInsertNotes()") end DeleteNotes() @@ -942,9 +1008,9 @@ function InsertNotes() end -- m.activeTake end -------------------------------------------------------------------------------- --- InsertNotes(note_buffer) - insert notes in the active take +-- InsertNotesOrig(note_buffer) - insert notes in the active take -------------------------------------------------------------------------------- -function InsertNotesOld() +function InsertNotesOrig() local debug = false if debug or m.debug then ConMsg("InsertNotes()") end DeleteNotes() From d60815210fd8ac8468dc4583c02afc2e10e63d8c Mon Sep 17 00:00:00 2001 From: RobU23 Date: Mon, 15 May 2017 23:26:12 +0100 Subject: [PATCH 02/33] added GUI elements for repeat added set default repeat state added start of repeat code to InsertNotes() --- .../RobU - MIDI Ex Machina.lua | 86 +++++++++++++------ 1 file changed, 60 insertions(+), 26 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 66b54e2..cbe002e 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -113,7 +113,8 @@ m.seqGrid16 = {8, 8, 0, 4} -- sane default sequencer note length slider values m.seqGrid8 = {0, 8, 2, 2} -- sane default sequencer note length slider values m.seqGrid4 = {0, 2, 8, 1} -- sane default sequencer note length slider values m.seqShift = 0; m.seqShiftMin = -16; m.seqShiftMax = 16 -- shift notes left-right from sequencer -m.repeatStart, m.repeatEnd, m.repeatLength, m.repeatTimes = 0, 0, 0, 0 -- repeat values (currently unused) +m.repNum, m.repLenGrid, m.repMax, m.repLenPPQN = 0, 0, 0, 0 -- repeat values +m.repNumT, m.repLenGridT = {}, {} -- repeat value tables -- euclidean generator m.eucF = true -- generate euclid (option) @@ -791,8 +792,8 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) end -- newNote end -- itemPos < itemLength if debug and m.debug then PrintNotes(t) end - PurgeNoteBuf() - InsertNotes() + PurgeNoteBuf() + if not m.seqRndNotesF then InsertNotes() end end -------------------------------------------------------------------------------- -- GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) @@ -933,30 +934,36 @@ function InsertNotes() end -- stop note shifting -- start repeat - m.repeatTimes = 2; m.repeatLength = 4 --(in grid divisions) - local repeatEnd = gridSize * m.repeatLength - local noteSize = 0 - local gridRep = 1 - local gridPos = 0 - local noteIdx = 1 +--m.repNum, m.repLenGrid, m.repMax, m.repLenPPQN + t3 = {} -- temp for repeating + local repLenPPQN = m.repLenGrid * gridSize + local repStart = 0 + local repEnd = repLenPPQN + local repLoop = m.repNum + local writePos = repStart ConMsg("\nStart repeat...") - while m.repeatTimes > 0 do - ConMsg("m.repeatTimes = " .. tostring(m.repeatTimes)) - - ConMsg("gridPos = " .. tostring(gridPos)) - gridPos = gridPos + gridSize + while repLoop > 0 do + ConMsg("\nrepLoop = " .. tostring(repLoop)) + ConMsg("repStart = " .. tostring(repStart)) + ConMsg("repEnd = " .. tostring(repEnd)) + ConMsg("writePos = " .. tostring(writePos)) + for k, v in pairs(t2) do + if v[3] >= repStart and v[3] < repEnd then + if v[4] > repEnd then v[4] = repEnd end + t3[k] = {} + ConMsg("note data") + ConMsg("a - noteIdx = " .. tostring(k) .. " - Start = " .. tostring(v[3]) .. " - End = " .. tostring(v[4])) + ConMsg("b - noteIdx = " .. tostring(k) .. " - Start = " .. tostring(v[3] + writePos) .. " - End = " .. tostring(v[4] + writePos)) + t3[k][1] = v[1]; t3[k][2] = v[2]; t3[k][5] = v[5]; t3[k][6] = v[6]; t3[k][7] = v[7]; t3[k][8] = v[8]; + t3[k][3] = v[3] + writePos; t3[k][4] = v[4] + writePos + reaper.MIDI_InsertNote(m.activeTake, t3[k][1], t3[k][2], t3[k][3], t3[k][4], t3[k][6], t3[k][7], t3[k][8], false) + end -- if v[3] + end -- for k, v t2 + repLoop = repLoop - 1 + writePos = writePos + repLenPPQN + end - m.repeatTimes = m.repeatTimes - 1 - end -- m.repeatTimes - ConMsg("m.repeatTimes = " .. tostring(m.repeatTimes)) - ConMsg("gridPos = " .. tostring(gridPos)) - - ConMsg("\nStart remainder...") - for gP = gridPos, itemLength, gridSize do - ConMsg("gridPos = " .. tostring(gP)) - end - ConMsg("itemLength = " .. tostring(itemLength)) -- insert note buffer to the active take --while t2[i] do --reaper.MIDI_InsertNote(m.activeTake, t2[i][1], t2[i][2], t2[i][3], t2[i][4], t2[i][6], t2[i][7], t2[i][8], false) @@ -1172,6 +1179,11 @@ local seqAccSldrText = e.Textbox:new({2,3}, sx + (sp * 8) - (sw / 2), 210, ( local seqLegProbSldr = e.Vert_Slider:new({2}, sx + (sp * 10) - (sw / 2), sy, sw, sh, e.col_blue, "%", e.Arial, 16, e.col_grey8, m.legatoProb, 0, 0, 10, 1) local seqLegSldrText = e.Textbox:new({2}, sx + (sp * 10) - (sw / 2), 210, sw, 20, e.col_grey5, "Leg", e.Arial, 16, e.col_grey7) +-- repeat dropboxes +local seqRepLenDrop = e.Droplist:new({2}, sx + (sp * 11) + 10, sy + 15, sw * 3, 20, e.col_blue, "Length", e.Arial, 16, e.col_grey8, m.repLenGrid, m.repLenGridT) +local seqRepNumDrop = e.Droplist:new({2}, sx + (sp * 11) + 10, sy + 60, sw * 3, 20, e.col_blue, "Amount", e.Arial, 16, e.col_grey8, m.repNum, m.repNumT) +local seqRepText = e.Textbox:new({2}, sx + (sp * 11) + 10, sy + 90, sw * 3, 20, e.col_grey5, "Repeat", e.Arial, 16, e.col_grey7) + -- sequence shift buttons local seqShiftLBtn = e.Button:new({2}, sx + (sp * 11) + 10, sy + sh - 25, sw, 25, e.col_blue, "<<", e.Arial, 16, e.col_grey8) local seqShiftRBtn = e.Button:new({2}, sx + (sp * 13) - 10, sy + sh - 25, sw, 25, e.col_blue, ">>", e.Arial, 16, e.col_grey8) @@ -1212,9 +1224,10 @@ local msgText = e.Textbox:new({9}, m.win_x + 10, m.win_y + 30, m.win_w - 40, m.w -------------------------------------------------------------------------------- local t_Buttons = {randomBtn, sequenceBtn, seqShiftLBtn, seqShiftRBtn, euclidBtn} local t_Checkboxes = {noteOptionsCb, seqOptionsCb, eucOptionsCb} +local t_Droplists2 = {seqRepLenDrop, seqRepNumDrop} local t_RadButtons = {seqGridRad} local t_RSliders = {octProbSldr, seqAccRSldr, seqAccProbSldr, seqLegProbSldr} -local t_Textboxes = {probSldrText, octProbText, seqGridText, seqSldrText, seqShiftVal, seqShiftText, seqAccSldrText, seqLegSldrText, txtEuclidLabel, optText, msgText} +local t_Textboxes = {probSldrText, octProbText, seqGridText, seqSldrText, seqShiftVal, seqRepText, seqShiftText, seqAccSldrText, seqLegSldrText, txtEuclidLabel, optText, msgText} -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- @@ -1802,6 +1815,25 @@ function SetDefaultSeqShift() m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) end +-- Set default sequencer repeat state +function SetDefaultSeqRepeat() + GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) + local gridSize = m.reaGrid * m.ppqn + local itemLength = GetItemLength() + m.repNum = 1; m.repLenGrid = 1 + seqRepNumDrop.val1 = m.repNum + seqRepLenDrop.val1 = m.repLenGrid + m.repMax = math.floor(itemLength / gridSize) + for i = 1, m.repMax do + seqRepNumDrop.val2[i] = i + seqRepLenDrop.val2[i] = i + end + --[[ +m.repNum, m.repLenGrid, m.repMax, m.repLenPPQN +seqRepLenDrop, m.repLenGridT) +seqRepNumDrop, m.repNumT) +--]] +end -- Reset sequencer grid sliders seqSldrText.onRClick = function() @@ -2009,7 +2041,8 @@ function DrawGUI() for key, check in pairs(t_Checkboxes) do check:draw() end for key, radio in pairs(t_RadButtons) do radio:draw() end for key, btn in pairs(t_Buttons) do btn:draw() end - for key, dlist in pairs(t_Droplists) do dlist:draw() end + for key, dlist in pairs(t_Droplists) do dlist:draw() end + for key, dlist2 in pairs(t_Droplists2) do dlist2:draw() end --for key, knb in pairs(t_Knobs) do knb:draw() end for key, rsliders in pairs(t_RSliders) do rsliders:draw() end for key, nsldrs in pairs(t_noteSliders) do nsldrs:draw() end @@ -2061,6 +2094,7 @@ function InitMidiExMachina() SetDefaultRndOptions(); SetDefaultRndSliders() SetDefaultSeqOptions(); SetDefaultSeqShift() SetDefaultSeqGridSliders(); SetDefaultAccLegSliders() + SetDefaultSeqRepeat() SetDefaultEucOptions(); SetDefaultEucSliders() GetItemLength() From 9b00a89218da14c3d977750c9d95114fcf7166c8 Mon Sep 17 00:00:00 2001 From: RobU Date: Wed, 17 May 2017 07:36:29 +0100 Subject: [PATCH 03/33] add GUI elements for Note Repeater add preliminary repeat code (tbc - pre-repeat or post-repeat) --- .../RobU - MIDI Ex Machina.lua | 278 +++++++++++------- 1 file changed, 179 insertions(+), 99 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index cbe002e..8a0b95a 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -113,8 +113,11 @@ m.seqGrid16 = {8, 8, 0, 4} -- sane default sequencer note length slider values m.seqGrid8 = {0, 8, 2, 2} -- sane default sequencer note length slider values m.seqGrid4 = {0, 2, 8, 1} -- sane default sequencer note length slider values m.seqShift = 0; m.seqShiftMin = -16; m.seqShiftMax = 16 -- shift notes left-right from sequencer +m.loopStartG, m.loopLenG, m.loopNum, m.loopMaxRep = 0, 0, 0, 0 -- repeat values for GUI +m.t_loopStart, m.t_loopRep, m.t_loopLenG = {}, {}, {} -- repeat value tables + m.repNum, m.repLenGrid, m.repMax, m.repLenPPQN = 0, 0, 0, 0 -- repeat values -m.repNumT, m.repLenGridT = {}, {} -- repeat value tables + -- euclidean generator m.eucF = true -- generate euclid (option) @@ -139,8 +142,8 @@ m.scales = { {0, 2, 3, 5, 7, 8, 10, 12, name = "Aeolian / Minor"}, {0, 1, 3, 5, 6, 8, 10, 12, name = "Locrian"}, {0, 3, 5, 6, 7, 10, 12,name = "Blues"}, - {0, 2, 4, 7, 9, 12,name = "Pentatonic Major"}, - {0, 3, 5, 7, 10, 12,name = "Pentatonic Minor"}, + {0, 2, 4, 7, 9, 12,name = "Pentatonic Maj"}, + {0, 3, 5, 7, 10, 12,name = "Pentatonic Min"}, {name = "Permute"} } -- a list of scales available to the note randomiser, more can be added manually if required @@ -709,12 +712,13 @@ end -- RandomiseNotesPoly(noteProbTable) -------------------------------------------------------------------------------- function RandomiseNotesPoly(noteProbTable) - local debug = false + local debug = true if debug or m.debug then ConMsg("RandomiseNotesPoly()") end m.dupes.i = 1 local i = 1 local t1, t2 = GetNoteBuf(), NewNoteBuf() CopyTable(t1, t2) + if debug or m.debug then PrintNotes(t1) end while t2[i] do if t2[i][1] == true or m.rndAllNotesF then -- if selected, or all notes flag is true if i == 1 and m.rndFirstNoteF then -- if selected, the first not is always root of scale @@ -726,6 +730,7 @@ function RandomiseNotesPoly(noteProbTable) i = i + 1 end -- while t1[i] PurgeNoteBuf() + if debug or m.debug then PrintNotes(t2) end InsertNotes() if m.rndPermuteF and m.activeTake then __, pHash = reaper.MIDI_GetHash(m.activeTake, false, 0) @@ -736,7 +741,7 @@ end -- GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) -------------------------------------------------------------------------------- function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) - local debug = false + local debug = true if debug or m.debug then ConMsg("GenSequence()") end local t, t2 = NewNoteBuf(), GetNoteBuf() CopyTable(t2, t) @@ -791,9 +796,10 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) t[noteCount][8] = noteVel -- velocity end -- newNote end -- itemPos < itemLength - if debug and m.debug then PrintNotes(t) end + if debug or m.debug then PrintNotes(t) end PurgeNoteBuf() if not m.seqRndNotesF then InsertNotes() end + --InsertNotes() end -------------------------------------------------------------------------------- -- GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) @@ -848,7 +854,7 @@ function GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) idx = Wrap(idx, step) end PurgeNoteBuf() - InsertNotes() + if not m.eucRndNotesF then InsertNotes() end end -------------------------------------------------------------------------------- -- GenNoteAttributes(accF, accProb, accVal, legF, legVal) -- accent, legato only @@ -908,70 +914,93 @@ end -- InsertNotes() - insert current note buffer in the active take -------------------------------------------------------------------------------- function InsertNotes() - local debug = false + local debug = true if debug or m.debug then ConMsg("\nInsertNotes()") end - DeleteNotes() local i = 1 if m.activeTake then local gridSize = m.reaGrid * m.ppqn - local itemLength = GetItemLength() + local itemLenP = GetItemLength() local noteShift = m.seqShift * gridSize local t1 = GetNoteBuf() - local t2 = {} -- temp for note shifting (no undo) - CopyTable(t1, t2) - - for k, v in pairs(t2) do -- start note shifting + PrintNotes(t1) + -- note shifter + local t2 = {} -- temp for note shifter (no undo) + CopyTable(t1, t2) + for k, v in pairs(t2) do v[3] = v[3] + noteShift v[4] = v[4] + noteShift if v[3] < 0 then - v[3] = itemLength + v[3] - v[4] = itemLength + v[4] - if v[4] > itemLength then v[4] = itemLength + m.legato end - elseif v[3] >= itemLength then - v[3] = v[3] - itemLength - v[4] = v[4] - itemLength + v[3] = itemLenP + v[3] + v[4] = itemLenP + v[4] + if v[4] > itemLenP then v[4] = itemLenP + m.legato end + elseif v[3] >= itemLenP then + v[3] = v[3] - itemLenP + v[4] = v[4] - itemLenP end - end -- stop note shifting - - -- start repeat ---m.repNum, m.repLenGrid, m.repMax, m.repLenPPQN - t3 = {} -- temp for repeating - local repLenPPQN = m.repLenGrid * gridSize - local repStart = 0 - local repEnd = repLenPPQN - local repLoop = m.repNum - local writePos = repStart - - ConMsg("\nStart repeat...") - while repLoop > 0 do - ConMsg("\nrepLoop = " .. tostring(repLoop)) - ConMsg("repStart = " .. tostring(repStart)) - ConMsg("repEnd = " .. tostring(repEnd)) - ConMsg("writePos = " .. tostring(writePos)) - for k, v in pairs(t2) do - if v[3] >= repStart and v[3] < repEnd then - if v[4] > repEnd then v[4] = repEnd end - t3[k] = {} - ConMsg("note data") - ConMsg("a - noteIdx = " .. tostring(k) .. " - Start = " .. tostring(v[3]) .. " - End = " .. tostring(v[4])) - ConMsg("b - noteIdx = " .. tostring(k) .. " - Start = " .. tostring(v[3] + writePos) .. " - End = " .. tostring(v[4] + writePos)) - t3[k][1] = v[1]; t3[k][2] = v[2]; t3[k][5] = v[5]; t3[k][6] = v[6]; t3[k][7] = v[7]; t3[k][8] = v[8]; - t3[k][3] = v[3] + writePos; t3[k][4] = v[4] + writePos - reaper.MIDI_InsertNote(m.activeTake, t3[k][1], t3[k][2], t3[k][3], t3[k][4], t3[k][6], t3[k][7], t3[k][8], false) - end -- if v[3] - end -- for k, v t2 - repLoop = repLoop - 1 - writePos = writePos + repLenPPQN - end + end -- end note shifter - -- insert note buffer to the active take - --while t2[i] do - --reaper.MIDI_InsertNote(m.activeTake, t2[i][1], t2[i][2], t2[i][3], t2[i][4], t2[i][6], t2[i][7], t2[i][8], false) - --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) - --i = i + 1 - --end -- while t2[i] - reaper.MIDI_Sort(m.activeTake) - reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off + -- note repeater + if m.seqRepeatF then + DeleteNotes() + t3 = {} -- temp table for repeater (no undo) + --m.loopStartG, m.loopLenG, m.loopNum, m.loopMaxRep + --m.t_loopStart, m.t_loopRep, m.t_loopLenG + local loopStartP = m.t_loopStart[m.loopStartG] * gridSize + local loopLenP = m.loopLenG * gridSize + local loopEndP = loopStartP + loopLenP + local loopNum = m.loopNum + local writeOffP = 0 + if loopStartP > 0 then writeOffP = -loopStartP else writeOffP = 0 end + + if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end + if debug or m.debug then ConMsg("loopStartP = " .. tostring(loopStartP)) end + if debug or m.debug then ConMsg("loopLenP = " .. tostring(loopLenP)) end + if debug or m.debug then ConMsg("loopEndP = " .. tostring(loopEndP)) end + if debug or m.debug then ConMsg("loopNum = " .. tostring(loopNum)) end + if debug or m.debug then ConMsg("writeOffP = " .. tostring(writeOffP)) end + + if debug or m.debug then ConMsg("\nStart repeater...") end + while loopNum > 0 do + if debug or m.debug then ConMsg("\nloopNum = " .. tostring(loopNum)) end + if debug or m.debug then ConMsg("writeOffP = " .. tostring(writeOffP)) end + + for k, v in pairs(t2) do + if v[3] >= loopStartP and v[3] < loopEndP then + t3[k] = {} + t3[k][1] = v[1]; + t3[k][2] = v[2]; + t3[k][3] = v[3] + writeOffP + + if v[4] > loopEndP then + t3[k][4] = loopEndP + writeOffP + else + t3[k][4] = v[4] + writeOffP + end + + t3[k][5] = v[5]; + t3[k][6] = v[6]; + t3[k][7] = v[7]; + t3[k][8] = v[8]; + if debug or m.debug then ConMsg("a - idx = " .. tostring(k) .. " - Start = " .. tostring(v[3]) .. " - End = " .. tostring(v[4])) end + if debug or m.debug then ConMsg("b - idx = " .. tostring(k) .. " - Start = " .. tostring(t3[k][3]) .. " - End = " .. tostring(t3[k][4])) end + reaper.MIDI_InsertNote(m.activeTake, t3[k][1], t3[k][2], t3[k][3], t3[k][4], t3[k][6], t3[k][7], t3[k][8], false) + end -- if v[3] + end -- for k, v t2 + loopNum = loopNum - 1 + writeOffP = writeOffP + loopLenP + end + reaper.MIDI_Sort(m.activeTake) + reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off + else -- note m.seqRepeatF + DeleteNotes() + while t2[i] do + reaper.MIDI_InsertNote(m.activeTake, t1[i][1], t1[i][2], t1[i][3], t1[i][4], t1[i][6], t1[i][7], t1[i][8], false) + --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) + i = i + 1 + end -- while t2[i] + reaper.MIDI_Sort(m.activeTake) + reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off + end else if debug or m.debug then ConMsg("No Active Take") end end -- m.activeTake @@ -1039,7 +1068,7 @@ end -- PrintNotes - arg note_buffer t; print note_buffer to reaper console -------------------------------------------------------------------------------- function PrintNotes(t) -- debug code - local debug = false + local debug = true if debug or m.debug then ConMsg("PrintNotes()") end local i = 1 local str = "sel \t mut \t s_ppq \t e_ppq \t leng \t chan \t pitch \t vel \n" @@ -1113,7 +1142,7 @@ t_winElements = {winFrame, zoomDrop, winText, layerBtn01, layerBtn02, layerBtn03 -- Common Elements -------------------------------------------------------------------------------- -- key, octave, & scale droplists -dx, dy, dw, dh = 25, 70, 110, 20 +dx, dy, dw, dh = 25, 70, 100, 20 local keyDrop = e.Droplist:new({1, 2, 3}, dx, dy, dw, dh, e.col_blue, "Root Note", e.Arial, 16, e.col_grey8, m.key, m.notes) local octDrop = e.Droplist:new({1, 2, 3}, dx, dy + 45, dw, dh, e.col_blue, "Octave ", e.Arial, 16, e.col_grey8, m.oct,{0, 1, 2, 3, 4, 5, 6, 7}) local scaleDrop = e.Droplist:new({1, 2, 3}, dx, dy + 90, dw, dh, e.col_blue, "Scale", e.Arial, 16, e.col_grey8, 1, m.scalelist) @@ -1123,7 +1152,7 @@ local t_Droplists = {keyDrop, octDrop, scaleDrop} -- Randomiser Layer -------------------------------------------------------------------------------- -- note randomise button -local randomBtn = e.Button:new({1}, 25, 205, 110, 25, e.col_green, "Generate", e.Arial, 16, e.col_grey8) +local randomBtn = e.Button:new({1}, 25, 205, 100, 25, e.col_green, "Generate", e.Arial, 16, e.col_grey8) -- note weight sliders local nx, ny, nw, nh, np = 160, 50, 30, 150, 40 local noteSldr01 = e.Vert_Slider:new({1}, nx, ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) @@ -1148,66 +1177,67 @@ local probSldrText = e.Textbox:new({1}, nx, 210, 510, 20, e.col_grey5, "Note Wei local octProbSldr = e.Vert_Slider:new({1}, nx+(np*13) + 10, ny, nw, nh, e.col_blue, "%", e.Arial, 16, e.col_grey8, m.rndOctProb, 0, 0, 10, 1) local octProbText = e.Textbox:new({1}, nx+(np*13) + 10, 210, (nw), 20, e.col_grey5, "Oct", e.Arial, 16, e.col_grey7) -- Note randomiser options -local noteOptionsCb = e.Checkbox:new({1}, nx+(np*14)+10, ny+30, 30, 30, e.col_orange, "", e.Arial, 16, e.col_grey8, {0,0,0}, {"All / Sel Notes", "1st Note = Root", "Octave X2"}) +local noteOptionsCb = e.Checkbox:new({1}, nx+(np*15)-10, ny+30, 30, 30, e.col_orange, "", e.Arial, 16, e.col_grey8, {0,0,0}, {"All / Sel Notes", "1st Note = Root", "Octave X2"}) local noteOptionText = e.Textbox:new({1}, nx+(np*14)+20, 210, (nw*4), 20, e.col_grey5, "Options", e.Arial, 16, e.col_grey7) -------------------------------------------------------------------------------- -- Sequencer Layer -------------------------------------------------------------------------------- -- sequence generate button -local sequenceBtn = e.Button:new({2}, 25, 205, 110, 25, e.col_yellow, "Generate", e.Arial, 16, e.col_grey8) -local sx, sy, sw, sh, sp = 160, 50, 30, 150, 40 +local sequenceBtn = e.Button:new({2}, 25, 205, 100, 25, e.col_yellow, "Generate", e.Arial, 16, e.col_grey8) +local sx, sy, sw, sh, sp = 140, 50, 30, 150, 40 -- sequencer grid size radio selector local seqGridRad = e.Rad_Button:new({2,3}, sx, sy + 40, 30, 30, e.col_yellow, "", e.Arial, 16, e.col_grey8, 1, {"1/16", "1/8", "1/4"}) -local seqGridText = e.Textbox:new({2,3}, sx, 210, (sw*2)+20, 20, e.col_grey5, "Grid Size", e.Arial, 16, e.col_grey7) +local seqGridText = e.Textbox:new({2,3}, sx+5, 210, (sw*2)+5, 20, e.col_grey5, "Grid Size", e.Arial, 16, e.col_grey7) -- sequence grid probability sliders -local seqSldr16 = e.Vert_Slider:new({2}, sx+(sp*3), sy, sw, sh, e.col_blue, "1/16", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) -local seqSldr8 = e.Vert_Slider:new({2}, sx+(sp*4), sy, sw, sh, e.col_blue, "1/8", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) -local seqSldr4 = e.Vert_Slider:new({2}, sx+(sp*5), sy, sw, sh, e.col_blue, "1/4", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) -local seqSldrRest = e.Vert_Slider:new({2}, sx+(sp*6), sy, sw, sh, e.col_blue, "Rest", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) +local seqSldr16 = e.Vert_Slider:new({2}, sx+(sp*2)+20, sy, sw, sh, e.col_blue, "1/16", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) +local seqSldr8 = e.Vert_Slider:new({2}, sx+(sp*3)+20, sy, sw, sh, e.col_blue, "1/8", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) +local seqSldr4 = e.Vert_Slider:new({2}, sx+(sp*4)+20, sy, sw, sh, e.col_blue, "1/4", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) +local seqSldrRest = e.Vert_Slider:new({2}, sx+(sp*5)+20, sy, sw, sh, e.col_blue, "Rest", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) -- sequence grid probability slider table local t_seqSliders = {seqSldr16, seqSldr8, seqSldr4, seqSldrRest} -- sequence grid probability sliders label - right click to reset all (per grid size selection) -local seqSldrText = e.Textbox:new({2}, sx + (sp * 3), 210, (sw * 5), 20, e.col_grey5, "Size Weight Sliders", e.Arial, 16, e.col_grey7) +local seqSldrText = e.Textbox:new({2}, sx+(sp * 2)+20, 210, (sw * 5), 20, e.col_grey5, "Size Weight Sliders", e.Arial, 16, e.col_grey7) -- velocity accent slider (shared with Euclid layer) -local seqAccRSldr = e.V_Rng_Slider:new({2,3}, sx + (sp * 8) - (sw / 2), sy, sw, sh, e.col_blue, "", e.Arial, 16, e.col_grey8, m.accentLow, m.accentHigh, 0, 127, 1) -local seqAccProbSldr = e.Vert_Slider:new({2,3}, sx + (sp * 9) - (sw / 2), sy, sw, sh, e.col_blue, "%", e.Arial, 16, e.col_grey8, m.accentProb, 0, 0, 10, 1) -local seqAccSldrText = e.Textbox:new({2,3}, sx + (sp * 8) - (sw / 2), 210, (sw * 2) + 10, 20, e.col_grey5, "Vel | Acc", e.Arial, 16, e.col_grey7) +local seqAccRSldr = e.V_Rng_Slider:new({2,3}, sx+(sp*7), sy, sw, sh, e.col_blue, "", e.Arial, 16, e.col_grey8, m.accentLow, m.accentHigh, 0, 127, 1) +local seqAccProbSldr = e.Vert_Slider:new({2,3}, sx+(sp*8), sy, sw, sh, e.col_blue, "%", e.Arial, 16, e.col_grey8, m.accentProb, 0, 0, 10, 1) +local seqAccSldrText = e.Textbox:new({2,3}, sx+(sp*7), 210, (sw * 2) + 10, 20, e.col_grey5, "Vel | Acc", e.Arial, 16, e.col_grey7) -- legato slider -local seqLegProbSldr = e.Vert_Slider:new({2}, sx + (sp * 10) - (sw / 2), sy, sw, sh, e.col_blue, "%", e.Arial, 16, e.col_grey8, m.legatoProb, 0, 0, 10, 1) -local seqLegSldrText = e.Textbox:new({2}, sx + (sp * 10) - (sw / 2), 210, sw, 20, e.col_grey5, "Leg", e.Arial, 16, e.col_grey7) +local seqLegProbSldr = e.Vert_Slider:new({2}, sx+(sp * 9), sy, sw, sh, e.col_blue, "%", e.Arial, 16, e.col_grey8, m.legatoProb, 0, 0, 10, 1) +local seqLegSldrText = e.Textbox:new({2}, sx+(sp * 9), 210, sw, 20, e.col_grey5, "Leg", e.Arial, 16, e.col_grey7) -- repeat dropboxes -local seqRepLenDrop = e.Droplist:new({2}, sx + (sp * 11) + 10, sy + 15, sw * 3, 20, e.col_blue, "Length", e.Arial, 16, e.col_grey8, m.repLenGrid, m.repLenGridT) -local seqRepNumDrop = e.Droplist:new({2}, sx + (sp * 11) + 10, sy + 60, sw * 3, 20, e.col_blue, "Amount", e.Arial, 16, e.col_grey8, m.repNum, m.repNumT) -local seqRepText = e.Textbox:new({2}, sx + (sp * 11) + 10, sy + 90, sw * 3, 20, e.col_grey5, "Repeat", e.Arial, 16, e.col_grey7) +local seqRepLenDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+15, sw*2, 20, e.col_blue, "Length", e.Arial, 16, e.col_grey8, m.loopLenG, m.t_loopLenG) +local seqRepNumDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+65, sw*2, 20, e.col_blue, "Amount", e.Arial, 16, e.col_grey8, m.loopNum, m.t_loopRep) +local seqRepStartDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+115, sw*2, 20, e.col_blue, "Start", e.Arial, 16, e.col_grey8, m.loopStartG, m.t_loopStart) +local seqRepText = e.Textbox:new({2}, sx+(sp*10)+25, 210, sw*2, 20, e.col_grey5, "Repeat", e.Arial, 16, e.col_grey7) -- sequence shift buttons -local seqShiftLBtn = e.Button:new({2}, sx + (sp * 11) + 10, sy + sh - 25, sw, 25, e.col_blue, "<<", e.Arial, 16, e.col_grey8) -local seqShiftRBtn = e.Button:new({2}, sx + (sp * 13) - 10, sy + sh - 25, sw, 25, e.col_blue, ">>", e.Arial, 16, e.col_grey8) -local seqShiftVal = e.Textbox:new({2}, sx + (sp * 12), sy + sh - 25, sw, 25, e.col_grey5, tostring(m.seqShift), e.Arial, 16, e.col_grey7) -local seqShiftText = e.Textbox:new({2}, sx + (sp * 11) + 10, 210, sw * 3, 20, e.col_grey5, "Shift Notes", e.Arial, 16, e.col_grey7) +local seqShiftLBtn = e.Button:new({2}, sx+(sp*12)+30, sy+sh-25, sw-5, 25, e.col_blue, "<<", e.Arial, 16, e.col_grey8) +local seqShiftVal = e.Textbox:new({2}, sx+(sp*13)+15, sy+sh-25, sw, 25, e.col_grey5, tostring(m.seqShift), e.Arial, 16, e.col_grey7) +local seqShiftRBtn = e.Button:new({2}, sx+(sp*14)+5, sy+sh-25, sw-5, 25, e.col_blue, ">>", e.Arial, 16, e.col_grey8) +local seqShiftText = e.Textbox:new({2}, sx+(sp*12)+30, 210, sw*3-10, 20, e.col_grey5, "Shift Notes", e.Arial, 16, e.col_grey7) -- Sequencer options -local seqOptionsCb = e.Checkbox:new({2}, sx+(np * 14) + 10, sy + 5, 30, 30, e.col_orange, "", e.Arial, 16, e.col_grey8, {0,0,0,0,0}, {"Generate", "1st Note Always", "Accent", "Legato", "Rnd Notes"}) +local seqOptionsCb = e.Checkbox:new({2}, sx+(np * 15) + 10, sy + 5, 30, 30, e.col_orange, "", e.Arial, 16, e.col_grey8, {0,0,0,0,0}, {"Generate", "Force 1st Note", "Accent", "Legato", "Rnd Notes", "Repeat"}) -------------------------------------------------------------------------------- -- Euclid Layer -------------------------------------------------------------------------------- -- euclid generate button -local euclidBtn = e.Button:new({3}, 25, 205, 110, 25, e.col_orange, "Generate", Arial, 16, e.col_grey8) +local euclidBtn = e.Button:new({3}, 25, 205, 100, 25, e.col_orange, "Generate", Arial, 16, e.col_grey8) -- euclidean sliders local ex, ey, ew, eh, ep = 160, 50, 30, 150, 40 -local euclidPulsesSldr = e.Vert_Slider:new({3}, ex+(ep*3), ey, ew, eh, e.col_blue, "Puls", Arial, 16, e.col_grey8, m.eucPulses, 0, 1, 24, 1) -local euclidStepsSldr = e.Vert_Slider:new({3}, ex+(ep*4), ey, ew, eh, e.col_blue, "Step", Arial, 16, e.col_grey8, m.eucSteps, 0, 1, 24, 1) -local euclidRotationSldr = e.Vert_Slider:new({3}, ex+(ep*5), ey, ew, eh, e.col_blue, "Rot", Arial, 16, e.col_grey8, m.eucRot, 0, 0, 24, 1) +local euclidPulsesSldr = e.Vert_Slider:new({3}, ex+(ep*2), ey, ew, eh, e.col_blue, "Puls", Arial, 16, e.col_grey8, m.eucPulses, 0, 1, 24, 1) +local euclidStepsSldr = e.Vert_Slider:new({3}, ex+(ep*3), ey, ew, eh, e.col_blue, "Step", Arial, 16, e.col_grey8, m.eucSteps, 0, 1, 24, 1) +local euclidRotationSldr = e.Vert_Slider:new({3}, ex+(ep*4), ey, ew, eh, e.col_blue, "Rot", Arial, 16, e.col_grey8, m.eucRot, 0, 0, 24, 1) local t_euclidSliders = {euclidPulsesSldr, euclidStepsSldr, euclidRotationSldr} -- euclid slider label - right click to reset all -local txtEuclidLabel = e.Textbox:new({3}, ex + (ep * 3), 210, (ew * 3) + 20, 20, e.col_grey5, "Euclid Sliders", Arial, 16, e.col_grey7) +local txtEuclidLabel = e.Textbox:new({3}, ex + (ep * 2), 210, (ew * 3) + 20, 20, e.col_grey5, "Euclid Sliders", Arial, 16, e.col_grey7) -- Sequencer options -local eucOptionsCb = e.Checkbox:new({3}, ex + (ep * 14) + 10, ey + 40, 30, 30, e.col_orange, "", e.Arial, 16, e.col_grey8, {0,0,0}, {"Generate", "Accent", "Rnd Notes"}) +local eucOptionsCb = e.Checkbox:new({3}, ex + (ep * 15)- 10, ey + 40, 30, 30, e.col_orange, "", e.Arial, 16, e.col_grey8, {0,0,0}, {"Generate", "Accent", "Rnd Notes"}) -------------------------------------------------------------------------------- -- Options Layer @@ -1224,7 +1254,7 @@ local msgText = e.Textbox:new({9}, m.win_x + 10, m.win_y + 30, m.win_w - 40, m.w -------------------------------------------------------------------------------- local t_Buttons = {randomBtn, sequenceBtn, seqShiftLBtn, seqShiftRBtn, euclidBtn} local t_Checkboxes = {noteOptionsCb, seqOptionsCb, eucOptionsCb} -local t_Droplists2 = {seqRepLenDrop, seqRepNumDrop} +local t_Droplists2 = {seqRepLenDrop, seqRepNumDrop, seqRepStartDrop} local t_RadButtons = {seqGridRad} local t_RSliders = {octProbSldr, seqAccRSldr, seqAccProbSldr, seqLegProbSldr} local t_Textboxes = {probSldrText, octProbText, seqGridText, seqSldrText, seqShiftVal, seqRepText, seqShiftText, seqAccSldrText, seqLegSldrText, txtEuclidLabel, optText, msgText} @@ -1707,7 +1737,51 @@ seqShiftRBtn.onLClick = function() seqShiftVal.label = tostring(m.seqShift) InsertNotes() end +-- Sequencer repeat length +seqRepLenDrop.onLClick = function() + local debug = true + if debug or m.debug then ConMsg("\noseqRepLenDrop.onLClick()") end + m.loopLenG = seqRepLenDrop.val1 + if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end +--seqRepLenDrop +--seqRepNumDrop +--seqRepStartDrop + -- set project ext state + --pExtState.oct = m.oct + --pExtState.root = m.root + --pExtSaveStateF = true +end +-- Sequencer repeat length +seqRepNumDrop.onLClick = function() + local debug = true + if debug or m.debug then ConMsg("\noseqRepNumDrop.onLClick()") end + m.loopNum = seqRepNumDrop.val1 + if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end +--seqRepLenDrop +--seqRepNumDrop +--seqRepStartDrop + + -- set project ext state + --pExtState.oct = m.oct + --pExtState.root = m.root + --pExtSaveStateF = true +end +-- Sequencer repeat length +seqRepStartDrop.onLClick = function() + local debug = true + if debug or m.debug then ConMsg("\noseqRepStartDrop.onLClick()") end + m.loopStartG = seqRepStartDrop.val1 + if debug or m.debug then ConMsg("m.loopStartG = " .. tostring(m.t_loopStart[m.loopStartG])) end +--seqRepLenDrop +--seqRepNumDrop +--seqRepStartDrop + + -- set project ext state + --pExtState.oct = m.oct + --pExtState.root = m.root + --pExtSaveStateF = true +end -- Set sequencer default options function SetDefaultSeqOptions() local debug = false @@ -1820,18 +1894,24 @@ function SetDefaultSeqRepeat() GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() - m.repNum = 1; m.repLenGrid = 1 - seqRepNumDrop.val1 = m.repNum - seqRepLenDrop.val1 = m.repLenGrid - m.repMax = math.floor(itemLength / gridSize) - for i = 1, m.repMax do + + m.loopLenG = 1; m.loopNum = 1; m.loopStartG = 1 + + seqRepNumDrop.val1 = m.loopNum + seqRepLenDrop.val1 = m.loopLenG + seqRepStartDrop.val1 = m.loopStartG + + m.loopMaxRep = math.floor(itemLength / gridSize) + + for i = 1, m.loopMaxRep do seqRepNumDrop.val2[i] = i seqRepLenDrop.val2[i] = i + seqRepStartDrop.val2[i] = i-1 end --[[ m.repNum, m.repLenGrid, m.repMax, m.repLenPPQN -seqRepLenDrop, m.repLenGridT) -seqRepNumDrop, m.repNumT) +seqRepLenDrop, m.t_loopLenG) +seqRepNumDrop, m.t_loopRep) --]] end From 392a7378048f1c1ddbbb27fc67981727f4a7c4cf Mon Sep 17 00:00:00 2001 From: RobU23 Date: Thu, 18 May 2017 23:44:50 +0100 Subject: [PATCH 04/33] meh... --- .../RobU - MIDI Ex Machina.lua | 111 +++++++++++------- 1 file changed, 67 insertions(+), 44 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 8a0b95a..9b77318 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -105,7 +105,7 @@ m.seqAccentF = true -- generate accents (option) m.seqLegatoF = false -- use legato (option) m.seqRndNotesF = true -- randomise notes (option) m.seqRepeatF = false -- repeat sequence by grid length (option - not implemented yet) -m.legato = -10 -- default legatolessness value +m.legato = 10 -- default legatolessness value m.accentLow = 100; m.accentHigh = 127; m.accentProb = 3 -- default values (options) -- accentLow/High - min 0, max 127; accentProb - min 0, max 10 m.legatoProb = 3 -- default value (option - min 0, max 10) @@ -498,6 +498,15 @@ function GetNotesFromTake() t[i][6] = channel t[i][7] = pitch t[i][8] = velocity + if not m.seqLegF then + if t[i][5] >= 950 and t[i][5] <= 960 then t[i][5] = 960; t[i][4] = t[i][3] + t[i][5]; t[i][9] = true -- 1/4 + elseif t[i][5] >= 470 and t[i][5] <= 480 then t[i][5] = 480; t[i][4] = t[i][3] + t[i][5]; t[i][9] = true -- 1/8 + elseif t[i][5] >= 230 and t[i][5] <= 240 then t[i][5] = 240; t[i][4] = t[i][3] + t[i][5]; t[i][9] = true -- 1/16 + else t[i][9] = false + end + end + +--]] end -- for i end -- num_notes else -- no active take @@ -581,12 +590,12 @@ function GenLegatoTable(probTable, probSlider) ClearTable(probTable) -- no legato for i = 1, (probSlider.max - probSlider.val1) do - probTable[j] = m.legato + probTable[j] = false j = j + 1 end -- legato for i = 1, (probSlider.val1) do - probTable[j] = 0 + probTable[j] = true j = j + 1 end end @@ -750,7 +759,7 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) local itemPos = 0 local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() - local noteStart, noteEnd, noteLen, noteVel = 0, 0, 0, 0 + local noteStart, noteEnd, noteLen, noteVel, notLeg = 0, 0, 0, 0, 0 local newNote = 0 local noteCount = 0; restCount = 0 while itemPos < itemLength do @@ -775,9 +784,9 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) noteEnd = noteStart + noteLen itemPos = itemPos + noteLen if m.seqLegatoF then -- handle legato flag - noteEnd = noteEnd + legProbTable[math.random(1, #legProbTable)] + noteLeg = legProbTable[math.random(1, #legProbTable)] else - noteEnd = noteEnd + m.legato + noteLeg = false end if m.seqAccentF then -- handle accent flag noteVel = accProbTable[math.random(1, #accProbTable)] @@ -793,7 +802,11 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) t[noteCount][5] = noteLen -- note length t[noteCount][6] = 0 -- channel t[noteCount][7] = m.root -- note number + t[noteCount][8] = noteVel -- velocity + + t[noteCount][9] = noteLeg -- legato + end -- newNote end -- itemPos < itemLength if debug or m.debug then PrintNotes(t) end @@ -846,6 +859,7 @@ function GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) t[noteCount][6] = 0 -- channel t[noteCount][7] = m.root -- note number t[noteCount][8] = noteVel -- velocity + t[noteCount][9] = false -- handle legatolessness else itemPos = itemPos + gridSize restCount = restCount + 1 @@ -868,24 +882,27 @@ function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) local noteStart, noteEnd, noteLen = 0, 0, 0 CopyTable(t1, t2) if debug and m.debug then PrintNotes(t2) end - while t2[i] do - if t2[i][1] then + for k, v in pairs(t2) do + -- fix legato + if not legF then + if v[5] >= 950 and v[5] <= 960 then v[5] = 960; v[4] = v[3] + v[5]; v[9] = true -- 1/4 + elseif v[5] >= 470 and v[5] <= 480 then v[5] = 480; v[4] = v[3] + v[5]; v[9] = true -- 1/8 + elseif v[5] >= 230 and v[5] <= 240 then v[5] = 240; v[4] = v[3] + v[5]; v[9] = true -- 1/16 + else v[9] = false + end + end + if v[1] then -- selected if accF then -- handle accent flag (8 = velocity) - t2[i][8] = accProbTable[math.random(1, #accProbTable)] - end -- end accent + v[8] = accProbTable[math.random(1, #accProbTable)] + end -- end accF if legF ~= 1 then -- no legato when called by euclid - if legF then -- handle legato flag (3 = noteStart, 4 = noteEnd, 5 = noteLen) - noteLen = t2[i][5] - if noteLen >= 960 + m.legato and noteLen <= 960 - m.legato then noteLen = 960 -- 1/4 - elseif noteLen >= 480 + m.legato and noteLen <= 480 - m.legato then noteLen = 480 -- 1/8 - elseif noteLen >= 240 + m.legato and noteLen <= 240 - m.legato then noteLen = 240 -- 1/16 - end - t2[i][4] = t2[i][3] + noteLen + legProbTable[math.random(1, #legProbTable)] - end -- legato - end -- t2[i] - end --selected - i = i + 1 - end -- while t1[i] + if legF then -- handle legato flag + v[9] = legProbTable[math.random(1, #legProbTable)] + end -- legF + end -- legF ~= 1 + end -- selected + + end -- for k, v t2 if debug and m.debug then PrintNotes(t2) end PurgeNoteBuf() InsertNotes() @@ -924,31 +941,32 @@ function InsertNotes() local t1 = GetNoteBuf() PrintNotes(t1) -- note shifter - local t2 = {} -- temp for note shifter (no undo) + local t2 = {} -- temp table for note shifter (no undo) CopyTable(t1, t2) + for k, v in pairs(t2) do v[3] = v[3] + noteShift v[4] = v[4] + noteShift + if v[3] < 0 then v[3] = itemLenP + v[3] v[4] = itemLenP + v[4] - if v[4] > itemLenP then v[4] = itemLenP + m.legato end + if v[4] > itemLenP then v[4] = itemLenP end elseif v[3] >= itemLenP then v[3] = v[3] - itemLenP v[4] = v[4] - itemLenP end - end -- end note shifter + end -- for k, v t2 -- note repeater if m.seqRepeatF then DeleteNotes() - t3 = {} -- temp table for repeater (no undo) - --m.loopStartG, m.loopLenG, m.loopNum, m.loopMaxRep - --m.t_loopStart, m.t_loopRep, m.t_loopLenG + t3 = {} -- temp table for note repeater (no undo) local loopStartP = m.t_loopStart[m.loopStartG] * gridSize local loopLenP = m.loopLenG * gridSize local loopEndP = loopStartP + loopLenP local loopNum = m.loopNum + local noteEnd local writeOffP = 0 if loopStartP > 0 then writeOffP = -loopStartP else writeOffP = 0 end @@ -967,40 +985,45 @@ function InsertNotes() for k, v in pairs(t2) do if v[3] >= loopStartP and v[3] < loopEndP then t3[k] = {} - t3[k][1] = v[1]; - t3[k][2] = v[2]; - t3[k][3] = v[3] + writeOffP + t3[k][1] = v[1] -- selected + t3[k][2] = v[2] -- muted + + t3[k][3] = v[3] + writeOffP -- startppqn - if v[4] > loopEndP then + if v[4] > loopEndP then -- endppqn t3[k][4] = loopEndP + writeOffP else t3[k][4] = v[4] + writeOffP end + + if not t3[k][9] then t3[k][4] = t3[k][4] - m.legato end -- handle the legatolessness - t3[k][5] = v[5]; - t3[k][6] = v[6]; - t3[k][7] = v[7]; - t3[k][8] = v[8]; + t3[k][6] = v[6] -- channel + t3[k][7] = v[7] -- pitch + t3[k][8] = v[8] -- vel if debug or m.debug then ConMsg("a - idx = " .. tostring(k) .. " - Start = " .. tostring(v[3]) .. " - End = " .. tostring(v[4])) end if debug or m.debug then ConMsg("b - idx = " .. tostring(k) .. " - Start = " .. tostring(t3[k][3]) .. " - End = " .. tostring(t3[k][4])) end reaper.MIDI_InsertNote(m.activeTake, t3[k][1], t3[k][2], t3[k][3], t3[k][4], t3[k][6], t3[k][7], t3[k][8], false) + end -- if v[3] - end -- for k, v t2 + end -- for k, v t3 loopNum = loopNum - 1 writeOffP = writeOffP + loopLenP end reaper.MIDI_Sort(m.activeTake) reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off - else -- note m.seqRepeatF + else -- not m.seqRepeatF DeleteNotes() - while t2[i] do - reaper.MIDI_InsertNote(m.activeTake, t1[i][1], t1[i][2], t1[i][3], t1[i][4], t1[i][6], t1[i][7], t1[i][8], false) + + for k, v in pairs(t2) do + if not v[9] then v[4] = v[4] - m.legato end-- handle the legatolessness + reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) - i = i + 1 - end -- while t2[i] + end -- for k, v t2 + reaper.MIDI_Sort(m.activeTake) reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off - end + end -- m.seqRepeatF else if debug or m.debug then ConMsg("No Active Take") end end -- m.activeTake @@ -1071,7 +1094,7 @@ function PrintNotes(t) -- debug code local debug = true if debug or m.debug then ConMsg("PrintNotes()") end local i = 1 - local str = "sel \t mut \t s_ppq \t e_ppq \t leng \t chan \t pitch \t vel \n" + local str = "sel \t mut \t s_ppq \t e_ppq \t leng \t chan \t pitch \t vel \t leg \n" while t[i] do j = 1 while (t[i][j] ~= nil) do From d225c3aca3855562124a276ded95296ed5b03719 Mon Sep 17 00:00:00 2001 From: RobU Date: Sat, 20 May 2017 08:45:42 +0100 Subject: [PATCH 05/33] changed legato calculations, moved to InsertNotes() updated GetNotesFromTake() with legato fixes changed to a default font setting (for future options) minor bug fix to PrintNotes() and PrintTable() --- .../RobU - MIDI Ex Machina.lua | 222 +++++++++--------- 1 file changed, 109 insertions(+), 113 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 9b77318..feb74ad 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -81,6 +81,7 @@ m.win_bg = {0, 0, 0} -- background colour m.def_zoom = 4 -- 100% (option) -- zoom values are 1=70, 2=80, 3=90, 4=100, 5=110%, 6=120, 7=140, 8=160, 9=180, 10=200 m.zoomF = false +m.defFont = e.Lucinda; m.defFontSz = 15 -- default octave & key -- due to some quirk, oct 4 is really oct 3... @@ -106,6 +107,7 @@ m.seqLegatoF = false -- use legato (option) m.seqRndNotesF = true -- randomise notes (option) m.seqRepeatF = false -- repeat sequence by grid length (option - not implemented yet) m.legato = 10 -- default legatolessness value +m.legQ = 240 m.accentLow = 100; m.accentHigh = 127; m.accentProb = 3 -- default values (options) -- accentLow/High - min 0, max 127; accentProb - min 0, max 10 m.legatoProb = 3 -- default value (option - min 0, max 10) @@ -116,7 +118,7 @@ m.seqShift = 0; m.seqShiftMin = -16; m.seqShiftMax = 16 -- shift notes left-righ m.loopStartG, m.loopLenG, m.loopNum, m.loopMaxRep = 0, 0, 0, 0 -- repeat values for GUI m.t_loopStart, m.t_loopRep, m.t_loopLenG = {}, {}, {} -- repeat value tables -m.repNum, m.repLenGrid, m.repMax, m.repLenPPQN = 0, 0, 0, 0 -- repeat values +--m.repNum, m.repLenGrid, m.repMax, m.repLenPPQN = 0, 0, 0, 0 -- repeat values -- euclidean generator @@ -479,13 +481,15 @@ end -- GetNotesFromTake() - fill a note buffer from the active take -------------------------------------------------------------------------------- function GetNotesFromTake() - local debug = false + local debug = true if debug or m.debug then ConMsg("GetNotesFromTake()") end local i, t if m.activeTake then local _retval, num_notes, num_cc, num_sysex = reaper.MIDI_CountEvts(m.activeTake) if num_notes > 0 then t = GetNoteBuf(); if t == nil then t = NewNoteBuf() end + local gridSize = GetReaperGrid() + local div, rem, noteLen ClearTable(t) for i = 1, num_notes do _retval, selected, muted, startppq, endppq, channel, pitch, velocity = reaper.MIDI_GetNote(m.activeTake, i-1) @@ -493,22 +497,20 @@ function GetNotesFromTake() t[i][1] = selected t[i][2] = muted t[i][3] = startppq - t[i][4] = endppq - t[i][5] = endppq-startppq + noteLen = endppq - startppq + div = math.floor(noteLen / m.legQ + 0.5) + if div < 1 then div = 1 end + rem = noteLen % m.legQ + noteLen = div * m.legQ + t[i][4] = startppq + noteLen + t[i][5] = noteLen t[i][6] = channel t[i][7] = pitch t[i][8] = velocity - if not m.seqLegF then - if t[i][5] >= 950 and t[i][5] <= 960 then t[i][5] = 960; t[i][4] = t[i][3] + t[i][5]; t[i][9] = true -- 1/4 - elseif t[i][5] >= 470 and t[i][5] <= 480 then t[i][5] = 480; t[i][4] = t[i][3] + t[i][5]; t[i][9] = true -- 1/8 - elseif t[i][5] >= 230 and t[i][5] <= 240 then t[i][5] = 240; t[i][4] = t[i][3] + t[i][5]; t[i][9] = true -- 1/16 - else t[i][9] = false - end - end - ---]] + t[i][9] = rem == 0 and true or false end -- for i end -- num_notes + if debug or m.debug then PrintNotes(t) end else -- no active take if debug or m.debug then ConMsg("No Active Take") end end -- m.activeTake @@ -878,19 +880,12 @@ function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) if debug or m.debug then ConMsg("GenNoteAttributes()") end if not accF and not legF then return end local t1, t2 = GetNoteBuf(), NewNoteBuf() + local gridSize = GetReaperGrid() local i = 1 - local noteStart, noteEnd, noteLen = 0, 0, 0 + local div, rem, noteLen CopyTable(t1, t2) if debug and m.debug then PrintNotes(t2) end for k, v in pairs(t2) do - -- fix legato - if not legF then - if v[5] >= 950 and v[5] <= 960 then v[5] = 960; v[4] = v[3] + v[5]; v[9] = true -- 1/4 - elseif v[5] >= 470 and v[5] <= 480 then v[5] = 480; v[4] = v[3] + v[5]; v[9] = true -- 1/8 - elseif v[5] >= 230 and v[5] <= 240 then v[5] = 240; v[4] = v[3] + v[5]; v[9] = true -- 1/16 - else v[9] = false - end - end if v[1] then -- selected if accF then -- handle accent flag (8 = velocity) v[8] = accProbTable[math.random(1, #accProbTable)] @@ -940,18 +935,17 @@ function InsertNotes() local noteShift = m.seqShift * gridSize local t1 = GetNoteBuf() PrintNotes(t1) + -- note shifter local t2 = {} -- temp table for note shifter (no undo) CopyTable(t1, t2) - for k, v in pairs(t2) do v[3] = v[3] + noteShift v[4] = v[4] + noteShift - if v[3] < 0 then v[3] = itemLenP + v[3] v[4] = itemLenP + v[4] - if v[4] > itemLenP then v[4] = itemLenP end + if v[4] > itemLenP then v[4] = itemLenP end elseif v[3] >= itemLenP then v[3] = v[3] - itemLenP v[4] = v[4] - itemLenP @@ -1093,6 +1087,7 @@ end function PrintNotes(t) -- debug code local debug = true if debug or m.debug then ConMsg("PrintNotes()") end + if not t then return end local i = 1 local str = "sel \t mut \t s_ppq \t e_ppq \t leng \t chan \t pitch \t vel \t leg \n" while t[i] do @@ -1113,6 +1108,7 @@ end function PrintTable(t) -- debug code local debug = false if debug or m.debug then ConMsg("PrintTable()") end + if not t then return end local str = "" for k, v in pairs(t) do str = str .. tostring(v) .. "\t" @@ -1150,14 +1146,14 @@ end -------------------------------------------------------------------------------- -- Persistent window elements local winFrame = e.Frame:new({0}, 5, 5, m.win_w - 10, m.win_h - 10, e.col_grey4) -local zoomDrop = e.Droplist:new({0}, 5, 5, 40, 22, e.col_green, "", e.Arial, 16, e.col_grey8, 4, {"70%", "80%", "90%", "100%", "110%", "120%", "140%", "160%", "180%", "200%"}) -local winText = e.Textbox:new({0}, 45, 5, m.win_w - 50, 22, e.col_green, "MIDI Ex Machina ", e.Arial, 16, e.col_grey8) -local layerBtn01 = e.Button:new({0}, 5, m.win_h - 25, 100, 20, e.col_green, "Randomiser", e.Arial, 16, e.col_grey8) -local layerBtn02 = e.Button:new({0}, 105, m.win_h - 25, 100, 20, e.col_grey5, "Sequencer", e.Arial, 16, e.col_grey7) -local layerBtn03 = e.Button:new({0}, 205, m.win_h - 25, 100, 20, e.col_grey5, "Euclidiser", e.Arial, 16, e.col_grey7) -local layerBtn04 = e.Button:new({0}, 305, m.win_h - 25, 100, 20, e.col_grey5, "Options", e.Arial, 16, e.col_grey7) -local undoBtn = e.Button:new({0}, m.win_w-85, m.win_h -25, 40, 20, e.col_grey5, "Undo", e.Arial, 16, e.col_grey7) -local redoBtn = e.Button:new({0}, m.win_w-45, m.win_h -25, 40, 20, e.col_grey5, "Redo", e.Arial, 16, e.col_grey7) +local zoomDrop = e.Droplist:new({0}, 5, 5, 40, 22, e.col_green, "", m.defFont, m.defFontSz, e.col_grey8, 4, {"70%", "80%", "90%", "100%", "110%", "120%", "140%", "160%", "180%", "200%"}) +local winText = e.Textbox:new({0}, 45, 5, m.win_w - 50, 22, e.col_green, "MIDI Ex Machina ", m.defFont, m.defFontSz, e.col_grey8) +local layerBtn01 = e.Button:new({0}, 5, m.win_h - 25, 100, 20, e.col_green, "Randomiser", m.defFont, m.defFontSz, e.col_grey8) +local layerBtn02 = e.Button:new({0}, 105, m.win_h - 25, 100, 20, e.col_grey5, "Sequencer", m.defFont, m.defFontSz, e.col_grey7) +local layerBtn03 = e.Button:new({0}, 205, m.win_h - 25, 100, 20, e.col_grey5, "Euclidiser", m.defFont, m.defFontSz, e.col_grey7) +local layerBtn04 = e.Button:new({0}, 305, m.win_h - 25, 100, 20, e.col_grey5, "Options", m.defFont, m.defFontSz, e.col_grey7) +local undoBtn = e.Button:new({0}, m.win_w-85, m.win_h -25, 40, 20, e.col_grey5, "Undo", m.defFont, m.defFontSz, e.col_grey7) +local redoBtn = e.Button:new({0}, m.win_w-45, m.win_h -25, 40, 20, e.col_grey5, "Redo", m.defFont, m.defFontSz, e.col_grey7) -- Persistent window element table t_winElements = {winFrame, zoomDrop, winText, layerBtn01, layerBtn02, layerBtn03, layerBtn04, undoBtn, redoBtn} @@ -1166,121 +1162,121 @@ t_winElements = {winFrame, zoomDrop, winText, layerBtn01, layerBtn02, layerBtn03 -------------------------------------------------------------------------------- -- key, octave, & scale droplists dx, dy, dw, dh = 25, 70, 100, 20 -local keyDrop = e.Droplist:new({1, 2, 3}, dx, dy, dw, dh, e.col_blue, "Root Note", e.Arial, 16, e.col_grey8, m.key, m.notes) -local octDrop = e.Droplist:new({1, 2, 3}, dx, dy + 45, dw, dh, e.col_blue, "Octave ", e.Arial, 16, e.col_grey8, m.oct,{0, 1, 2, 3, 4, 5, 6, 7}) -local scaleDrop = e.Droplist:new({1, 2, 3}, dx, dy + 90, dw, dh, e.col_blue, "Scale", e.Arial, 16, e.col_grey8, 1, m.scalelist) +local keyDrop = e.Droplist:new({1, 2, 3}, dx, dy, dw, dh, e.col_blue, "Root Note", m.defFont, m.defFontSz, e.col_grey8, m.key, m.notes) +local octDrop = e.Droplist:new({1, 2, 3}, dx, dy + 45, dw, dh, e.col_blue, "Octave ", m.defFont, m.defFontSz, e.col_grey8, m.oct,{0, 1, 2, 3, 4, 5, 6, 7}) +local scaleDrop = e.Droplist:new({1, 2, 3}, dx, dy + 90, dw, dh, e.col_blue, "Scale", m.defFont, m.defFontSz, e.col_grey8, 1, m.scalelist) local t_Droplists = {keyDrop, octDrop, scaleDrop} -------------------------------------------------------------------------------- -- Randomiser Layer -------------------------------------------------------------------------------- -- note randomise button -local randomBtn = e.Button:new({1}, 25, 205, 100, 25, e.col_green, "Generate", e.Arial, 16, e.col_grey8) +local randomBtn = e.Button:new({1}, 25, 205, 100, 25, e.col_green, "Generate", m.defFont, m.defFontSz, e.col_grey8) -- note weight sliders local nx, ny, nw, nh, np = 160, 50, 30, 150, 40 -local noteSldr01 = e.Vert_Slider:new({1}, nx, ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr02 = e.Vert_Slider:new({1}, nx+(np*1), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr03 = e.Vert_Slider:new({1}, nx+(np*2), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr04 = e.Vert_Slider:new({1}, nx+(np*3), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr05 = e.Vert_Slider:new({1}, nx+(np*4), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr06 = e.Vert_Slider:new({1}, nx+(np*5), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr07 = e.Vert_Slider:new({1}, nx+(np*6), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr08 = e.Vert_Slider:new({1}, nx+(np*7), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr09 = e.Vert_Slider:new({1}, nx+(np*8), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr10 = e.Vert_Slider:new({1}, nx+(np*9), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr11 = e.Vert_Slider:new({1}, nx+(np*10), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr12 = e.Vert_Slider:new({1}, nx+(np*11), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr13 = e.Vert_Slider:new({1}, nx+(np*12), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr01 = e.Vert_Slider:new({1}, nx, ny, nw, nh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr02 = e.Vert_Slider:new({1}, nx+(np*1), ny, nw, nh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr03 = e.Vert_Slider:new({1}, nx+(np*2), ny, nw, nh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr04 = e.Vert_Slider:new({1}, nx+(np*3), ny, nw, nh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr05 = e.Vert_Slider:new({1}, nx+(np*4), ny, nw, nh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr06 = e.Vert_Slider:new({1}, nx+(np*5), ny, nw, nh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr07 = e.Vert_Slider:new({1}, nx+(np*6), ny, nw, nh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr08 = e.Vert_Slider:new({1}, nx+(np*7), ny, nw, nh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr09 = e.Vert_Slider:new({1}, nx+(np*8), ny, nw, nh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr10 = e.Vert_Slider:new({1}, nx+(np*9), ny, nw, nh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr11 = e.Vert_Slider:new({1}, nx+(np*10), ny, nw, nh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr12 = e.Vert_Slider:new({1}, nx+(np*11), ny, nw, nh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr13 = e.Vert_Slider:new({1}, nx+(np*12), ny, nw, nh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, 1, 0, 0, 12, 1) -- Note probability slider table local t_noteSliders = {noteSldr01, noteSldr02, noteSldr03, noteSldr04, noteSldr05, noteSldr06, noteSldr07, noteSldr08, noteSldr09, noteSldr10, noteSldr11, noteSldr12, noteSldr13} -- Note probability slider label (Textbox) - right-click to reset all -local probSldrText = e.Textbox:new({1}, nx, 210, 510, 20, e.col_grey5, "Note Weight Sliders", e.Arial, 16, e.col_grey7) +local probSldrText = e.Textbox:new({1}, nx, 210, 510, 20, e.col_grey5, "Note Weight Sliders", m.defFont, m.defFontSz, e.col_grey7) -- Note octave doubler probability slider -local octProbSldr = e.Vert_Slider:new({1}, nx+(np*13) + 10, ny, nw, nh, e.col_blue, "%", e.Arial, 16, e.col_grey8, m.rndOctProb, 0, 0, 10, 1) -local octProbText = e.Textbox:new({1}, nx+(np*13) + 10, 210, (nw), 20, e.col_grey5, "Oct", e.Arial, 16, e.col_grey7) +local octProbSldr = e.Vert_Slider:new({1}, nx+(np*13) + 10, ny, nw, nh, e.col_blue, "%", m.defFont, m.defFontSz, e.col_grey8, m.rndOctProb, 0, 0, 10, 1) +local octProbText = e.Textbox:new({1}, nx+(np*13) + 10, 210, (nw), 20, e.col_grey5, "Oct", m.defFont, m.defFontSz, e.col_grey7) -- Note randomiser options -local noteOptionsCb = e.Checkbox:new({1}, nx+(np*15)-10, ny+30, 30, 30, e.col_orange, "", e.Arial, 16, e.col_grey8, {0,0,0}, {"All / Sel Notes", "1st Note = Root", "Octave X2"}) -local noteOptionText = e.Textbox:new({1}, nx+(np*14)+20, 210, (nw*4), 20, e.col_grey5, "Options", e.Arial, 16, e.col_grey7) +local noteOptionsCb = e.Checkbox:new({1}, nx+(np*15)-10, ny+30, 30, 30, e.col_orange, "", m.defFont, m.defFontSz, e.col_grey8, {0,0,0}, {"All / Sel Notes", "1st Note = Root", "Octave X2"}) +local noteOptionText = e.Textbox:new({1}, nx+(np*14)+20, 210, (nw*4), 20, e.col_grey5, "Options", m.defFont, m.defFontSz, e.col_grey7) -------------------------------------------------------------------------------- -- Sequencer Layer -------------------------------------------------------------------------------- -- sequence generate button -local sequenceBtn = e.Button:new({2}, 25, 205, 100, 25, e.col_yellow, "Generate", e.Arial, 16, e.col_grey8) +local sequenceBtn = e.Button:new({2}, 25, 205, 100, 25, e.col_yellow, "Generate", m.defFont, m.defFontSz, e.col_grey8) local sx, sy, sw, sh, sp = 140, 50, 30, 150, 40 -- sequencer grid size radio selector -local seqGridRad = e.Rad_Button:new({2,3}, sx, sy + 40, 30, 30, e.col_yellow, "", e.Arial, 16, e.col_grey8, 1, {"1/16", "1/8", "1/4"}) -local seqGridText = e.Textbox:new({2,3}, sx+5, 210, (sw*2)+5, 20, e.col_grey5, "Grid Size", e.Arial, 16, e.col_grey7) +local seqGridRad = e.Rad_Button:new({2,3}, sx, sy + 40, 30, 30, e.col_yellow, "", m.defFont, m.defFontSz, e.col_grey8, 1, {"1/16", "1/8", "1/4"}) +local seqGridText = e.Textbox:new({2,3}, sx+5, 210, (sw*2)+5, 20, e.col_grey5, "Grid Size", m.defFont, m.defFontSz, e.col_grey7) -- sequence grid probability sliders -local seqSldr16 = e.Vert_Slider:new({2}, sx+(sp*2)+20, sy, sw, sh, e.col_blue, "1/16", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) -local seqSldr8 = e.Vert_Slider:new({2}, sx+(sp*3)+20, sy, sw, sh, e.col_blue, "1/8", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) -local seqSldr4 = e.Vert_Slider:new({2}, sx+(sp*4)+20, sy, sw, sh, e.col_blue, "1/4", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) -local seqSldrRest = e.Vert_Slider:new({2}, sx+(sp*5)+20, sy, sw, sh, e.col_blue, "Rest", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) +local seqSldr16 = e.Vert_Slider:new({2}, sx+(sp*2)+20, sy, sw, sh, e.col_blue, "1/16", m.defFont, m.defFontSz, e.col_grey8, 0, 0, 0, m.defFontSz, 1) +local seqSldr8 = e.Vert_Slider:new({2}, sx+(sp*3)+20, sy, sw, sh, e.col_blue, "1/8", m.defFont, m.defFontSz, e.col_grey8, 0, 0, 0, m.defFontSz, 1) +local seqSldr4 = e.Vert_Slider:new({2}, sx+(sp*4)+20, sy, sw, sh, e.col_blue, "1/4", m.defFont, m.defFontSz, e.col_grey8, 0, 0, 0, m.defFontSz, 1) +local seqSldrRest = e.Vert_Slider:new({2}, sx+(sp*5)+20, sy, sw, sh, e.col_blue, "Rest", m.defFont, m.defFontSz, e.col_grey8, 0, 0, 0, m.defFontSz, 1) -- sequence grid probability slider table local t_seqSliders = {seqSldr16, seqSldr8, seqSldr4, seqSldrRest} -- sequence grid probability sliders label - right click to reset all (per grid size selection) -local seqSldrText = e.Textbox:new({2}, sx+(sp * 2)+20, 210, (sw * 5), 20, e.col_grey5, "Size Weight Sliders", e.Arial, 16, e.col_grey7) +local seqSldrText = e.Textbox:new({2}, sx+(sp * 2)+20, 210, (sw * 5), 20, e.col_grey5, "Size Weight Sliders", m.defFont, m.defFontSz, e.col_grey7) -- velocity accent slider (shared with Euclid layer) -local seqAccRSldr = e.V_Rng_Slider:new({2,3}, sx+(sp*7), sy, sw, sh, e.col_blue, "", e.Arial, 16, e.col_grey8, m.accentLow, m.accentHigh, 0, 127, 1) -local seqAccProbSldr = e.Vert_Slider:new({2,3}, sx+(sp*8), sy, sw, sh, e.col_blue, "%", e.Arial, 16, e.col_grey8, m.accentProb, 0, 0, 10, 1) -local seqAccSldrText = e.Textbox:new({2,3}, sx+(sp*7), 210, (sw * 2) + 10, 20, e.col_grey5, "Vel | Acc", e.Arial, 16, e.col_grey7) +local seqAccRSldr = e.V_Rng_Slider:new({2,3}, sx+(sp*7), sy, sw, sh, e.col_blue, "", m.defFont, m.defFontSz, e.col_grey8, m.accentLow, m.accentHigh, 0, 127, 1) +local seqAccProbSldr = e.Vert_Slider:new({2,3}, sx+(sp*8), sy, sw, sh, e.col_blue, "%", m.defFont, m.defFontSz, e.col_grey8, m.accentProb, 0, 0, 10, 1) +local seqAccSldrText = e.Textbox:new({2,3}, sx+(sp*7), 210, (sw * 2) + 10, 20, e.col_grey5, "Vel | Acc", m.defFont, m.defFontSz, e.col_grey7) -- legato slider -local seqLegProbSldr = e.Vert_Slider:new({2}, sx+(sp * 9), sy, sw, sh, e.col_blue, "%", e.Arial, 16, e.col_grey8, m.legatoProb, 0, 0, 10, 1) -local seqLegSldrText = e.Textbox:new({2}, sx+(sp * 9), 210, sw, 20, e.col_grey5, "Leg", e.Arial, 16, e.col_grey7) +local seqLegProbSldr = e.Vert_Slider:new({2}, sx+(sp * 9), sy, sw, sh, e.col_blue, "%", m.defFont, m.defFontSz, e.col_grey8, m.legatoProb, 0, 0, 10, 1) +local seqLegSldrText = e.Textbox:new({2}, sx+(sp * 9), 210, sw, 20, e.col_grey5, "Leg", m.defFont, m.defFontSz, e.col_grey7) -- repeat dropboxes -local seqRepLenDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+15, sw*2, 20, e.col_blue, "Length", e.Arial, 16, e.col_grey8, m.loopLenG, m.t_loopLenG) -local seqRepNumDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+65, sw*2, 20, e.col_blue, "Amount", e.Arial, 16, e.col_grey8, m.loopNum, m.t_loopRep) -local seqRepStartDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+115, sw*2, 20, e.col_blue, "Start", e.Arial, 16, e.col_grey8, m.loopStartG, m.t_loopStart) -local seqRepText = e.Textbox:new({2}, sx+(sp*10)+25, 210, sw*2, 20, e.col_grey5, "Repeat", e.Arial, 16, e.col_grey7) +local seqLoopLenDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+15, sw*2, 20, e.col_blue, "Length", m.defFont, m.defFontSz, e.col_grey8, m.loopLenG, m.t_loopLenG) +local seqLoopNumDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+65, sw*2, 20, e.col_blue, "Amount", m.defFont, m.defFontSz, e.col_grey8, m.loopNum, m.t_loopRep) +local seqLoopStartDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+115, sw*2, 20, e.col_blue, "Start", m.defFont, m.defFontSz, e.col_grey8, m.loopStartG, m.t_loopStart) +local seqLoopText = e.Textbox:new({2}, sx+(sp*10)+25, 210, sw*2, 20, e.col_grey5, "Repeat", m.defFont, m.defFontSz, e.col_grey7) -- sequence shift buttons -local seqShiftLBtn = e.Button:new({2}, sx+(sp*12)+30, sy+sh-25, sw-5, 25, e.col_blue, "<<", e.Arial, 16, e.col_grey8) -local seqShiftVal = e.Textbox:new({2}, sx+(sp*13)+15, sy+sh-25, sw, 25, e.col_grey5, tostring(m.seqShift), e.Arial, 16, e.col_grey7) -local seqShiftRBtn = e.Button:new({2}, sx+(sp*14)+5, sy+sh-25, sw-5, 25, e.col_blue, ">>", e.Arial, 16, e.col_grey8) -local seqShiftText = e.Textbox:new({2}, sx+(sp*12)+30, 210, sw*3-10, 20, e.col_grey5, "Shift Notes", e.Arial, 16, e.col_grey7) +local seqShiftLBtn = e.Button:new({2}, sx+(sp*12)+30, sy+sh-25, sw-5, 25, e.col_blue, "<<", m.defFont, m.defFontSz, e.col_grey8) +local seqShiftVal = e.Textbox:new({2}, sx+(sp*13)+15, sy+sh-25, sw, 25, e.col_grey5, tostring(m.seqShift), m.defFont, m.defFontSz, e.col_grey7) +local seqShiftRBtn = e.Button:new({2}, sx+(sp*14)+5, sy+sh-25, sw-5, 25, e.col_blue, ">>", m.defFont, m.defFontSz, e.col_grey8) +local seqShiftText = e.Textbox:new({2}, sx+(sp*12)+30, 210, sw*3-10, 20, e.col_grey5, "Shift Notes", m.defFont, m.defFontSz, e.col_grey7) -- Sequencer options -local seqOptionsCb = e.Checkbox:new({2}, sx+(np * 15) + 10, sy + 5, 30, 30, e.col_orange, "", e.Arial, 16, e.col_grey8, {0,0,0,0,0}, {"Generate", "Force 1st Note", "Accent", "Legato", "Rnd Notes", "Repeat"}) +local seqOptionsCb = e.Checkbox:new({2}, sx+(np * 15) + 10, sy + 5, 30, 30, e.col_orange, "", m.defFont, m.defFontSz, e.col_grey8, {0,0,0,0,0}, {"Generate", "Force 1st Note", "Accent", "Legato", "Rnd Notes", "Repeat"}) -------------------------------------------------------------------------------- -- Euclid Layer -------------------------------------------------------------------------------- -- euclid generate button -local euclidBtn = e.Button:new({3}, 25, 205, 100, 25, e.col_orange, "Generate", Arial, 16, e.col_grey8) +local euclidBtn = e.Button:new({3}, 25, 205, 100, 25, e.col_orange, "Generate", m.defFont, m.defFontSz, e.col_grey8) -- euclidean sliders local ex, ey, ew, eh, ep = 160, 50, 30, 150, 40 -local euclidPulsesSldr = e.Vert_Slider:new({3}, ex+(ep*2), ey, ew, eh, e.col_blue, "Puls", Arial, 16, e.col_grey8, m.eucPulses, 0, 1, 24, 1) -local euclidStepsSldr = e.Vert_Slider:new({3}, ex+(ep*3), ey, ew, eh, e.col_blue, "Step", Arial, 16, e.col_grey8, m.eucSteps, 0, 1, 24, 1) -local euclidRotationSldr = e.Vert_Slider:new({3}, ex+(ep*4), ey, ew, eh, e.col_blue, "Rot", Arial, 16, e.col_grey8, m.eucRot, 0, 0, 24, 1) +local euclidPulsesSldr = e.Vert_Slider:new({3}, ex+(ep*2), ey, ew, eh, e.col_blue, "Puls", m.defFont, m.defFontSz, e.col_grey8, m.eucPulses, 0, 1, 24, 1) +local euclidStepsSldr = e.Vert_Slider:new({3}, ex+(ep*3), ey, ew, eh, e.col_blue, "Step", m.defFont, m.defFontSz, e.col_grey8, m.eucSteps, 0, 1, 24, 1) +local euclidRotationSldr = e.Vert_Slider:new({3}, ex+(ep*4), ey, ew, eh, e.col_blue, "Rot", m.defFont, m.defFontSz, e.col_grey8, m.eucRot, 0, 0, 24, 1) local t_euclidSliders = {euclidPulsesSldr, euclidStepsSldr, euclidRotationSldr} -- euclid slider label - right click to reset all -local txtEuclidLabel = e.Textbox:new({3}, ex + (ep * 2), 210, (ew * 3) + 20, 20, e.col_grey5, "Euclid Sliders", Arial, 16, e.col_grey7) +local txtEuclidLabel = e.Textbox:new({3}, ex + (ep * 2), 210, (ew * 3) + 20, 20, e.col_grey5, "Euclid Sliders", m.defFont, m.defFontSz, e.col_grey7) -- Sequencer options -local eucOptionsCb = e.Checkbox:new({3}, ex + (ep * 15)- 10, ey + 40, 30, 30, e.col_orange, "", e.Arial, 16, e.col_grey8, {0,0,0}, {"Generate", "Accent", "Rnd Notes"}) +local eucOptionsCb = e.Checkbox:new({3}, ex + (ep * 15)- 10, ey + 40, 30, 30, e.col_orange, "", m.defFont, m.defFontSz, e.col_grey8, {0,0,0}, {"Generate", "Accent", "Rnd Notes"}) -------------------------------------------------------------------------------- -- Options Layer -------------------------------------------------------------------------------- -local optText = e.Textbox:new({4}, m.win_x + 10, m.win_y + 30, m.win_w - 40, m.win_h - 80, e.col_grey5, "Nothing to see here, yet...", e.Arial, 16, e.col_grey8) +local optText = e.Textbox:new({4}, m.win_x + 10, m.win_y + 30, m.win_w - 40, m.win_h - 80, e.col_grey5, "Nothing to see here, yet...", m.defFont, m.defFontSz, e.col_grey8) -------------------------------------------------------------------------------- -- Messages Layer -------------------------------------------------------------------------------- -local msgText = e.Textbox:new({9}, m.win_x + 10, m.win_y + 30, m.win_w - 40, m.win_h - 80, e.col_greym, "", e.Arial, 22, e.col_grey9) +local msgText = e.Textbox:new({9}, m.win_x + 10, m.win_y + 30, m.win_w - 40, m.win_h - 80, e.col_greym, "", m.defFont, 22, e.col_grey9) -------------------------------------------------------------------------------- -- Shared Element Tables -------------------------------------------------------------------------------- local t_Buttons = {randomBtn, sequenceBtn, seqShiftLBtn, seqShiftRBtn, euclidBtn} local t_Checkboxes = {noteOptionsCb, seqOptionsCb, eucOptionsCb} -local t_Droplists2 = {seqRepLenDrop, seqRepNumDrop, seqRepStartDrop} +local t_Droplists2 = {seqLoopLenDrop, seqLoopNumDrop, seqLoopStartDrop} local t_RadButtons = {seqGridRad} local t_RSliders = {octProbSldr, seqAccRSldr, seqAccProbSldr, seqLegProbSldr} -local t_Textboxes = {probSldrText, octProbText, seqGridText, seqSldrText, seqShiftVal, seqRepText, seqShiftText, seqAccSldrText, seqLegSldrText, txtEuclidLabel, optText, msgText} +local t_Textboxes = {probSldrText, octProbText, seqGridText, seqSldrText, seqShiftVal, seqLoopText, seqShiftText, seqAccSldrText, seqLegSldrText, txtEuclidLabel, optText, msgText} -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- @@ -1761,14 +1757,14 @@ seqShiftRBtn.onLClick = function() InsertNotes() end -- Sequencer repeat length -seqRepLenDrop.onLClick = function() +seqLoopLenDrop.onLClick = function() local debug = true - if debug or m.debug then ConMsg("\noseqRepLenDrop.onLClick()") end - m.loopLenG = seqRepLenDrop.val1 + if debug or m.debug then ConMsg("\noseqLoopLenDrop.onLClick()") end + m.loopLenG = seqLoopLenDrop.val1 if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end ---seqRepLenDrop ---seqRepNumDrop ---seqRepStartDrop +--seqLoopLenDrop +--seqLoopNumDrop +--seqLoopStartDrop -- set project ext state --pExtState.oct = m.oct @@ -1776,14 +1772,14 @@ seqRepLenDrop.onLClick = function() --pExtSaveStateF = true end -- Sequencer repeat length -seqRepNumDrop.onLClick = function() +seqLoopNumDrop.onLClick = function() local debug = true - if debug or m.debug then ConMsg("\noseqRepNumDrop.onLClick()") end - m.loopNum = seqRepNumDrop.val1 + if debug or m.debug then ConMsg("\noseqLoopNumDrop.onLClick()") end + m.loopNum = seqLoopNumDrop.val1 if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end ---seqRepLenDrop ---seqRepNumDrop ---seqRepStartDrop +--seqLoopLenDrop +--seqLoopNumDrop +--seqLoopStartDrop -- set project ext state --pExtState.oct = m.oct @@ -1791,14 +1787,14 @@ seqRepNumDrop.onLClick = function() --pExtSaveStateF = true end -- Sequencer repeat length -seqRepStartDrop.onLClick = function() +seqLoopStartDrop.onLClick = function() local debug = true - if debug or m.debug then ConMsg("\noseqRepStartDrop.onLClick()") end - m.loopStartG = seqRepStartDrop.val1 + if debug or m.debug then ConMsg("\noseqLoopStartDrop.onLClick()") end + m.loopStartG = seqLoopStartDrop.val1 if debug or m.debug then ConMsg("m.loopStartG = " .. tostring(m.t_loopStart[m.loopStartG])) end ---seqRepLenDrop ---seqRepNumDrop ---seqRepStartDrop +--seqLoopLenDrop +--seqLoopNumDrop +--seqLoopStartDrop -- set project ext state --pExtState.oct = m.oct @@ -1920,21 +1916,21 @@ function SetDefaultSeqRepeat() m.loopLenG = 1; m.loopNum = 1; m.loopStartG = 1 - seqRepNumDrop.val1 = m.loopNum - seqRepLenDrop.val1 = m.loopLenG - seqRepStartDrop.val1 = m.loopStartG + seqLoopNumDrop.val1 = m.loopNum + seqLoopLenDrop.val1 = m.loopLenG + seqLoopStartDrop.val1 = m.loopStartG m.loopMaxRep = math.floor(itemLength / gridSize) for i = 1, m.loopMaxRep do - seqRepNumDrop.val2[i] = i - seqRepLenDrop.val2[i] = i - seqRepStartDrop.val2[i] = i-1 + seqLoopNumDrop.val2[i] = i + seqLoopLenDrop.val2[i] = i + seqLoopStartDrop.val2[i] = i-1 end --[[ m.repNum, m.repLenGrid, m.repMax, m.repLenPPQN -seqRepLenDrop, m.t_loopLenG) -seqRepNumDrop, m.t_loopRep) +seqLoopLenDrop, m.t_loopLenG) +seqLoopNumDrop, m.t_loopRep) --]] end From 78c5037cc77a2cd292f3d035784573efd8b2a6b3 Mon Sep 17 00:00:00 2001 From: RobU Date: Sat, 20 May 2017 11:50:41 +0100 Subject: [PATCH 06/33] more repeat code... --- .../RobU - MIDI Ex Machina.lua | 135 ++++++++++-------- 1 file changed, 76 insertions(+), 59 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index feb74ad..209950e 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -481,7 +481,7 @@ end -- GetNotesFromTake() - fill a note buffer from the active take -------------------------------------------------------------------------------- function GetNotesFromTake() - local debug = true + local debug = false if debug or m.debug then ConMsg("GetNotesFromTake()") end local i, t if m.activeTake then @@ -723,7 +723,7 @@ end -- RandomiseNotesPoly(noteProbTable) -------------------------------------------------------------------------------- function RandomiseNotesPoly(noteProbTable) - local debug = true + local debug = false if debug or m.debug then ConMsg("RandomiseNotesPoly()") end m.dupes.i = 1 local i = 1 @@ -752,7 +752,7 @@ end -- GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) -------------------------------------------------------------------------------- function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) - local debug = true + local debug = false if debug or m.debug then ConMsg("GenSequence()") end local t, t2 = NewNoteBuf(), GetNoteBuf() CopyTable(t2, t) @@ -804,9 +804,7 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) t[noteCount][5] = noteLen -- note length t[noteCount][6] = 0 -- channel t[noteCount][7] = m.root -- note number - t[noteCount][8] = noteVel -- velocity - t[noteCount][9] = noteLeg -- legato end -- newNote @@ -903,26 +901,6 @@ function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) InsertNotes() end -------------------------------------------------------------------------------- --- SetNotes - arg notebuf t1; set notes in the active take --------------------------------------------------------------------------------- -function SetNotes() - local debug = false - if debug or m.debug then ConMsg("SetNotes()") end - local i = 1 - if m.activeTake then - local t1 = GetNoteBuf() - while t1[i] do - reaper.MIDI_SetNote(m.activeTake, i-1, t1[i][1], t1[i][2], t1[i][3], t1[i][4], t1[i][6], t1[i][7], t1[i][8], __) - --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) - i = i + 1 - end -- while t1[i] - reaper.MIDI_Sort(m.activeTake) - reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off - else - if debug or m.debug then ConMsg("No Active Take") end - end -- m.activeTake -end --------------------------------------------------------------------------------- -- InsertNotes() - insert current note buffer in the active take -------------------------------------------------------------------------------- function InsertNotes() @@ -954,9 +932,10 @@ function InsertNotes() -- note repeater if m.seqRepeatF then + if debug then ConMsg("Repeating...") end DeleteNotes() t3 = {} -- temp table for note repeater (no undo) - local loopStartP = m.t_loopStart[m.loopStartG] * gridSize + local loopStartP = (m.t_loopStart[m.loopStartG] - 1) * gridSize local loopLenP = m.loopLenG * gridSize local loopEndP = loopStartP + loopLenP local loopNum = m.loopNum @@ -1228,9 +1207,9 @@ local seqLegProbSldr = e.Vert_Slider:new({2}, sx+(sp * 9), sy, sw, sh, e.col_blu local seqLegSldrText = e.Textbox:new({2}, sx+(sp * 9), 210, sw, 20, e.col_grey5, "Leg", m.defFont, m.defFontSz, e.col_grey7) -- repeat dropboxes -local seqLoopLenDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+15, sw*2, 20, e.col_blue, "Length", m.defFont, m.defFontSz, e.col_grey8, m.loopLenG, m.t_loopLenG) -local seqLoopNumDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+65, sw*2, 20, e.col_blue, "Amount", m.defFont, m.defFontSz, e.col_grey8, m.loopNum, m.t_loopRep) -local seqLoopStartDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+115, sw*2, 20, e.col_blue, "Start", m.defFont, m.defFontSz, e.col_grey8, m.loopStartG, m.t_loopStart) +local seqLoopStartDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+15, sw*2, 20, e.col_blue, "Start", m.defFont, m.defFontSz, e.col_grey8, m.loopStartG, m.t_loopStart) +local seqLoopLenDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+65, sw*2, 20, e.col_blue, "Length", m.defFont, m.defFontSz, e.col_grey8, m.loopLenG, m.t_loopLenG) +local seqLoopNumDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+115, sw*2, 20, e.col_blue, "Amount", m.defFont, m.defFontSz, e.col_grey8, m.loopNum, m.t_loopRep) local seqLoopText = e.Textbox:new({2}, sx+(sp*10)+25, 210, sw*2, 20, e.col_grey5, "Repeat", m.defFont, m.defFontSz, e.col_grey7) -- sequence shift buttons @@ -1614,8 +1593,10 @@ sequenceBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nsequenceBtn.onLClick()") end if m.activeTake then - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence - seqShiftVal.label = tostring(m.seqShift) + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn off repeat + InsertNotes() + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence + seqShiftVal.label = tostring(m.seqShift) if m.seqF then SetSeqGridSizes(t_seqSliders) GenProbTable(m.preSeqProbTable, t_seqSliders, m.seqProbTable) @@ -1654,7 +1635,8 @@ sequenceBtn.onLClick = function() pExtState.seqGrid4[k] = v.val1 end end - + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn on repeat + InsertNotes() pExtState.seqAccRSldrLo = seqAccRSldr.val1 pExtState.seqAccRSldrHi = seqAccRSldr.val2 pExtState.seqAccProb = seqAccProbSldr.val1 @@ -1663,6 +1645,7 @@ sequenceBtn.onLClick = function() pExtSaveStateF = true end --m.activeTake end + -- Sequencer options toggle logic seqOptionsCb.onLClick = function() local debug = false @@ -1673,10 +1656,14 @@ seqOptionsCb.onLClick = function() m.seqLegatoF = seqOptionsCb.val1[4] == 1 and true or false -- Legato m.seqRndNotesF = seqOptionsCb.val1[5] == 1 and true or false -- Randomise Notes m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Repeat + if pExtState.seqOptionsCb then + if pExtState.seqOptionsCb[6] ~= m.seqRepeatF then InsertNotes() end + end pExtState.seqOptionsCb = {m.seqF, m.seqFirstNoteF, m.seqAccentF, m.seqLegatoF, m.seqRndNotesF, m.seqRepeatF} pExtSaveStateF = true if debug or m.debug then PrintTable(seqOptionsCb.val1) end end + -- Sequencer grid radio button seqGridRad.onLClick = function() -- change grid size local debug = false @@ -1730,6 +1717,7 @@ seqGridRad.onLClick = function() -- change grid size end -- m.activeTake end + -- Sequencer shift left seqShiftLBtn.onLClick = function() local gridSize = m.reaGrid * m.ppqn @@ -1756,51 +1744,41 @@ seqShiftRBtn.onLClick = function() seqShiftVal.label = tostring(m.seqShift) InsertNotes() end --- Sequencer repeat length -seqLoopLenDrop.onLClick = function() - local debug = true - if debug or m.debug then ConMsg("\noseqLoopLenDrop.onLClick()") end - m.loopLenG = seqLoopLenDrop.val1 - if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end ---seqLoopLenDrop ---seqLoopNumDrop ---seqLoopStartDrop +-- Sequencer repeat start +seqLoopStartDrop.onLClick = function() + local debug = true + if debug or m.debug then ConMsg("\nseqLoopStartDrop.onLClick()") end + m.loopStartG = seqLoopStartDrop.val1 + UpdateSeqRepeat() -- set project ext state --pExtState.oct = m.oct --pExtState.root = m.root --pExtSaveStateF = true end -- Sequencer repeat length -seqLoopNumDrop.onLClick = function() +seqLoopLenDrop.onLClick = function() local debug = true - if debug or m.debug then ConMsg("\noseqLoopNumDrop.onLClick()") end - m.loopNum = seqLoopNumDrop.val1 - if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end ---seqLoopLenDrop ---seqLoopNumDrop ---seqLoopStartDrop - + if debug or m.debug then ConMsg("\nseqLoopLenDrop.onLClick()") end + m.loopLenG = seqLoopLenDrop.val1 + UpdateSeqRepeat() -- set project ext state --pExtState.oct = m.oct --pExtState.root = m.root --pExtSaveStateF = true end --- Sequencer repeat length -seqLoopStartDrop.onLClick = function() +-- Sequencer repeat amount +seqLoopNumDrop.onLClick = function() local debug = true - if debug or m.debug then ConMsg("\noseqLoopStartDrop.onLClick()") end - m.loopStartG = seqLoopStartDrop.val1 - if debug or m.debug then ConMsg("m.loopStartG = " .. tostring(m.t_loopStart[m.loopStartG])) end ---seqLoopLenDrop ---seqLoopNumDrop ---seqLoopStartDrop - + if debug or m.debug then ConMsg("\nseqLoopNumDrop.onLClick()") end + m.loopNum = seqLoopNumDrop.val1 + UpdateSeqRepeat() -- set project ext state --pExtState.oct = m.oct --pExtState.root = m.root --pExtSaveStateF = true end + -- Set sequencer default options function SetDefaultSeqOptions() local debug = false @@ -1824,6 +1802,7 @@ function SetDefaultSeqOptions() seqOptionsCb.val1[5] = (true and m.seqRndNotesF) and 1 or 0 -- random notes seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 -- repeat end + -- Set default accent & legato sliders function SetDefaultAccLegSliders() local debug = false @@ -1850,6 +1829,7 @@ function SetDefaultAccLegSliders() seqLegProbSldr.val1 = m.legatoProb end end + -- Set default grid sliders function SetDefaultSeqGridSliders() local debug = false @@ -1899,6 +1879,7 @@ function SetDefaultSeqGridSliders() end end + -- Set default sequencer shift state function SetDefaultSeqShift() local debug = false @@ -1908,6 +1889,7 @@ function SetDefaultSeqShift() m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) end + -- Set default sequencer repeat state function SetDefaultSeqRepeat() GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) @@ -1923,9 +1905,9 @@ function SetDefaultSeqRepeat() m.loopMaxRep = math.floor(itemLength / gridSize) for i = 1, m.loopMaxRep do + seqLoopStartDrop.val2[i] = i seqLoopNumDrop.val2[i] = i seqLoopLenDrop.val2[i] = i - seqLoopStartDrop.val2[i] = i-1 end --[[ m.repNum, m.repLenGrid, m.repMax, m.repLenPPQN @@ -1933,6 +1915,41 @@ seqLoopLenDrop, m.t_loopLenG) seqLoopNumDrop, m.t_loopRep) --]] end +-- Update sequencer repeat state +function UpdateSeqRepeat() + local debug = true + if debug or m.debug then ConMsg("\nUpdateSeqRepeat()") end + GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) + local gridSizeP = m.reaGrid * m.ppqn + if debug or m.debug then ConMsg("gridSizeP = " .. tostring(gridSizeP)) end + local itemLenP = GetItemLength() + if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end + local itemLenG = math.floor(itemLenP / gridSizeP) + if debug or m.debug then ConMsg("itemLenG = " .. tostring(itemLenG)) end + local remLenG = itemLenG - m.loopStartG + if debug or m.debug then ConMsg("remLenG = " .. tostring(remLenG)) end + + -- set the start point lookup table + for i = 1, itemLenG do + seqLoopStartDrop.val2[i], m.t_loopStart[i] = i, i + end + + + --[[ +m.t_loopStart, m.t_loopRep, m.t_loopLenG +seqLoopStartDrop.val1 = m.loopStartG -- loop start point in grid pos +seqLoopStartDrop.val2[m.loopStartG] -- loop start lookup table +seqLoopLenDrop.val1 = m.loopLenG -- loop len in grid units +seqLoopLenDrop.val2[m.loopLenG] -- loop len lookup table +seqLoopNumDrop.val1 = m.loopNum -- loop amount integer +seqLoopNumDrop.val2[m.loopNum] -- loop amount lookup table +--]] +if m.seqRepeatF then InsertNotes() end + + if debug or m.debug then ConMsg("m.loopStartG = " .. tostring(m.t_loopStart[m.loopStartG])) end + if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end + if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end +end -- Reset sequencer grid sliders seqSldrText.onRClick = function() From 396f09cc2faa95bbae0d10583bc4439c12923a09 Mon Sep 17 00:00:00 2001 From: RobU Date: Sun, 21 May 2017 17:24:14 +0100 Subject: [PATCH 07/33] fixed noteShift bug added note repeater onLClick logic added beta repeat functionality to InsertNotes --- .../RobU - MIDI Ex Machina.lua | 310 ++++++++++++------ 1 file changed, 218 insertions(+), 92 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 209950e..097534f 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -116,10 +116,7 @@ m.seqGrid8 = {0, 8, 2, 2} -- sane default sequencer note length slider values m.seqGrid4 = {0, 2, 8, 1} -- sane default sequencer note length slider values m.seqShift = 0; m.seqShiftMin = -16; m.seqShiftMax = 16 -- shift notes left-right from sequencer m.loopStartG, m.loopLenG, m.loopNum, m.loopMaxRep = 0, 0, 0, 0 -- repeat values for GUI -m.t_loopStart, m.t_loopRep, m.t_loopLenG = {}, {}, {} -- repeat value tables - ---m.repNum, m.repLenGrid, m.repMax, m.repLenPPQN = 0, 0, 0, 0 -- repeat values - +m.t_loopStart, m.t_loopNum, m.t_loopLen = {}, {}, {} -- repeat value tables -- euclidean generator m.eucF = true -- generate euclid (option) @@ -434,7 +431,7 @@ function GetItemLength() ConMsg("Num of Bar = " .. numBarsPerItem) ConMsg("Item size ppqn = " .. ItemPPQN .. "\n") end - return ItemPPQN + return math.floor(ItemPPQN) end -------------------------------------------------------------------------------- -- GetReaperGrid() - get the current grid size, set global var m.reaGrid @@ -754,10 +751,8 @@ end function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) local debug = false if debug or m.debug then ConMsg("GenSequence()") end - local t, t2 = NewNoteBuf(), GetNoteBuf() - CopyTable(t2, t) + local t = NewNoteBuf() GetReaperGrid() -- populates m.reaGrid - ClearTable(t) local itemPos = 0 local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() @@ -811,8 +806,8 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) end -- itemPos < itemLength if debug or m.debug then PrintNotes(t) end PurgeNoteBuf() - if not m.seqRndNotesF then InsertNotes() end - --InsertNotes() + --if not m.seqRndNotesF then InsertNotes() end + InsertNotes() end -------------------------------------------------------------------------------- -- GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) @@ -868,7 +863,8 @@ function GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) idx = Wrap(idx, step) end PurgeNoteBuf() - if not m.eucRndNotesF then InsertNotes() end + --if not m.eucRndNotesF then InsertNotes() end + InsertNotes() end -------------------------------------------------------------------------------- -- GenNoteAttributes(accF, accProb, accVal, legF, legVal) -- accent, legato only @@ -904,29 +900,38 @@ end -- InsertNotes() - insert current note buffer in the active take -------------------------------------------------------------------------------- function InsertNotes() - local debug = true + local debug = false if debug or m.debug then ConMsg("\nInsertNotes()") end local i = 1 if m.activeTake then - local gridSize = m.reaGrid * m.ppqn + local gridSize = math.floor(m.reaGrid * m.ppqn) local itemLenP = GetItemLength() - local noteShift = m.seqShift * gridSize + local noteShift = math.floor(m.seqShift * gridSize) local t1 = GetNoteBuf() - PrintNotes(t1) + if debug then PrintNotes(t1) end -- note shifter + if debug then ConMsg("Shifting...") end local t2 = {} -- temp table for note shifter (no undo) + if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end + if debug or m.debug then ConMsg("gridSize = " .. tostring(gridSize)) end + if debug or m.debug then ConMsg("noteShift = " .. tostring(noteShift)) end CopyTable(t1, t2) for k, v in pairs(t2) do + if debug or m.debug then ConMsg("idx =\t" .. tostring(k)) end + if debug or m.debug then ConMsg("orig start =\t" .. tostring(v[3]) .. " - orig end =\t" .. tostring(v[4])) end v[3] = v[3] + noteShift - v[4] = v[4] + noteShift + v[4] = v[4] + noteShift + if debug or m.debug then ConMsg("shift start =\t" .. tostring(v[3]) .. " - shift end =\t" .. tostring(v[4])) end if v[3] < 0 then v[3] = itemLenP + v[3] - v[4] = itemLenP + v[4] + v[4] = itemLenP + v[4] if v[4] > itemLenP then v[4] = itemLenP end + if debug or m.debug then ConMsg("neg start =\t" .. tostring(v[3]) .. " - neg end =\t" .. tostring(v[4])) end elseif v[3] >= itemLenP then v[3] = v[3] - itemLenP - v[4] = v[4] - itemLenP + v[4] = v[4] - itemLenP + if debug or m.debug then ConMsg("pos start =\t" .. tostring(v[3]) .. " - poa end =\t" .. tostring(v[4])) end end end -- for k, v t2 @@ -935,11 +940,12 @@ function InsertNotes() if debug then ConMsg("Repeating...") end DeleteNotes() t3 = {} -- temp table for note repeater (no undo) - local loopStartP = (m.t_loopStart[m.loopStartG] - 1) * gridSize + local loopStartP = (m.loopStartG -1) * gridSize local loopLenP = m.loopLenG * gridSize local loopEndP = loopStartP + loopLenP local loopNum = m.loopNum local noteEnd + local kOff = 0 local writeOffP = 0 if loopStartP > 0 then writeOffP = -loopStartP else writeOffP = 0 end @@ -950,39 +956,97 @@ function InsertNotes() if debug or m.debug then ConMsg("loopNum = " .. tostring(loopNum)) end if debug or m.debug then ConMsg("writeOffP = " .. tostring(writeOffP)) end + -- pre-repeat start + if debug or m.debug then ConMsg("\nStart pre-repeat...") end + for k, v in pairs(t2) do + if v[3] >= 0 and v[3] < loopStartP then + t3[k] = {} + t3[k][1] = v[1] -- selected + t3[k][2] = v[2] -- muted + t3[k][3] = v[3] -- startppqn + t3[k][4] = v[4] -- endppqn + if not t3[k][9] then t3[k][4] = t3[k][4] - m.legato end -- handle the legatolessness + t3[k][6] = v[6] -- channel + t3[k][7] = v[7] -- pitch + t3[k][8] = v[8] -- vel + if debug or m.debug then ConMsg("a - idx = " .. tostring(k) .. " - Start = " .. tostring(v[3]) .. " - End = " .. tostring(v[4])) end + if debug or m.debug then ConMsg("b - idx = " .. tostring(k) .. " - Start = " .. tostring(t3[k][3]) .. " - End = " .. tostring(t3[k][4])) end + reaper.MIDI_InsertNote(m.activeTake, t3[k][1], t3[k][2], t3[k][3], t3[k][4], t3[k][6], t3[k][7], t3[k][8], false) + kOff = kOff + 1 + --if debug or m.debug then ConMsg("kOff = " .. tostring(kOff)) end + end + end -- k, v in pairs(t2) - pre-repeat + writeOffP = writeOffP + loopStartP + + -- repeat start if debug or m.debug then ConMsg("\nStart repeater...") end while loopNum > 0 do if debug or m.debug then ConMsg("\nloopNum = " .. tostring(loopNum)) end if debug or m.debug then ConMsg("writeOffP = " .. tostring(writeOffP)) end - for k, v in pairs(t2) do if v[3] >= loopStartP and v[3] < loopEndP then - t3[k] = {} - t3[k][1] = v[1] -- selected - t3[k][2] = v[2] -- muted - - t3[k][3] = v[3] + writeOffP -- startppqn - + t3[k + kOff] = {} + t3[k + kOff][1] = v[1] -- selected + t3[k + kOff][2] = v[2] -- muted + t3[k + kOff][3] = v[3] + writeOffP -- startppqn if v[4] > loopEndP then -- endppqn - t3[k][4] = loopEndP + writeOffP + t3[k + kOff][4] = loopEndP + writeOffP else - t3[k][4] = v[4] + writeOffP + t3[k + kOff][4] = v[4] + writeOffP end - - if not t3[k][9] then t3[k][4] = t3[k][4] - m.legato end -- handle the legatolessness - - t3[k][6] = v[6] -- channel - t3[k][7] = v[7] -- pitch - t3[k][8] = v[8] -- vel + if not t3[k + kOff][9] then t3[k + kOff][4] = t3[k + kOff][4] - m.legato end -- handle the legatolessness + t3[k + kOff][6] = v[6] -- channel + t3[k + kOff][7] = v[7] -- pitch + t3[k + kOff][8] = v[8] -- vel if debug or m.debug then ConMsg("a - idx = " .. tostring(k) .. " - Start = " .. tostring(v[3]) .. " - End = " .. tostring(v[4])) end - if debug or m.debug then ConMsg("b - idx = " .. tostring(k) .. " - Start = " .. tostring(t3[k][3]) .. " - End = " .. tostring(t3[k][4])) end - reaper.MIDI_InsertNote(m.activeTake, t3[k][1], t3[k][2], t3[k][3], t3[k][4], t3[k][6], t3[k][7], t3[k][8], false) + if debug or m.debug then ConMsg("b - idx = " .. tostring(k + kOff) .. " - Start = " .. tostring(t3[k + kOff][3]) .. " - End = " .. tostring(t3[k + kOff][4])) end + reaper.MIDI_InsertNote(m.activeTake, t3[k + kOff][1], t3[k + kOff][2], t3[k + kOff][3], t3[k + kOff][4], t3[k + kOff][6], t3[k + kOff][7], t3[k + kOff][8], false) end -- if v[3] - end -- for k, v t3 + end -- for k, v t3 - repeat loopNum = loopNum - 1 writeOffP = writeOffP + loopLenP - end + end -- while loopNum > 0 + + -- post-repeat start + if debug or m.debug then ConMsg("\nStart post-repeat...") end + if debug or m.debug then ConMsg("writeOffP = " .. tostring(writeOffP)) end + + kOff = kOff + 1 + local written = loopStartP + (loopLenP * m.loopNum) + if debug or m.debug then ConMsg("written = " .. tostring(written)) end + local remLenP = itemLenP - written + if debug or m.debug then ConMsg("remLenP = " .. tostring(remLenP)) end + local readStartP = loopStartP + loopLenP + if debug or m.debug then ConMsg("readStartP = " .. tostring(readStartP)) end + local readEndP = readStartP + remLenP + if debug or m.debug then ConMsg("readEndP = " .. tostring(readEndP)) end + local writeOffP = written - readStartP + if debug or m.debug then ConMsg("writeOffP = " .. tostring(writeOffP)) end + + for k, v in pairs(t2) do + if v[3] >= readStartP and v[3] < readEndP then + t3[k + kOff] = {} + t3[k + kOff][1] = v[1] -- selected + t3[k + kOff][2] = v[2] -- muted + t3[k + kOff][3] = v[3] + writeOffP -- startppqn + if v[4] > itemLenP then -- endppqn + t3[k + kOff][4] = itemLenP + else + t3[k + kOff][4] = v[4] + writeOffP + end + if not t3[k + kOff][9] then t3[k + kOff][4] = t3[k + kOff][4] - m.legato end -- handle the legatolessness + t3[k + kOff][6] = v[6] -- channel + t3[k + kOff][7] = v[7] -- pitch + t3[k + kOff][8] = v[8] -- vel + if debug or m.debug then ConMsg("a - idx = " .. tostring(k) .. " - Start = " .. tostring(v[3]) .. " - End = " .. tostring(v[4])) end + if debug or m.debug then ConMsg("b - idx = " .. tostring(k + kOff) .. " - Start = " .. tostring(t3[k + kOff][3]) .. " - End = " .. tostring(t3[k + kOff][4])) end + reaper.MIDI_InsertNote(m.activeTake, t3[k + kOff][1], t3[k + kOff][2], t3[k + kOff][3], t3[k + kOff][4], t3[k + kOff][6], t3[k + kOff][7], t3[k + kOff][8], false) + kOff = kOff + 1 + if debug or m.debug then ConMsg("kOff = " .. tostring(kOff)) end + end + end -- k, v in pairs(t2) - post-repeat + reaper.MIDI_Sort(m.activeTake) reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off else -- not m.seqRepeatF @@ -1064,7 +1128,7 @@ end -- PrintNotes - arg note_buffer t; print note_buffer to reaper console -------------------------------------------------------------------------------- function PrintNotes(t) -- debug code - local debug = true + local debug = false if debug or m.debug then ConMsg("PrintNotes()") end if not t then return end local i = 1 @@ -1208,8 +1272,8 @@ local seqLegSldrText = e.Textbox:new({2}, sx+(sp * 9), 210, sw, 20, e.col_gr -- repeat dropboxes local seqLoopStartDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+15, sw*2, 20, e.col_blue, "Start", m.defFont, m.defFontSz, e.col_grey8, m.loopStartG, m.t_loopStart) -local seqLoopLenDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+65, sw*2, 20, e.col_blue, "Length", m.defFont, m.defFontSz, e.col_grey8, m.loopLenG, m.t_loopLenG) -local seqLoopNumDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+115, sw*2, 20, e.col_blue, "Amount", m.defFont, m.defFontSz, e.col_grey8, m.loopNum, m.t_loopRep) +local seqLoopLenDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+65, sw*2, 20, e.col_blue, "Length", m.defFont, m.defFontSz, e.col_grey8, m.loopLenG, m.t_loopLen) +local seqLoopNumDrop = e.Droplist:new({2}, sx+(sp*10)+25, sy+115, sw*2, 20, e.col_blue, "Amount", m.defFont, m.defFontSz, e.col_grey8, m.loopNum, m.t_loopNum) local seqLoopText = e.Textbox:new({2}, sx+(sp*10)+25, 210, sw*2, 20, e.col_grey5, "Repeat", m.defFont, m.defFontSz, e.col_grey7) -- sequence shift buttons @@ -1747,10 +1811,51 @@ end -- Sequencer repeat start seqLoopStartDrop.onLClick = function() - local debug = true + local debug = false if debug or m.debug then ConMsg("\nseqLoopStartDrop.onLClick()") end + + GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) + local gridSizeP = m.reaGrid * m.ppqn + if debug or m.debug then ConMsg("gridSizeP = " .. tostring(gridSizeP)) end + local itemLenP = GetItemLength() + if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end + local itemLenG = math.floor(itemLenP / gridSizeP) + if debug or m.debug then ConMsg("itemLenG = " .. tostring(itemLenG)) end + local remLenG = itemLenG - (seqLoopStartDrop.val1 -1) + if debug or m.debug then ConMsg("remLenG = " .. tostring(remLenG)) end + + -- set the start point lookup table + for i = 1, itemLenG do + seqLoopStartDrop.val2[i] = i + m.t_loopStart[i] = i + end m.loopStartG = seqLoopStartDrop.val1 - UpdateSeqRepeat() + + -- check the loop length doesn't exceed the remaining item length + if seqLoopLenDrop.val1 > remLenG then seqLoopLenDrop.val1 = remLenG end + seqLoopLenDrop.val2 = {} + for i = 1, remLenG do + seqLoopLenDrop.val2[i] = i + end + m.loopLenG = seqLoopLenDrop.val1 + + -- check the loop amount doesn't exceed the remaining item length + while seqLoopNumDrop.val1 * m.loopLenG > remLenG do + seqLoopNumDrop.val1 = seqLoopNumDrop.val1 - 1 + end + seqLoopNumDrop.val2 = {} + local maxLoops = math.floor(remLenG / m.loopLenG) + for i = 1, maxLoops do + seqLoopNumDrop.val2[i] = i + end + m.loopNum = seqLoopNumDrop.val1 + + if m.seqRepeatF then InsertNotes() end + + if debug or m.debug then ConMsg("m.loopStartG = " .. tostring(m.loopStartG)) end + if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end + if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end + -- set project ext state --pExtState.oct = m.oct --pExtState.root = m.root @@ -1758,10 +1863,44 @@ seqLoopStartDrop.onLClick = function() end -- Sequencer repeat length seqLoopLenDrop.onLClick = function() - local debug = true + local debug = false if debug or m.debug then ConMsg("\nseqLoopLenDrop.onLClick()") end + + GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) + local gridSizeP = m.reaGrid * m.ppqn + if debug or m.debug then ConMsg("gridSizeP = " .. tostring(gridSizeP)) end + local itemLenP = GetItemLength() + if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end + local itemLenG = math.floor(itemLenP / gridSizeP) + if debug or m.debug then ConMsg("itemLenG = " .. tostring(itemLenG)) end + local remLenG = itemLenG - (seqLoopStartDrop.val1 -1) + if debug or m.debug then ConMsg("remLenG = " .. tostring(remLenG)) end + + -- check the loop length doesn't exceed the remaining item length + if seqLoopLenDrop.val1 > remLenG then seqLoopLenDrop.val1 = remLenG end + seqLoopLenDrop.val2 = {} + for i = 1, remLenG do + seqLoopLenDrop.val2[i] = i + end m.loopLenG = seqLoopLenDrop.val1 - UpdateSeqRepeat() + + -- check the loop amount doesn't exceed the remaining item length + while seqLoopNumDrop.val1 * m.loopLenG > remLenG do + seqLoopNumDrop.val1 = seqLoopNumDrop.val1 - 1 + end + seqLoopNumDrop.val2 = {} + local maxLoops = math.floor(remLenG / m.loopLenG) + for i = 1, maxLoops do + seqLoopNumDrop.val2[i] = i + end + m.loopNum = seqLoopNumDrop.val1 + + if m.seqRepeatF then InsertNotes() end + + if debug or m.debug then ConMsg("m.loopStartG = " .. tostring(m.t_loopStart[m.loopStartG])) end + if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end + if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end + -- set project ext state --pExtState.oct = m.oct --pExtState.root = m.root @@ -1769,10 +1908,36 @@ seqLoopLenDrop.onLClick = function() end -- Sequencer repeat amount seqLoopNumDrop.onLClick = function() - local debug = true + local debug = false if debug or m.debug then ConMsg("\nseqLoopNumDrop.onLClick()") end + + GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) + local gridSizeP = m.reaGrid * m.ppqn + if debug or m.debug then ConMsg("gridSizeP = " .. tostring(gridSizeP)) end + local itemLenP = GetItemLength() + if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end + local itemLenG = math.floor(itemLenP / gridSizeP) + if debug or m.debug then ConMsg("itemLenG = " .. tostring(itemLenG)) end + local remLenG = itemLenG - (seqLoopStartDrop.val1 -1) + if debug or m.debug then ConMsg("remLenG = " .. tostring(remLenG)) end + + -- check the loop amount doesn't exceed the remaining item length + while seqLoopNumDrop.val1 * m.loopLenG > remLenG do + seqLoopNumDrop.val1 = seqLoopNumDrop.val1 - 1 + end + seqLoopNumDrop.val2 = {} + local maxLoops = math.floor(remLenG / m.loopLenG) + for i = 1, maxLoops do + seqLoopNumDrop.val2[i] = i + end m.loopNum = seqLoopNumDrop.val1 - UpdateSeqRepeat() + + if m.seqRepeatF then InsertNotes() end + + if debug or m.debug then ConMsg("m.loopStartG = " .. tostring(m.t_loopStart[m.loopStartG])) end + if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end + if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end + -- set project ext state --pExtState.oct = m.oct --pExtState.root = m.root @@ -1802,7 +1967,6 @@ function SetDefaultSeqOptions() seqOptionsCb.val1[5] = (true and m.seqRndNotesF) and 1 or 0 -- random notes seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 -- repeat end - -- Set default accent & legato sliders function SetDefaultAccLegSliders() local debug = false @@ -1829,7 +1993,6 @@ function SetDefaultAccLegSliders() seqLegProbSldr.val1 = m.legatoProb end end - -- Set default grid sliders function SetDefaultSeqGridSliders() local debug = false @@ -1879,7 +2042,6 @@ function SetDefaultSeqGridSliders() end end - -- Set default sequencer shift state function SetDefaultSeqShift() local debug = false @@ -1889,67 +2051,31 @@ function SetDefaultSeqShift() m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) end - -- Set default sequencer repeat state function SetDefaultSeqRepeat() GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() - m.loopLenG = 1; m.loopNum = 1; m.loopStartG = 1 + m.loopStartG = 1; m.loopLenG = 1; m.loopNum = 1 + seqLoopStartDrop.val1 = m.loopStartG seqLoopNumDrop.val1 = m.loopNum seqLoopLenDrop.val1 = m.loopLenG - seqLoopStartDrop.val1 = m.loopStartG - + m.loopMaxRep = math.floor(itemLength / gridSize) for i = 1, m.loopMaxRep do - seqLoopStartDrop.val2[i] = i + seqLoopStartDrop.val2[i] = i seqLoopNumDrop.val2[i] = i seqLoopLenDrop.val2[i] = i end --[[ m.repNum, m.repLenGrid, m.repMax, m.repLenPPQN -seqLoopLenDrop, m.t_loopLenG) -seqLoopNumDrop, m.t_loopRep) +seqLoopLenDrop, m.t_loopLen) +seqLoopNumDrop, m.t_loopNum) --]] end --- Update sequencer repeat state -function UpdateSeqRepeat() - local debug = true - if debug or m.debug then ConMsg("\nUpdateSeqRepeat()") end - GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) - local gridSizeP = m.reaGrid * m.ppqn - if debug or m.debug then ConMsg("gridSizeP = " .. tostring(gridSizeP)) end - local itemLenP = GetItemLength() - if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end - local itemLenG = math.floor(itemLenP / gridSizeP) - if debug or m.debug then ConMsg("itemLenG = " .. tostring(itemLenG)) end - local remLenG = itemLenG - m.loopStartG - if debug or m.debug then ConMsg("remLenG = " .. tostring(remLenG)) end - - -- set the start point lookup table - for i = 1, itemLenG do - seqLoopStartDrop.val2[i], m.t_loopStart[i] = i, i - end - - - --[[ -m.t_loopStart, m.t_loopRep, m.t_loopLenG -seqLoopStartDrop.val1 = m.loopStartG -- loop start point in grid pos -seqLoopStartDrop.val2[m.loopStartG] -- loop start lookup table -seqLoopLenDrop.val1 = m.loopLenG -- loop len in grid units -seqLoopLenDrop.val2[m.loopLenG] -- loop len lookup table -seqLoopNumDrop.val1 = m.loopNum -- loop amount integer -seqLoopNumDrop.val2[m.loopNum] -- loop amount lookup table ---]] -if m.seqRepeatF then InsertNotes() end - - if debug or m.debug then ConMsg("m.loopStartG = " .. tostring(m.t_loopStart[m.loopStartG])) end - if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end - if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end -end -- Reset sequencer grid sliders seqSldrText.onRClick = function() From 06d9a74e51f7fe20402f890526e0a81b50c038d6 Mon Sep 17 00:00:00 2001 From: RobU Date: Sun, 21 May 2017 22:27:05 +0100 Subject: [PATCH 08/33] repeat glue fixes repeat code fixes --- .../RobU - MIDI Ex Machina.lua | 528 +++++++++++------- 1 file changed, 311 insertions(+), 217 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 097534f..ccaf6c1 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -73,7 +73,7 @@ local p = require 'persistence' -- currently unused, i.e. no preset save, load, -------------------------------------------------------------------------------- m = {} -- all ex machina data -- user changeable defaults are marked with "(option)" -m.debug = false +m.debug = true -- window m.win_title = "RobU : MIDI Ex Machina - v1.3.2"; m.win_dockstate = 0 m.win_x = 10; m.win_y = 10; m.win_w = 900; m.win_h = 280 -- window dimensions @@ -117,6 +117,7 @@ m.seqGrid4 = {0, 2, 8, 1} -- sane default sequencer note length slider values m.seqShift = 0; m.seqShiftMin = -16; m.seqShiftMax = 16 -- shift notes left-right from sequencer m.loopStartG, m.loopLenG, m.loopNum, m.loopMaxRep = 0, 0, 0, 0 -- repeat values for GUI m.t_loopStart, m.t_loopNum, m.t_loopLen = {}, {}, {} -- repeat value tables +m.loopGlueF = false -- euclidean generator m.eucF = true -- generate euclid (option) @@ -319,6 +320,7 @@ end function ClearTable(t) local debug = false if debug or m.debug then ConMsg("ClearTable()") end + for k, v in pairs(t) do t[k] = nil end @@ -327,6 +329,9 @@ end -- CopyTable(t1, t2) - copies note data from t1 to t2 -------------------------------------------------------------------------------- function CopyTable(t1, t2) + local debug = false + if debug or m.debug then ConMsg("CopyTable()") end + ClearTable(t2) local i = 1 while t1[i] do @@ -345,12 +350,13 @@ end local function NewNoteBuf() local debug = false if debug or m.debug then ConMsg("NewNoteBuf()") end + m.notebuf.i = m.notebuf.i + 1 m.notebuf.max = m.notebuf.max + 1 m.notebuf[m.notebuf.i] = {} if debug or m.debug then str = "created buffer\n" - str = str .. "buffer index = " .. tostring(m.notebuf.i) .. "\n" + str = str .. "buffer index = " .. tostring(m.notebuf.i) ConMsg(str) end return m.notebuf[m.notebuf.i] @@ -361,10 +367,11 @@ end local function GetNoteBuf() local debug = false if debug or m.debug then ConMsg("GetNoteBuf()") end + if m.notebuf.i >= 1 then if debug or m.debug then str = "retrieved buffer\n" - str = str .. "buffer index = " .. tostring(m.notebuf.i) .. "\n" + str = str .. "buffer index = " .. tostring(m.notebuf.i) ConMsg(str) end return m.notebuf[m.notebuf.i] @@ -376,17 +383,18 @@ end local function UndoNoteBuf() local debug = false if debug or m.debug then ConMsg("UndoNoteBuf()") end + if m.notebuf.i > 1 then m.notebuf.i = m.notebuf.i -1 if debug or m.debug then str = "removed buffer " .. tostring(m.notebuf.i + 1) .. "\n" - str = str .. "buffer index = " .. tostring(m.notebuf.i) .. "\n" + str = str .. "buffer index = " .. tostring(m.notebuf.i) ConMsg(str) end else if debug or m.debug then str = "nothing to undo...\n" - str = str .. "buffer index = " .. tostring(m.notebuf.i) .. "\n" + str = str .. "buffer index = " .. tostring(m.notebuf.i) ConMsg(str) end end @@ -401,6 +409,7 @@ local function PurgeNoteBuf() ConMsg("current idx = " .. tostring(m.notebuf.i)) ConMsg("max idx = " .. tostring(m.notebuf.max)) end + while m.notebuf.max > m.notebuf.i do m.notebuf[m.notebuf.max] = nil if debug or m.debug then ConMsg("purging buffer " .. tostring(m.notebuf.max)) @@ -415,6 +424,7 @@ end function GetItemLength() local debug = false if debug or m.debug then ConMsg("GetItemLength()") end + mItem = reaper.GetSelectedMediaItem(0, 0) mItemLen = reaper.GetMediaItemInfo_Value(mItem, "D_LENGTH") mBPM, mBPI = reaper.GetProjectTimeSignature2(0) @@ -424,12 +434,12 @@ function GetItemLength() numBarsPerItem = numQNPerItem / 4 ItemPPQN = numQNPerItem * m.ppqn if debug or m.debug then - ConMsg("ItemLen (ms) = " .. mItemLen) - ConMsg("mBPM = " .. mBPM) - ConMsg("MS Per QN = " .. msPerQN) - ConMsg("Num of QN = " .. numQNPerItem) - ConMsg("Num of Bar = " .. numBarsPerItem) - ConMsg("Item size ppqn = " .. ItemPPQN .. "\n") + --ConMsg("ItemLen (ms) = " .. mItemLen) + --ConMsg("mBPM = " .. mBPM) + --ConMsg("MS Per QN = " .. msPerQN) + ConMsg("Num of QNs = " .. numQNPerItem) + ConMsg("Num of Measures = " .. numBarsPerItem) + ConMsg("Itemlen (ppqn) = " .. ItemPPQN) end return math.floor(ItemPPQN) end @@ -439,6 +449,7 @@ end function GetReaperGrid(gridRad) local debug = false if debug or m.debug then ConMsg("GetReaperGrid()") end + if m.activeTake then m.reaGrid, __, __ = reaper.MIDI_GetGrid(m.activeTake) -- returns quarter notes if gridRad then -- if a grid object was passed, update it @@ -457,6 +468,7 @@ end function GetPermuteScaleFromTake(t) local debug = false if debug or m.debug then ConMsg("GetPermuteScaleFromTake()") end + local i, j = 1, 0 if m.activeTake then local __, num_notes, num_cc, num_sysex = reaper.MIDI_CountEvts(m.activeTake) @@ -479,13 +491,13 @@ end -------------------------------------------------------------------------------- function GetNotesFromTake() local debug = false - if debug or m.debug then ConMsg("GetNotesFromTake()") end + if debug or m.debug then ConMsg("\nGetNotesFromTake()") end + local i, t if m.activeTake then local _retval, num_notes, num_cc, num_sysex = reaper.MIDI_CountEvts(m.activeTake) if num_notes > 0 then t = GetNoteBuf(); if t == nil then t = NewNoteBuf() end - local gridSize = GetReaperGrid() local div, rem, noteLen ClearTable(t) for i = 1, num_notes do @@ -518,6 +530,7 @@ end function DeleteNotes() local debug = false if debug or m.debug then ConMsg("DeleteNotes()") end + local i, num_notes = 0, 0 if m.activeTake then __, num_notes, __, __ = reaper.MIDI_CountEvts(m.activeTake) @@ -545,6 +558,7 @@ end function GenProbTable(preProbTable, sliderTable, probTable) local debug = false if debug or m.debug then ConMsg("GenProbTable()") end + local i, j, k, l = 1, 1, 1, 1 local floor = math.floor ClearTable(probTable) @@ -565,6 +579,7 @@ end function GenAccentTable(probTable, velSlider, probSlider) local debug = false if debug or m.debug then ConMsg("GenAccentTable()") end + local i, j = 1, 1 ClearTable(probTable) -- insert normal velocity @@ -585,6 +600,7 @@ end function GenLegatoTable(probTable, probSlider) local debug = false if debug or m.debug then ConMsg("GenLegatoTable()") end + local i, j = 1, 1 ClearTable(probTable) -- no legato @@ -605,6 +621,7 @@ end function GenOctaveTable(probTable, probSlider) local debug = false if debug or m.debug then ConMsg("GenOctaveTable()") end + local i, j = 1, 1 ClearTable(probTable) -- single octave @@ -625,6 +642,7 @@ end function SetScale(scaleName, allScales, scale) local debug = false if debug or m.debug then ConMsg("SetScale()") end + ClearTable(scale) for i = 1, #allScales, 1 do if scaleName == allScales[i].name then @@ -663,6 +681,7 @@ end function UpdateSliderLabels(sliderTable, preProbTable) local debug = false if debug or m.debug then ConMsg("UpdateSliderLabels()") end + for k, v in pairs(sliderTable) do if preProbTable[k] then -- if there's a Scale note -- set the slider to the note name @@ -680,22 +699,26 @@ end function GetUniqueNote(tNotes, noteIdx, noteProbTable, octProbTable) local debug = false if debug and m.debug then ConMsg("GetUniqueNote()") end + newNote = m.root + noteProbTable[math.random(1, #noteProbTable)] if m.rndOctX2F and not m.rndPermuteF then newNote = newNote + octProbTable[math.random(1, #octProbTable)] end + if #m.dupes == 0 then -- dupe table is empty m.dupes.i = 1; m.dupes[m.dupes.i] = {} -- add note to the dupe table m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] m.dupes[m.dupes.i].midi = newNote return newNote + elseif tNotes[noteIdx][3] >= m.dupes[m.dupes.i].srtpos and tNotes[noteIdx][3] < m.dupes[m.dupes.i].endpos then -- note overlaps with previous note m.dupes.i = m.dupes.i + 1; m.dupes[m.dupes.i] = {} -- add note to dupe table m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] unique = false + while not unique do newNote = m.root + noteProbTable[math.random(1,#noteProbTable)] if m.rndOctX2F and not m.rndPermuteF then @@ -708,6 +731,7 @@ function GetUniqueNote(tNotes, noteIdx, noteProbTable, octProbTable) end -- not unique m.dupes[m.dupes.i].midi = newNote -- update dupe table return newNote + else -- note does not overlap with previous note m.dupes = {}; m.dupes.i = 1; m.dupes[m.dupes.i] = {} -- reset dupe table m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] @@ -721,12 +745,14 @@ end -------------------------------------------------------------------------------- function RandomiseNotesPoly(noteProbTable) local debug = false - if debug or m.debug then ConMsg("RandomiseNotesPoly()") end + if debug or m.debug then ConMsg("\nRandomiseNotesPoly()") end + m.dupes.i = 1 local i = 1 local t1, t2 = GetNoteBuf(), NewNoteBuf() CopyTable(t1, t2) if debug or m.debug then PrintNotes(t1) end + while t2[i] do if t2[i][1] == true or m.rndAllNotesF then -- if selected, or all notes flag is true if i == 1 and m.rndFirstNoteF then -- if selected, the first not is always root of scale @@ -737,6 +763,7 @@ function RandomiseNotesPoly(noteProbTable) end i = i + 1 end -- while t1[i] + PurgeNoteBuf() if debug or m.debug then PrintNotes(t2) end InsertNotes() @@ -750,7 +777,8 @@ end -------------------------------------------------------------------------------- function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) local debug = false - if debug or m.debug then ConMsg("GenSequence()") end + if debug or m.debug then ConMsg("\nGenSequence()") end + local t = NewNoteBuf() GetReaperGrid() -- populates m.reaGrid local itemPos = 0 @@ -759,6 +787,7 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) local noteStart, noteEnd, noteLen, noteVel, notLeg = 0, 0, 0, 0, 0 local newNote = 0 local noteCount = 0; restCount = 0 + while itemPos < itemLength do if m.seqFirstNoteF and noteCount == 0 then -- handle first note flag @@ -773,6 +802,7 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) if newNote == -1 then itemPos = itemPos + gridSize restCount = restCount + 1 + else noteStart = itemPos noteLen = newNote * m.ppqn @@ -803,6 +833,7 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) t[noteCount][9] = noteLeg -- legato end -- newNote + end -- itemPos < itemLength if debug or m.debug then PrintNotes(t) end PurgeNoteBuf() @@ -814,7 +845,8 @@ end -------------------------------------------------------------------------------- function GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) local debug = false - if debug or m.debug then ConMsg("GenBjorklund()") end + if debug or m.debug then ConMsg("\nGenBjorklund()") end + local floor = math.floor local t, t2 = NewNoteBuf(), GetNoteBuf() CopyTable(t2, t) @@ -832,12 +864,14 @@ function GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) local pattern = b.generate(pulse, step) local rot = floor(rotation.val1 + 0.5) local idx = (-rot) + 1; idx = Wrap(idx, step) + while itemPos < itemLength do if pattern[idx] then noteStart = itemPos noteLen = gridSize noteEnd = noteStart + noteLen itemPos = itemPos + noteLen + if m.eucAccentF then -- handle accent flag noteVel = accProbTable[math.random(1, #accProbTable)] else @@ -859,9 +893,11 @@ function GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) itemPos = itemPos + gridSize restCount = restCount + 1 end + idx = idx + 1 idx = Wrap(idx, step) end + PurgeNoteBuf() --if not m.eucRndNotesF then InsertNotes() end InsertNotes() @@ -871,7 +907,8 @@ end -------------------------------------------------------------------------------- function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) local debug = false - if debug or m.debug then ConMsg("GenNoteAttributes()") end + if debug or m.debug then ConMsg("\nGenNoteAttributes()") end + if not accF and not legF then return end local t1, t2 = GetNoteBuf(), NewNoteBuf() local gridSize = GetReaperGrid() @@ -879,6 +916,7 @@ function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) local div, rem, noteLen CopyTable(t1, t2) if debug and m.debug then PrintNotes(t2) end + for k, v in pairs(t2) do if v[1] then -- selected if accF then -- handle accent flag (8 = velocity) @@ -890,8 +928,8 @@ function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) end -- legF end -- legF ~= 1 end -- selected - end -- for k, v t2 + if debug and m.debug then PrintNotes(t2) end PurgeNoteBuf() InsertNotes() @@ -901,162 +939,137 @@ end -------------------------------------------------------------------------------- function InsertNotes() local debug = false - if debug or m.debug then ConMsg("\nInsertNotes()") end + if debug or m.debug then ConMsg("InsertNotes()") end + local i = 1 if m.activeTake then local gridSize = math.floor(m.reaGrid * m.ppqn) local itemLenP = GetItemLength() local noteShift = math.floor(m.seqShift * gridSize) local t1 = GetNoteBuf() - if debug then PrintNotes(t1) end -- note shifter - if debug then ConMsg("Shifting...") end + if debug or m.debug then ConMsg("Shifting...") end local t2 = {} -- temp table for note shifter (no undo) - if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end - if debug or m.debug then ConMsg("gridSize = " .. tostring(gridSize)) end - if debug or m.debug then ConMsg("noteShift = " .. tostring(noteShift)) end CopyTable(t1, t2) for k, v in pairs(t2) do - if debug or m.debug then ConMsg("idx =\t" .. tostring(k)) end - if debug or m.debug then ConMsg("orig start =\t" .. tostring(v[3]) .. " - orig end =\t" .. tostring(v[4])) end v[3] = v[3] + noteShift v[4] = v[4] + noteShift - if debug or m.debug then ConMsg("shift start =\t" .. tostring(v[3]) .. " - shift end =\t" .. tostring(v[4])) end if v[3] < 0 then v[3] = itemLenP + v[3] v[4] = itemLenP + v[4] if v[4] > itemLenP then v[4] = itemLenP end - if debug or m.debug then ConMsg("neg start =\t" .. tostring(v[3]) .. " - neg end =\t" .. tostring(v[4])) end elseif v[3] >= itemLenP then v[3] = v[3] - itemLenP v[4] = v[4] - itemLenP - if debug or m.debug then ConMsg("pos start =\t" .. tostring(v[3]) .. " - poa end =\t" .. tostring(v[4])) end end end -- for k, v t2 -- note repeater if m.seqRepeatF then - if debug then ConMsg("Repeating...") end + if debug or m.debug then ConMsg("Repeating...") end DeleteNotes() - t3 = {} -- temp table for note repeater (no undo) + t3 = {} -- temp table for note repeater (for glueing) local loopStartP = (m.loopStartG -1) * gridSize local loopLenP = m.loopLenG * gridSize local loopEndP = loopStartP + loopLenP local loopNum = m.loopNum - local noteEnd - local kOff = 0 + local i = 1 local writeOffP = 0 if loopStartP > 0 then writeOffP = -loopStartP else writeOffP = 0 end - - if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end - if debug or m.debug then ConMsg("loopStartP = " .. tostring(loopStartP)) end - if debug or m.debug then ConMsg("loopLenP = " .. tostring(loopLenP)) end - if debug or m.debug then ConMsg("loopEndP = " .. tostring(loopEndP)) end - if debug or m.debug then ConMsg("loopNum = " .. tostring(loopNum)) end - if debug or m.debug then ConMsg("writeOffP = " .. tostring(writeOffP)) end - - -- pre-repeat start - if debug or m.debug then ConMsg("\nStart pre-repeat...") end + + -- pre-repeat for k, v in pairs(t2) do if v[3] >= 0 and v[3] < loopStartP then - t3[k] = {} - t3[k][1] = v[1] -- selected - t3[k][2] = v[2] -- muted - t3[k][3] = v[3] -- startppqn - t3[k][4] = v[4] -- endppqn - if not t3[k][9] then t3[k][4] = t3[k][4] - m.legato end -- handle the legatolessness - t3[k][6] = v[6] -- channel - t3[k][7] = v[7] -- pitch - t3[k][8] = v[8] -- vel - if debug or m.debug then ConMsg("a - idx = " .. tostring(k) .. " - Start = " .. tostring(v[3]) .. " - End = " .. tostring(v[4])) end - if debug or m.debug then ConMsg("b - idx = " .. tostring(k) .. " - Start = " .. tostring(t3[k][3]) .. " - End = " .. tostring(t3[k][4])) end - reaper.MIDI_InsertNote(m.activeTake, t3[k][1], t3[k][2], t3[k][3], t3[k][4], t3[k][6], t3[k][7], t3[k][8], false) - kOff = kOff + 1 - --if debug or m.debug then ConMsg("kOff = " .. tostring(kOff)) end + t3[i] = {} + t3[i][1] = v[1] -- selected + t3[i][2] = v[2] -- muted + t3[i][3] = v[3] -- startppqn + t3[i][4] = v[4] -- endppqn + if not t3[i][9] then t3[i][4] = t3[i][4] - m.legato end -- handle legatolessness + t3[i][5] = v[5] -- length + t3[i][6] = v[6] -- channel + t3[i][7] = v[7] -- pitch + t3[i][8] = v[8] -- vel + t3[i][9] = v[9] -- legato + reaper.MIDI_InsertNote(m.activeTake, t3[i][1], t3[i][2], t3[i][3], t3[i][4], t3[i][6], t3[i][7], t3[i][8], false) + i = i + 1 end end -- k, v in pairs(t2) - pre-repeat writeOffP = writeOffP + loopStartP - -- repeat start - if debug or m.debug then ConMsg("\nStart repeater...") end + -- repeat while loopNum > 0 do - if debug or m.debug then ConMsg("\nloopNum = " .. tostring(loopNum)) end - if debug or m.debug then ConMsg("writeOffP = " .. tostring(writeOffP)) end for k, v in pairs(t2) do if v[3] >= loopStartP and v[3] < loopEndP then - t3[k + kOff] = {} - t3[k + kOff][1] = v[1] -- selected - t3[k + kOff][2] = v[2] -- muted - t3[k + kOff][3] = v[3] + writeOffP -- startppqn - if v[4] > loopEndP then -- endppqn - t3[k + kOff][4] = loopEndP + writeOffP - else - t3[k + kOff][4] = v[4] + writeOffP - end - if not t3[k + kOff][9] then t3[k + kOff][4] = t3[k + kOff][4] - m.legato end -- handle the legatolessness - t3[k + kOff][6] = v[6] -- channel - t3[k + kOff][7] = v[7] -- pitch - t3[k + kOff][8] = v[8] -- vel - if debug or m.debug then ConMsg("a - idx = " .. tostring(k) .. " - Start = " .. tostring(v[3]) .. " - End = " .. tostring(v[4])) end - if debug or m.debug then ConMsg("b - idx = " .. tostring(k + kOff) .. " - Start = " .. tostring(t3[k + kOff][3]) .. " - End = " .. tostring(t3[k + kOff][4])) end - reaper.MIDI_InsertNote(m.activeTake, t3[k + kOff][1], t3[k + kOff][2], t3[k + kOff][3], t3[k + kOff][4], t3[k + kOff][6], t3[k + kOff][7], t3[k + kOff][8], false) - + t3[i] = {} + t3[i][1] = v[1] -- selected + t3[i][2] = v[2] -- muted + t3[i][3] = v[3] + writeOffP -- startppqn + if v[4] > loopEndP then t3[i][4] = loopEndP + writeOffP else t3[i][4] = v[4] + writeOffP end -- endppqn + if not t3[i][9] then t3[i][4] = t3[i][4] - m.legato end -- handle legatolessness + t3[i][5] = v[5] -- length + t3[i][6] = v[6] -- channel + t3[i][7] = v[7] -- pitch + t3[i][8] = v[8] -- vel + t3[i][9] = v[9] -- legato + reaper.MIDI_InsertNote(m.activeTake, t3[i][1], t3[i][2], t3[i][3], t3[i][4], t3[i][6], t3[i][7], t3[i][8], false) + i = i + 1 end -- if v[3] + end -- for k, v t3 - repeat loopNum = loopNum - 1 writeOffP = writeOffP + loopLenP end -- while loopNum > 0 - -- post-repeat start - if debug or m.debug then ConMsg("\nStart post-repeat...") end - if debug or m.debug then ConMsg("writeOffP = " .. tostring(writeOffP)) end - - kOff = kOff + 1 - local written = loopStartP + (loopLenP * m.loopNum) - if debug or m.debug then ConMsg("written = " .. tostring(written)) end - local remLenP = itemLenP - written - if debug or m.debug then ConMsg("remLenP = " .. tostring(remLenP)) end + -- post-repeat + local written = loopStartP + (loopLenP * m.loopNum) + local remLenP = itemLenP - written local readStartP = loopStartP + loopLenP - if debug or m.debug then ConMsg("readStartP = " .. tostring(readStartP)) end local readEndP = readStartP + remLenP - if debug or m.debug then ConMsg("readEndP = " .. tostring(readEndP)) end local writeOffP = written - readStartP - if debug or m.debug then ConMsg("writeOffP = " .. tostring(writeOffP)) end for k, v in pairs(t2) do if v[3] >= readStartP and v[3] < readEndP then - t3[k + kOff] = {} - t3[k + kOff][1] = v[1] -- selected - t3[k + kOff][2] = v[2] -- muted - t3[k + kOff][3] = v[3] + writeOffP -- startppqn - if v[4] > itemLenP then -- endppqn - t3[k + kOff][4] = itemLenP - else - t3[k + kOff][4] = v[4] + writeOffP - end - if not t3[k + kOff][9] then t3[k + kOff][4] = t3[k + kOff][4] - m.legato end -- handle the legatolessness - t3[k + kOff][6] = v[6] -- channel - t3[k + kOff][7] = v[7] -- pitch - t3[k + kOff][8] = v[8] -- vel - if debug or m.debug then ConMsg("a - idx = " .. tostring(k) .. " - Start = " .. tostring(v[3]) .. " - End = " .. tostring(v[4])) end - if debug or m.debug then ConMsg("b - idx = " .. tostring(k + kOff) .. " - Start = " .. tostring(t3[k + kOff][3]) .. " - End = " .. tostring(t3[k + kOff][4])) end - reaper.MIDI_InsertNote(m.activeTake, t3[k + kOff][1], t3[k + kOff][2], t3[k + kOff][3], t3[k + kOff][4], t3[k + kOff][6], t3[k + kOff][7], t3[k + kOff][8], false) - kOff = kOff + 1 - if debug or m.debug then ConMsg("kOff = " .. tostring(kOff)) end + t3[i] = {} + t3[i][1] = v[1] -- selected + t3[i][2] = v[2] -- muted + t3[i][3] = v[3] + writeOffP -- startppqn + if v[4] > itemLenP then t3[i][4] = itemLenP else t3[i][4] = v[4] + writeOffP end -- endppqn + if not t3[i][9] then t3[i][4] = t3[i][4] - m.legato end -- handle legatolessness + t3[i][5] = v[5] -- channel + t3[i][6] = v[6] -- channel + t3[i][7] = v[7] -- pitch + t3[i][8] = v[8] -- vel + t3[i][9] = v[9] -- legato + reaper.MIDI_InsertNote(m.activeTake, t3[i][1], t3[i][2], t3[i][3], t3[i][4], t3[i][6], t3[i][7], t3[i][8], false) + i = i + 1 end end -- k, v in pairs(t2) - post-repeat reaper.MIDI_Sort(m.activeTake) reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off + else -- not m.seqRepeatF + if debug or m.debug then ConMsg("No repeat...") end DeleteNotes() - for k, v in pairs(t2) do - if not v[9] then v[4] = v[4] - m.legato end-- handle the legatolessness - reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) - --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) - end -- for k, v t2 + if m.loopGlueF then + if debug or m.debug then ConMsg("Glueing...") end + t4 = NewNoteBuf(); CopyTable(t3, t4) + if debug or m.debug then PrintNotes(t4) end + for k, v in pairs(t4) do + reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) + end + m.loopGlueF = false + + else -- not glueing + if debug or m.debug then ConMsg("no glueing, inserting shift table (t2)") end + for k, v in pairs(t2) do -- use the post-shifter table + if not v[9] then v[4] = v[4] - m.legato end -- handle legatolessness + reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) + end -- for k, v t2 + end -- m.loopGlueF reaper.MIDI_Sort(m.activeTake) reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off @@ -1066,73 +1079,16 @@ function InsertNotes() end -- m.activeTake end -------------------------------------------------------------------------------- --- InsertNotesWithShift(note_buffer) - insert notes in the active take --------------------------------------------------------------------------------- -function InsertNotesWithShift() - local debug = false - if debug or m.debug then ConMsg("\nInsertNotes()") end - DeleteNotes() - local i = 1 - if m.activeTake then - local gridSize = m.reaGrid * m.ppqn - local itemLength = GetItemLength() - local noteShift = m.seqShift * gridSize - local t1 = GetNoteBuf() - local t2 = {} -- for note shifting - CopyTable(t1, t2) - for k, v in pairs(t2) do -- do note shifting - v[3] = v[3] + noteShift - v[4] = v[4] + noteShift - if v[3] < 0 then - v[3] = itemLength + v[3] - v[4] = itemLength + v[4] - if v[4] > itemLength then v[4] = itemLength + m.legato end - elseif v[3] >= itemLength then - v[3] = v[3] - itemLength - v[4] = v[4] - itemLength - end - end - while t2[i] do - reaper.MIDI_InsertNote(m.activeTake, t2[i][1], t2[i][2], t2[i][3], t2[i][4], t2[i][6], t2[i][7], t2[i][8], false) - --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) - i = i + 1 - end -- while t2[i] - reaper.MIDI_Sort(m.activeTake) - reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off - else - if debug or m.debug then ConMsg("No Active Take") end - end -- m.activeTake -end --------------------------------------------------------------------------------- --- InsertNotesOrig(note_buffer) - insert notes in the active take --------------------------------------------------------------------------------- -function InsertNotesOrig() - local debug = false - if debug or m.debug then ConMsg("InsertNotes()") end - DeleteNotes() - local i = 1 - if m.activeTake then - local t1 = GetNoteBuf() - while t1[i] do - reaper.MIDI_InsertNote(m.activeTake, t1[i][1], t1[i][2], t1[i][3], t1[i][4], t1[i][6], t1[i][7], t1[i][8], false) - --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) - i = i + 1 - end -- while t1[i] - reaper.MIDI_Sort(m.activeTake) - reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off - else - if debug or m.debug then ConMsg("No Active Take") end - end -- m.activeTake -end --------------------------------------------------------------------------------- -- PrintNotes - arg note_buffer t; print note_buffer to reaper console -------------------------------------------------------------------------------- function PrintNotes(t) -- debug code local debug = false if debug or m.debug then ConMsg("PrintNotes()") end + if not t then return end local i = 1 local str = "sel \t mut \t s_ppq \t e_ppq \t leng \t chan \t pitch \t vel \t leg \n" + while t[i] do j = 1 while (t[i][j] ~= nil) do @@ -1142,6 +1098,7 @@ function PrintNotes(t) -- debug code str = str .. "\n" i = i + 1 end -- while t[i] + str = str .. "\n" if debug or m.debug then ConMsg(str) end end @@ -1151,11 +1108,14 @@ end function PrintTable(t) -- debug code local debug = false if debug or m.debug then ConMsg("PrintTable()") end + if not t then return end local str = "" + for k, v in pairs(t) do str = str .. tostring(v) .. "\t" end + str = str .. "\n" if debug or m.debug then ConMsg(str) end end @@ -1165,6 +1125,7 @@ end function ShowMessage(tb, msgNum) local debug = false if debug and m.debug then ConMsg("ShowMessage() ") end + if msgNum == 0 then tb.tab = (1 << 9) tb.label = "" @@ -1331,7 +1292,8 @@ local t_Textboxes = {probSldrText, octProbText, seqGridText, seqSldrText, seqShi -- Window zoom droplist zoomDrop.onLClick = function() -- window scaling local debug = false - if debug or m.debug then ConMsg("\nzoomDrop.onLClick()") end + if debug or m.debug then ConMsg("zoomDrop.onLClick()") end + if zoomDrop.val1 == 1 then e.gScale = 0.7 elseif zoomDrop.val1 == 2 then e.gScale = 0.8 elseif zoomDrop.val1 == 3 then e.gScale = 0.9 @@ -1343,6 +1305,7 @@ zoomDrop.onLClick = function() -- window scaling elseif zoomDrop.val1 == 9 then e.gScale = 1.8 elseif zoomDrop.val1 == 10 then e.gScale = 2.0 end + if debug or m.debug then ConMsg("zoom = " .. tostring(e.gScale)) end -- Save state, close and reopen GFX window if not pExtState.win_x then @@ -1357,7 +1320,8 @@ end -- Layer 1 button layerBtn01.onLClick = function() -- randomiser local debug = false - if debug or m.debug then ConMsg("\nlayerBtn01.onLClick() (note randomiser)") end + if debug or m.debug then ConMsg("layerBtn01.onLClick() (note randomiser)") end + e.gActiveLayer = 1 zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_green) winText.r, winText.g, winText.b, winText.a = table.unpack(e.col_green) @@ -1377,7 +1341,8 @@ end -- Layer 2 button layerBtn02.onLClick = function() -- sequencer local debug = false - if debug or m.debug then ConMsg("\nlayerBtn02.onLClick() (sequencer)") end + if debug or m.debug then ConMsg("layerBtn02.onLClick() (sequencer)") end + e.gActiveLayer = 2 zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_yellow) winText.r, winText.g, winText.b, winText.a = table.unpack(e.col_yellow) @@ -1397,7 +1362,8 @@ end -- Layer 3 button layerBtn03.onLClick = function() -- euclidean local debug = false - if debug or m.debug then ConMsg("\nlayerBtn03.onLClick() (euclid)") end + if debug or m.debug then ConMsg("layerBtn03.onLClick() (euclid)") end + e.gActiveLayer = 3 zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_orange) winText.r, winText.g, winText.b, winText.a = table.unpack(e.col_orange) @@ -1417,7 +1383,8 @@ end -- Layer 4 button layerBtn04.onLClick = function() -- options local debug = false - if debug or m.debug then ConMsg("\nlayerBtn04.onLClick() (options)") end + if debug or m.debug then ConMsg("layerBtn04.onLClick() (options)") end + e.gActiveLayer = 4 zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_grey5) winText.r, winText.g, winText.b, winText.a = table.unpack(e.col_grey5) @@ -1437,7 +1404,8 @@ end -- Undo button undoBtn.onLClick = function() -- undo local debug = false - if debug or m.debug then ConMsg("\nundoBtn.onLClick()") end + if debug or m.debug then ConMsg("undoBtn.onLClick()") end + UndoNoteBuf() InsertNotes() PrintNotes(m.notebuf[m.notebuf.i]) @@ -1445,7 +1413,8 @@ end -- Redo button redoBtn.onLClick = function() -- redo local debug = false - if debug or m.debug then ConMsg("\nredoBtn.onLClick()") end + if debug or m.debug then ConMsg("redoBtn.onLClick()") end + if m.notebuf[m.notebuf.i + 1] ~= nil then --PrintNotes(m.notebuf[m.notebuf.i + 1]) m.notebuf.i = m.notebuf.i + 1 @@ -1459,6 +1428,7 @@ end function SetDefaultWindowOpts() local debug = false if debug or m.debug then ConMsg("SetDefaultWinOpts()") end + if pExtState.zoomDrop then zoomDrop.val1 = pExtState.zoomDrop end @@ -1470,6 +1440,9 @@ function SetDefaultWindowOpts() end -- Set default layer function SetDefaultLayer() + local debug = false + if debug or m.debug then ConMsg("SetDefaultLayer()") end + if pExtState.activeLayer then if pExtState.activeLayer == 1 then layerBtn01.onLClick() elseif pExtState.activeLayer == 2 then layerBtn02.onLClick() @@ -1486,6 +1459,7 @@ end randomBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nrandomBtn.onLClick()") end + if m.activeTake then m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift seqShiftVal.label = tostring(m.seqShift) @@ -1496,9 +1470,11 @@ randomBtn.onLClick = function() RandomiseNotesPoly(m.noteProbTable) -- set project ext state pExtState.noteSliders = {} + for k, v in pairs(t_noteSliders) do pExtState.noteSliders[k] = v.val1 end + pExtState.rndOctProb = octProbSldr.val1 pExtSaveStateF = true end --m.activeTake @@ -1506,7 +1482,8 @@ end -- Randomiser options toggle logic noteOptionsCb.onLClick = function() local debug = false - if debug or m.debug then ConMsg("\nnoteOptionsCb.onLClick()") end + if debug or m.debug then ConMsg("noteOptionsCb.onLClick()") end + m.rndAllNotesF = noteOptionsCb.val1[1] == 1 and true or false -- All / Sel Notes m.rndFirstNoteF = noteOptionsCb.val1[2] == 1 and true or false -- 1st Note Root m.rndOctX2F = noteOptionsCb.val1[3] == 1 and true or false -- Octave X2 @@ -1517,7 +1494,8 @@ end -- Root Key droplist keyDrop.onLClick = function() local debug = false - if debug or m.debug then ConMsg("\nkeyDrop.onLClick()") end + if debug or m.debug then ConMsg("keyDrop.onLClick()") end + m.key = keyDrop.val1 m.root = SetRootNote(m.oct, m.key) UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) @@ -1529,7 +1507,8 @@ end -- Octave droplist octDrop.onLClick = function() local debug = false - if debug or m.debug then ConMsg("\noctDrop.onLClick()") end + if debug or m.debug then ConMsg("octDrop.onLClick()") end + m.oct = octDrop.val1 m.root = SetRootNote(m.oct, m.key) -- set project ext state @@ -1540,7 +1519,7 @@ end -- Scale droplist scaleDrop.onLClick = function() local debug = false - if debug or m.debug then ConMsg("\nscaleDrop.onLClick()") end + if debug or m.debug then ConMsg("scaleDrop.onLClick()") end SetScale(scaleDrop.val2[scaleDrop.val1], m.scales, m.preNoteProbTable) if m.rndPermuteF then noteOptionsCb.val1[1] = 0 @@ -1556,6 +1535,7 @@ end function SetDefaultScaleOpts() local debug = false if debug or m.debug then ConMsg("SetDefaultScaleOpts()") end + -- if key saved in project state, load it if pExtState.key then m.key = math.floor(tonumber(pExtState.key)) @@ -1588,12 +1568,14 @@ end function SetDefaultRndOptions() local debug = false if debug or m.debug then ConMsg("SetDefaultRndOptions()") end + -- if randomiser options were saved to project state, load them if pExtState.noteOptionsCb then m.rndAllNotesF = pExtState.noteOptionsCb[1] == true and true or false m.rndFirstNoteF = pExtState.noteOptionsCb[2] == true and true or false m.rndOctX2F = pExtState.noteOptionsCb[3] == true and true or false end + -- set randomiser options using defaults, or loaded project state noteOptionsCb.val1[1] = (true and m.rndAllNotesF) and 1 or 0 -- all notes noteOptionsCb.val1[2] = (true and m.rndFirstNoteF) and 1 or 0 -- first note root @@ -1603,6 +1585,7 @@ end function SetDefaultRndSliders() local debug = false if debug or m.debug then ConMsg("SetDefaultRndSliders()") end + -- if randomiser sliders were saved to project state, load them if pExtState.noteSliders then for k, v in pairs(t_noteSliders) do @@ -1622,8 +1605,12 @@ end -- Reset note probability sliders probSldrText.onRClick = function() + local debug = false + if debug or m.debug then ConMsg("probSldrText.onRClick()") end + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Note Sliders") + if result == 1 then for k, v in pairs(t_noteSliders) do -- reset the sliders if v.label ~= "" then v.val1 = 1 end @@ -1638,8 +1625,12 @@ probSldrText.onRClick = function() end -- Reset octave probability slider octProbText.onRClick = function() + local debug = false + if debug or m.debug then ConMsg("octProbText.onRClick()") end + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Octave Slider") + if result == 1 then octProbSldr.val1 = m.rndOctProb if pExtState.rndOctProb then -- write the new proj ext state @@ -1656,11 +1647,13 @@ end sequenceBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nsequenceBtn.onLClick()") end + if m.activeTake then m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn off repeat InsertNotes() m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence seqShiftVal.label = tostring(m.seqShift) + if m.seqF then SetSeqGridSizes(t_seqSliders) GenProbTable(m.preSeqProbTable, t_seqSliders, m.seqProbTable) @@ -1671,15 +1664,18 @@ sequenceBtn.onLClick = function() if m.seqRndNotesF then randomBtn.onLClick() -- call RandomiseNotes end + else -- not m.seqF GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) GenLegatoTable(m.legProbTable, seqLegProbSldr) GetNotesFromTake() GenNoteAttributes(m.seqAccentF, m.accProbTable, seqAccRSldr, m.seqLegatoF, m.legProbTable) + if m.seqRndNotesF then randomBtn.onLClick() -- call RandomiseNotes end end -- m.seqF + -- set project ext state if seqGridRad.val1 == 1 then -- 1/16 grid pExtState.seqGrid16 = {} @@ -1687,18 +1683,21 @@ sequenceBtn.onLClick = function() pExtState.seqGrid16[k] = v.val1 end end + if seqGridRad.val1 == 2 then -- 1/8 grid pExtState.seqGrid8 = {} for k, v in pairs (t_seqSliders) do pExtState.seqGrid8[k] = v.val1 end - end + end + if seqGridRad.val1 == 3 then -- 1/4 grid pExtState.seqGrid4 = {} for k, v in pairs (t_seqSliders) do pExtState.seqGrid4[k] = v.val1 end - end + end + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn on repeat InsertNotes() pExtState.seqAccRSldrLo = seqAccRSldr.val1 @@ -1713,16 +1712,19 @@ end -- Sequencer options toggle logic seqOptionsCb.onLClick = function() local debug = false - if debug or m.debug then ConMsg("\nseqOptionsCb.onLClick()") end + if debug or m.debug then ConMsg("seqOptionsCb.onLClick()") end + m.seqF = seqOptionsCb.val1[1] == 1 and true or false -- Generate m.seqFirstNoteF = seqOptionsCb.val1[2] == 1 and true or false -- 1st Note Always m.seqAccentF = seqOptionsCb.val1[3] == 1 and true or false -- Accent m.seqLegatoF = seqOptionsCb.val1[4] == 1 and true or false -- Legato m.seqRndNotesF = seqOptionsCb.val1[5] == 1 and true or false -- Randomise Notes m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Repeat + if pExtState.seqOptionsCb then if pExtState.seqOptionsCb[6] ~= m.seqRepeatF then InsertNotes() end end + pExtState.seqOptionsCb = {m.seqF, m.seqFirstNoteF, m.seqAccentF, m.seqLegatoF, m.seqRndNotesF, m.seqRepeatF} pExtSaveStateF = true if debug or m.debug then PrintTable(seqOptionsCb.val1) end @@ -1731,7 +1733,8 @@ end -- Sequencer grid radio button seqGridRad.onLClick = function() -- change grid size local debug = false - if debug or m.debug then ConMsg("\nseqGridRad.onLClick()") end + if debug or m.debug then ConMsg("seqGridRad.onLClick()") end + if m.activeTake then if seqGridRad.val1 == 1 then -- 1/16 grid @@ -1776,7 +1779,6 @@ seqGridRad.onLClick = function() -- change grid size seqShiftVal.label = tostring(m.seqShift) GetNotesFromTake() -- force an undo point on grid change --InsertNotes() - pExtSaveStateF = true end -- m.activeTake @@ -1784,27 +1786,37 @@ end -- Sequencer shift left seqShiftLBtn.onLClick = function() + local debug = false + if debug or m.debug then ConMsg("seqShiftLBtn()") end + local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() m.seqShiftMin = -(math.floor(itemLength / gridSize)-1) + if m.seqShift <= m.seqShiftMin then m.seqShift = 0 else m.seqShift = m.seqShift - 1 end + seqShiftVal.label = tostring(m.seqShift) InsertNotes() end -- Sequencer shift right seqShiftRBtn.onLClick = function() + local debug = false + if debug or m.debug then ConMsg("seqShiftRBtn()") end + local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() m.seqShiftMax = math.floor(itemLength / gridSize) - 1 + if m.seqShift >= m.seqShiftMax then m.seqShift = 0 else m.seqShift = m.seqShift + 1 end + seqShiftVal.label = tostring(m.seqShift) InsertNotes() end @@ -1812,7 +1824,7 @@ end -- Sequencer repeat start seqLoopStartDrop.onLClick = function() local debug = false - if debug or m.debug then ConMsg("\nseqLoopStartDrop.onLClick()") end + if debug or m.debug then ConMsg("seqLoopStartDrop.onLClick()") end GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) local gridSizeP = m.reaGrid * m.ppqn @@ -1864,7 +1876,7 @@ end -- Sequencer repeat length seqLoopLenDrop.onLClick = function() local debug = false - if debug or m.debug then ConMsg("\nseqLoopLenDrop.onLClick()") end + if debug or m.debug then ConMsg("seqLoopLenDrop.onLClick()") end GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) local gridSizeP = m.reaGrid * m.ppqn @@ -1909,7 +1921,7 @@ end -- Sequencer repeat amount seqLoopNumDrop.onLClick = function() local debug = false - if debug or m.debug then ConMsg("\nseqLoopNumDrop.onLClick()") end + if debug or m.debug then ConMsg("seqLoopNumDrop.onLClick()") end GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) local gridSizeP = m.reaGrid * m.ppqn @@ -1971,6 +1983,7 @@ end function SetDefaultAccLegSliders() local debug = false if debug or m.debug then ConMsg("SetDefaultAccLegSliders()") end + -- if seq accent & legato sliders were saved to project state, load them if pExtState.seqAccRSldrLo then seqAccRSldr.val1 = pExtState.seqAccRSldrLo @@ -1992,11 +2005,11 @@ function SetDefaultAccLegSliders() else seqLegProbSldr.val1 = m.legatoProb end -end +end -- function -- Set default grid sliders function SetDefaultSeqGridSliders() local debug = false - if debug or m.debug then ConMsg("\nSetDefaultSeqGridSliders()") end + if debug or m.debug then ConMsg("SetDefaultSeqGridSliders()") end GetReaperGrid(seqGridRad) SetSeqGridSizes(t_seqSliders) @@ -2046,6 +2059,7 @@ end function SetDefaultSeqShift() local debug = false if debug or m.debug then ConMsg("SetDefaultSeqShift()") end + m.seqShift = 0 m.seqShiftMin = 0 m.seqShiftMax = 0 @@ -2053,15 +2067,39 @@ function SetDefaultSeqShift() end -- Set default sequencer repeat state function SetDefaultSeqRepeat() + local debug = false + if debug or m.debug then ConMsg("SetDefaultSeqRepeat()") end + GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() - - m.loopStartG = 1; m.loopLenG = 1; m.loopNum = 1 - seqLoopStartDrop.val1 = m.loopStartG - seqLoopNumDrop.val1 = m.loopNum - seqLoopLenDrop.val1 = m.loopLenG + -- start + if pExtState.loopStartG then + m.loopStartG = pExtState.loopStartG + seqLoopStartDrop.val1 = m.loopStartG + else + m.loopStartG = 1 + seqLoopStartDrop.val1 = m.loopStartG + end + + -- length + if pExtState.loopLenG then + m.loopLenG = pExtState.loopLenG + seqLoopLenDrop.val1 = m.loopLenG + else + m.loopLenG = 1 + seqLoopLenDrop.val1 = m.loopLenG + end + + -- amount + if pExtState.loopNum then + m.loopNum = pExtState.loopNum + seqLoopNumDrop.val1 = m.loopNum + else + m.loopNum = 1 + seqLoopNumDrop.val1 = m.loopNum + end m.loopMaxRep = math.floor(itemLength / gridSize) @@ -2070,17 +2108,13 @@ function SetDefaultSeqRepeat() seqLoopNumDrop.val2[i] = i seqLoopLenDrop.val2[i] = i end - --[[ -m.repNum, m.repLenGrid, m.repMax, m.repLenPPQN -seqLoopLenDrop, m.t_loopLen) -seqLoopNumDrop, m.t_loopNum) ---]] end --- Reset sequencer grid sliders +-- Reset sequencer sections seqSldrText.onRClick = function() local debug = false - if debug or m.debug then ConMsg("\nseqSldrText.onLClick()") end + if debug or m.debug then ConMsg("seqSldrText.onLClick()") end + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Sequence Sliders") if result == 1 then @@ -2109,9 +2143,11 @@ end -- Reset sequencer velocity slider seqAccSldrText.onRClick = function() local debug = false - if debug or m.debug then ConMsg("\nseqAccSldrText.onLClick()") end + if debug or m.debug then ConMsg("seqAccSldrText.onRClick()") end + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Accent Sliders") + if result == 1 then seqAccRSldr.val1 = m.accentLow if pExtState.seqAccRSldrLo then pExtState.seqAccRSldrLo = nil end @@ -2119,15 +2155,17 @@ seqAccSldrText.onRClick = function() if pExtState.seqAccRSldrHi then pExtState.seqAccRSldrHi = nil end seqAccProbSldr.val1 = m.accentProb if pExtState.seqAccProb then pExtState.seqAccProb = nil end - pExtSaveStateF = true -- set the ext state save flag + pExtSaveStateF = true -- set the ext state save flag end -- result end -- Reset sequencer legato slider seqLegSldrText.onRClick = function() local debug = false - if debug or m.debug then ConMsg("\nseqLegSldrText.onLClick()") end + if debug or m.debug then ConMsg("seqLegSldrText.onLClick()") end + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Legato Slider") + if result == 1 then seqLegProbSldr.val1 = m.legatoProb if pExtState.seqLegProb then pExtState.seqLegProb = nil end @@ -2137,16 +2175,58 @@ end -- Reset sequencer shift seqShiftText.onRClick = function() local debug = false - if debug or m.debug then ConMsg("\nseqShiftText.onRClick") end + if debug or m.debug then ConMsg("seqShiftText.onRClick") end + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Note Shift") + if result == 1 then m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) InsertNotes() end -- result end +-- Reset sequencer repeat +seqLoopText.onRClick = function() + local debug = false + if debug or m.debug then ConMsg("seqLoopText.onRClick") end + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Repeat|Glue Repeat") + if result == 1 then + -- reset the GUI and repeat flag + m.seqRepeatF = false + seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 + seqOptionsCb.onLClick() + -- reset the drop down lists and clear pExtState + seqLoopStartDrop.val1 = 1; m.loopStartG = 1 + if pExtState.loopStartG then pExtState.loopStartG = nil end + seqLoopLenDrop.val1 = 1; m.loopLenG = 1 + if pExtState.loopLenG then pExtState.loopLenG = nil end + seqLoopNumDrop.val1 = 1; m.loopNum = 1 + if pExtState.loopNum then pExtState.loopNum = nil end + pExtSaveStateF = true -- set the ext state save flag + InsertNotes() + + elseif result == 2 then + m.loopGlueF = true + InsertNotes() + -- reset the GUI and repeat flag + m.seqRepeatF = false + seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 + seqOptionsCb.onLClick() + -- reset the drop down lists and pExtState + seqLoopStartDrop.val1 = 1; m.loopStartG = 1 + if pExtState.loopStartG then pExtState.loopStartG = nil end + seqLoopLenDrop.val1 = 1; m.loopLenG = 1 + if pExtState.loopLenG then pExtState.loopLenG = nil end + seqLoopNumDrop.val1 = 1; m.loopNum = 1 + if pExtState.loopNum then pExtState.loopNum = nil end + pExtSaveStateF = true -- set the ext state save flag + end -- result + +end -- onRClick -------------------------------------------------------------------------------- -- Euclidiser @@ -2155,6 +2235,7 @@ end euclidBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\neuclidBtn.onLClick()") end + if m.activeTake then if m.eucF then if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end @@ -2164,6 +2245,7 @@ euclidBtn.onLClick = function() if m.eucRndNotesF then randomBtn.onLClick() -- call RandomiseNotes end + else -- not m.eucF if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) @@ -2174,6 +2256,7 @@ euclidBtn.onLClick = function() randomBtn.onLClick() -- call RandomiseNotes end end -- m.eucF + -- set project ext state pExtState.eucSliders = {} for k, v in pairs(t_euclidSliders) do @@ -2185,7 +2268,8 @@ end -- Euclidiser options eucOptionsCb.onLClick = function() local debug = false - if debug or m.debug then ConMsg("\neucOptionsCb.onLClick()") end + if debug or m.debug then ConMsg("eucOptionsCb.onLClick()") end + m.eucF = eucOptionsCb.val1[1] == 1 and true or false -- Generate m.eucAccentF = eucOptionsCb.val1[2] == 1 and true or false -- Accent m.eucRndNotesF = eucOptionsCb.val1[3] == 1 and true or false -- Randomise notes @@ -2197,6 +2281,7 @@ end euclidPulsesSldr.onMove = function() local debug = false if debug or m.debug then ConMsg("euclidPlusesSldr.onMove()") end + if euclidPulsesSldr.val1 > euclidStepsSldr.val1 then -- pulses > steps euclidStepsSldr.val1 = euclidPulsesSldr.val1 euclidRotationSldr.max = euclidStepsSldr.val1 @@ -2221,6 +2306,7 @@ end euclidRotationSldr.onMove = function() local debug = false if debug or m.debug then ConMsg("euclidRotationSldr.onMove()") end + euclidRotationSldr.max = euclidStepsSldr.val1 if euclidRotationSldr.val1 > euclidStepsSldr.val1 then euclidRotationSldr.val1 = euclidStepsSldr.val1 @@ -2232,12 +2318,14 @@ end function SetDefaultEucOptions() local debug = false if debug or m.debug then ConMsg("SetDefaultEucOptions()") end + -- if euclidean options were saved to project state, load them if pExtState.eucOptionsCb then m.eucF = pExtState.eucOptionsCb[1] == true and true or false m.eucAccentF = pExtState.eucOptionsCb[2] == true and true or false m.eucRndNotesF = pExtState.eucOptionsCb[3] == true and true or false end + -- set euclidean options using defaults, or loaded project state eucOptionsCb.val1[1] = (true and m.eucF) and 1 or 0 -- generate eucOptionsCb.val1[2] = (true and m.eucAccentF) and 1 or 0 -- accents @@ -2247,12 +2335,14 @@ end function SetDefaultEucSliders() local debug = false if debug or m.debug then ConMsg("SetDefaultEucSliders()") end + -- if euclidean sliders were saved to project state, load them if pExtState.eucSliders then for k, v in pairs(t_euclidSliders) do v.val1 = pExtState.eucSliders[k] end else + euclidPulsesSldr.val1 = m.eucPulses euclidStepsSldr.val1 = m.eucSteps euclidRotationSldr.val1 = m.eucRot @@ -2262,9 +2352,11 @@ end -- Reset euclidean sliders txtEuclidLabel.onRClick = function() local debug = false - if debug or m.debug then ConMsg("\ntxtEuclidLabel.onLClick()") end + if debug or m.debug then ConMsg("txtEuclidLabel.onLClick()") end + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Euclid Sliders") + if result == 1 then euclidPulsesSldr.val1 = m.eucPulses euclidStepsSldr.val1 = m.eucSteps @@ -2329,18 +2421,19 @@ function InitMidiExMachina() pExtState = unpickle(pExtStateStr) end -- pExtStateStr end -- pExtLoadStateF - + + -- get some item info + GetItemLength() + GetNotesFromTake() -- grab the original note data (if any...) + -- set GUI defaults or restore from project state SetDefaultWindowOpts(); SetDefaultLayer() SetDefaultScaleOpts() SetDefaultRndOptions(); SetDefaultRndSliders() - SetDefaultSeqOptions(); SetDefaultSeqShift() + SetDefaultSeqOptions(); SetDefaultSeqShift(); SetDefaultSeqRepeat() SetDefaultSeqGridSliders(); SetDefaultAccLegSliders() - SetDefaultSeqRepeat() SetDefaultEucOptions(); SetDefaultEucSliders() - GetItemLength() - GetNotesFromTake() -- grab the original note data (if any...) if debug or m.debug then ConMsg("End InitMidiExMachina()\n") end end -------------------------------------------------------------------------------- @@ -2348,7 +2441,8 @@ end -------------------------------------------------------------------------------- function InitGFX() local debug = false - if debug or m.debug then ConMsg("InitGFX()") end + if debug or m.debug then ConMsg("\nInitGFX()") end + -- Init window ------ gfx.clear = RGB2Packed(table.unpack(m.win_bg)) gfx.init(m.win_title, m.win_w * e.gScale, m.win_h * e.gScale, m.win_dockstate, m.win_x, m.win_y) From 5b2525a365d823a8d5698aedff1e3b9b1a667346 Mon Sep 17 00:00:00 2001 From: RobU Date: Wed, 24 May 2017 08:13:00 +0100 Subject: [PATCH 09/33] code tidy added preliminary take-switching code --- .../RobU - MIDI Ex Machina.lua | 576 +++++++++--------- 1 file changed, 293 insertions(+), 283 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index ccaf6c1..0af2d1d 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -89,6 +89,7 @@ m.oct = 4; m.key = 1; m.root = 0 -- (options, except m.root) -- midi editor, take, grid m.activeEditor, m.activeTake = nil, nil +m.currTakeID, m.lastTakeID = "", "" m.ppqn = 960; -- default ppqn, no idea how to check if this has been changed.. m.reaGrid = 0 @@ -1698,7 +1699,7 @@ sequenceBtn.onLClick = function() end end - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn on repeat + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn on repeat InsertNotes() pExtState.seqAccRSldrLo = seqAccRSldr.val1 pExtState.seqAccRSldrHi = seqAccRSldr.val2 @@ -1709,17 +1710,40 @@ sequenceBtn.onLClick = function() end --m.activeTake end +-- Set sequencer options defaults +function SetDefaultSeqOptions() + local debug = false + if debug or m.debug then ConMsg("SetDefaultSeqOptions()") end + + -- if sequencer options were saved to project state, load them + if pExtState.seqOptionsCb then + m.seqF = pExtState.seqOptionsCb[1] == true and true or false + m.seqFirstNoteF = pExtState.seqOptionsCb[2] == true and true or false + m.seqAccentF = pExtState.seqOptionsCb[3] == true and true or false + m.seqLegatoF = pExtState.seqOptionsCb[4] == true and true or false + m.seqRndNotesF = pExtState.seqOptionsCb[5] == true and true or false + m.seqRepeatF = pExtState.seqOptionsCb[6] == true and true or false + end + + -- set sequencer options using defaults, or loaded project state + seqOptionsCb.val1[1] = (true and m.seqF) and 1 or 0 -- generate + seqOptionsCb.val1[2] = (true and m.seqFirstNoteF) and 1 or 0 -- 1st Note Always + seqOptionsCb.val1[3] = (true and m.seqAccentF) and 1 or 0 -- accent + seqOptionsCb.val1[4] = (true and m.seqLegatoF) and 1 or 0 -- legato + seqOptionsCb.val1[5] = (true and m.seqRndNotesF) and 1 or 0 -- random notes + seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 -- repeat +end -- Sequencer options toggle logic seqOptionsCb.onLClick = function() local debug = false if debug or m.debug then ConMsg("seqOptionsCb.onLClick()") end - m.seqF = seqOptionsCb.val1[1] == 1 and true or false -- Generate + m.seqF = seqOptionsCb.val1[1] == 1 and true or false -- Generate m.seqFirstNoteF = seqOptionsCb.val1[2] == 1 and true or false -- 1st Note Always - m.seqAccentF = seqOptionsCb.val1[3] == 1 and true or false -- Accent - m.seqLegatoF = seqOptionsCb.val1[4] == 1 and true or false -- Legato - m.seqRndNotesF = seqOptionsCb.val1[5] == 1 and true or false -- Randomise Notes - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Repeat + m.seqAccentF = seqOptionsCb.val1[3] == 1 and true or false -- Accent + m.seqLegatoF = seqOptionsCb.val1[4] == 1 and true or false -- Legato + m.seqRndNotesF = seqOptionsCb.val1[5] == 1 and true or false -- Randomise Notes + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Repeat if pExtState.seqOptionsCb then if pExtState.seqOptionsCb[6] ~= m.seqRepeatF then InsertNotes() end @@ -1730,7 +1754,86 @@ seqOptionsCb.onLClick = function() if debug or m.debug then PrintTable(seqOptionsCb.val1) end end --- Sequencer grid radio button +-- Set sequencer grid slider defaults +function SetDefaultSeqGridSliders() + local debug = false + if debug or m.debug then ConMsg("SetDefaultSeqGridSliders()") end + + GetReaperGrid(seqGridRad) + SetSeqGridSizes(t_seqSliders) + + if seqGridRad.val1 == 1 then + if pExtState.seqGrid16 then -- 1/16 grid + for k, v in pairs(t_seqSliders) do + v.val1 = pExtState.seqGrid16[k] + end + else -- not pExtState.seqGrid16 + for k, v in pairs(t_seqSliders) do + v.val1 = m.seqGrid16[k] + end + end -- pExtState.seqGrid16 + + elseif seqGridRad.val1 == 2 then + if pExtState.seqGrid8 then -- 1/8 grid + for k, v in pairs(t_seqSliders) do + v.val1 = pExtState.seqGrid8[k] + end + else -- not pExtState.seqGrid8 + for k, v in pairs(t_seqSliders) do + v.val1 = m.seqGrid8[k] + end + end -- pExtState.seqGrid8 + + elseif seqGridRad.val1 == 3 then + if pExtState.seqGrid4 then -- 1/4 grid + for k, v in pairs(t_seqSliders) do + v.val1 = pExtState.seqGrid4[k] + end + else -- not pExtState.seqGrid4 + for k, v in pairs(t_seqSliders) do + v.val1 = m.seqGrid4[k] + end + end + end -- pExtState.seqGrid4 + + if debug or m.debug then + for k, v in pairs(t_seqSliders) do + ConMsg("t_seqSliders.val1 (4) = " .. tostring(v.val1)) + end + end + +end +-- Reset sequencer grid sliders +seqSldrText.onRClick = function() + local debug = false + if debug or m.debug then ConMsg("seqSldrText.onLClick()") end + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Sequence Sliders") + if result == 1 then + if seqGridRad.val1 == 1 then -- 1/16ths + for k, v in pairs(t_seqSliders) do -- reset the sliders + v.val1 = m.seqGrid16[k] + end -- in pairs(t_seqSliders) + pExtState.seqGrid16 = nil + + elseif seqGridRad.val1 == 2 then -- 1/8ths + for k, v in pairs(t_seqSliders) do -- reset the sliders + v.val1 = m.seqGrid8[k] + end -- in pairs(t_seqSliders) + pExtState.seqGrid8 = nil + + elseif seqGridRad.val1 == 3 then -- 1/4ths + for k, v in pairs(t_seqSliders) do -- reset the sliders + v.val1 = m.seqGrid4[k] + end -- in pairs(t_seqSliders) + pExtState.seqGrid4 = nil + + end -- seqGridRad + pExtSaveStateF = true -- set the ext state save flag + end -- result +end +-- Sequencer grid toggle logic seqGridRad.onLClick = function() -- change grid size local debug = false if debug or m.debug then ConMsg("seqGridRad.onLClick()") end @@ -1784,7 +1887,91 @@ seqGridRad.onLClick = function() -- change grid size end -- m.activeTake end --- Sequencer shift left +-- Set sequencer accent & legato slider defaults +function SetDefaultAccLegSliders() + local debug = false + if debug or m.debug then ConMsg("SetDefaultAccLegSliders()") end + + -- if seq accent & legato sliders were saved to project state, load them + if pExtState.seqAccRSldrLo then + seqAccRSldr.val1 = pExtState.seqAccRSldrLo + else + seqAccRSldr.val1 = m.accentLow + end + if pExtState.seqAccRSldrHi then + seqAccRSldr.val2 = pExtState.seqAccRSldrHi + else + seqAccRSldr.val2 = m.accentHigh + end + if pExtState.seqAccProb then + seqAccProbSldr.val1 = pExtState.seqAccProb + else + seqAccProbSldr.val1 = m.accentProb + end + if pExtState.seqLegProb then + seqLegProbSldr.val1 = pExtState.seqLegProb + else + seqLegProbSldr.val1 = m.legatoProb + end +end -- function +-- Reset sequencer velocity slider +seqAccSldrText.onRClick = function() + local debug = false + if debug or m.debug then ConMsg("seqAccSldrText.onRClick()") end + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Accent Sliders") + + if result == 1 then + seqAccRSldr.val1 = m.accentLow + if pExtState.seqAccRSldrLo then pExtState.seqAccRSldrLo = nil end + seqAccRSldr.val2 = m.accentHigh + if pExtState.seqAccRSldrHi then pExtState.seqAccRSldrHi = nil end + seqAccProbSldr.val1 = m.accentProb + if pExtState.seqAccProb then pExtState.seqAccProb = nil end + pExtSaveStateF = true -- set the ext state save flag + end -- result +end +-- Reset sequencer legato sliders +seqLegSldrText.onRClick = function() + local debug = false + if debug or m.debug then ConMsg("seqLegSldrText.onLClick()") end + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Legato Slider") + + if result == 1 then + seqLegProbSldr.val1 = m.legatoProb + if pExtState.seqLegProb then pExtState.seqLegProb = nil end + pExtSaveStateF = true + end -- result +end + +-- Set sequence shifter defaults +function SetDefaultSeqShift() + local debug = false + if debug or m.debug then ConMsg("SetDefaultSeqShift()") end + + m.seqShift = 0 + m.seqShiftMin = 0 + m.seqShiftMax = 0 + seqShiftVal.label = tostring(m.seqShift) +end +-- Reset sequence shifter state +seqShiftText.onRClick = function() + local debug = false + if debug or m.debug then ConMsg("seqShiftText.onRClick") end + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Note Shift") + + if result == 1 then + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 + seqShiftVal.label = tostring(m.seqShift) + InsertNotes() + end -- result +end +-- Sequence shifter left seqShiftLBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("seqShiftLBtn()") end @@ -1802,7 +1989,7 @@ seqShiftLBtn.onLClick = function() seqShiftVal.label = tostring(m.seqShift) InsertNotes() end --- Sequencer shift right +-- Sequence shifter right seqShiftRBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("seqShiftRBtn()") end @@ -1821,7 +2008,92 @@ seqShiftRBtn.onLClick = function() InsertNotes() end --- Sequencer repeat start +-- Set default sequencer repeater state +function SetDefaultSeqRepeat() + local debug = false + if debug or m.debug then ConMsg("SetDefaultSeqRepeat()") end + + GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) + local gridSize = m.reaGrid * m.ppqn + local itemLength = GetItemLength() + + -- start + if pExtState.loopStartG then + m.loopStartG = pExtState.loopStartG + seqLoopStartDrop.val1 = m.loopStartG + else + m.loopStartG = 1 + seqLoopStartDrop.val1 = m.loopStartG + end + + -- length + if pExtState.loopLenG then + m.loopLenG = pExtState.loopLenG + seqLoopLenDrop.val1 = m.loopLenG + else + m.loopLenG = 1 + seqLoopLenDrop.val1 = m.loopLenG + end + + -- amount + if pExtState.loopNum then + m.loopNum = pExtState.loopNum + seqLoopNumDrop.val1 = m.loopNum + else + m.loopNum = 1 + seqLoopNumDrop.val1 = m.loopNum + end + + m.loopMaxRep = math.floor(itemLength / gridSize) + + for i = 1, m.loopMaxRep do + seqLoopStartDrop.val2[i] = i + seqLoopNumDrop.val2[i] = i + seqLoopLenDrop.val2[i] = i + end +end +-- Reset sequencer repeater +seqLoopText.onRClick = function() + local debug = false + if debug or m.debug then ConMsg("seqLoopText.onRClick") end + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Repeat|Glue Repeat") + + if result == 1 then + -- reset the GUI and repeat flag + m.seqRepeatF = false + seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 + seqOptionsCb.onLClick() + -- reset the drop down lists and clear pExtState + seqLoopStartDrop.val1 = 1; m.loopStartG = 1 + if pExtState.loopStartG then pExtState.loopStartG = nil end + seqLoopLenDrop.val1 = 1; m.loopLenG = 1 + if pExtState.loopLenG then pExtState.loopLenG = nil end + seqLoopNumDrop.val1 = 1; m.loopNum = 1 + if pExtState.loopNum then pExtState.loopNum = nil end + pExtSaveStateF = true -- set the ext state save flag + InsertNotes() + + elseif result == 2 then + m.loopGlueF = true + InsertNotes() + -- reset the GUI and repeat flag + m.seqRepeatF = false + seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 + seqOptionsCb.onLClick() + -- reset the drop down lists and pExtState + seqLoopStartDrop.val1 = 1; m.loopStartG = 1 + if pExtState.loopStartG then pExtState.loopStartG = nil end + seqLoopLenDrop.val1 = 1; m.loopLenG = 1 + if pExtState.loopLenG then pExtState.loopLenG = nil end + seqLoopNumDrop.val1 = 1; m.loopNum = 1 + if pExtState.loopNum then pExtState.loopNum = nil end + pExtSaveStateF = true -- set the ext state save flag + end -- result + +end -- onRClick +-- Sequencer repeater functions seqLoopStartDrop.onLClick = function() local debug = false if debug or m.debug then ConMsg("seqLoopStartDrop.onLClick()") end @@ -1956,278 +2228,6 @@ seqLoopNumDrop.onLClick = function() --pExtSaveStateF = true end --- Set sequencer default options -function SetDefaultSeqOptions() - local debug = false - if debug or m.debug then ConMsg("SetDefaultSeqOptions()") end - - -- if sequencer options were saved to project state, load them - if pExtState.seqOptionsCb then - m.seqF = pExtState.seqOptionsCb[1] == true and true or false - m.seqFirstNoteF = pExtState.seqOptionsCb[2] == true and true or false - m.seqAccentF = pExtState.seqOptionsCb[3] == true and true or false - m.seqLegatoF = pExtState.seqOptionsCb[4] == true and true or false - m.seqRndNotesF = pExtState.seqOptionsCb[5] == true and true or false - m.seqRepeatF = pExtState.seqOptionsCb[6] == true and true or false - end - - -- set sequencer options using defaults, or loaded project state - seqOptionsCb.val1[1] = (true and m.seqF) and 1 or 0 -- generate - seqOptionsCb.val1[2] = (true and m.seqFirstNoteF) and 1 or 0 -- 1st Note Always - seqOptionsCb.val1[3] = (true and m.seqAccentF) and 1 or 0 -- accent - seqOptionsCb.val1[4] = (true and m.seqLegatoF) and 1 or 0 -- legato - seqOptionsCb.val1[5] = (true and m.seqRndNotesF) and 1 or 0 -- random notes - seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 -- repeat -end --- Set default accent & legato sliders -function SetDefaultAccLegSliders() - local debug = false - if debug or m.debug then ConMsg("SetDefaultAccLegSliders()") end - - -- if seq accent & legato sliders were saved to project state, load them - if pExtState.seqAccRSldrLo then - seqAccRSldr.val1 = pExtState.seqAccRSldrLo - else - seqAccRSldr.val1 = m.accentLow - end - if pExtState.seqAccRSldrHi then - seqAccRSldr.val2 = pExtState.seqAccRSldrHi - else - seqAccRSldr.val2 = m.accentHigh - end - if pExtState.seqAccProb then - seqAccProbSldr.val1 = pExtState.seqAccProb - else - seqAccProbSldr.val1 = m.accentProb - end - if pExtState.seqLegProb then - seqLegProbSldr.val1 = pExtState.seqLegProb - else - seqLegProbSldr.val1 = m.legatoProb - end -end -- function --- Set default grid sliders -function SetDefaultSeqGridSliders() - local debug = false - if debug or m.debug then ConMsg("SetDefaultSeqGridSliders()") end - - GetReaperGrid(seqGridRad) - SetSeqGridSizes(t_seqSliders) - - if seqGridRad.val1 == 1 then - if pExtState.seqGrid16 then -- 1/16 grid - for k, v in pairs(t_seqSliders) do - v.val1 = pExtState.seqGrid16[k] - end - else -- not pExtState.seqGrid16 - for k, v in pairs(t_seqSliders) do - v.val1 = m.seqGrid16[k] - end - end -- pExtState.seqGrid16 - - elseif seqGridRad.val1 == 2 then - if pExtState.seqGrid8 then -- 1/8 grid - for k, v in pairs(t_seqSliders) do - v.val1 = pExtState.seqGrid8[k] - end - else -- not pExtState.seqGrid8 - for k, v in pairs(t_seqSliders) do - v.val1 = m.seqGrid8[k] - end - end -- pExtState.seqGrid8 - - elseif seqGridRad.val1 == 3 then - if pExtState.seqGrid4 then -- 1/4 grid - for k, v in pairs(t_seqSliders) do - v.val1 = pExtState.seqGrid4[k] - end - else -- not pExtState.seqGrid4 - for k, v in pairs(t_seqSliders) do - v.val1 = m.seqGrid4[k] - end - end - end -- pExtState.seqGrid4 - - if debug or m.debug then - for k, v in pairs(t_seqSliders) do - ConMsg("t_seqSliders.val1 (4) = " .. tostring(v.val1)) - end - end - -end --- Set default sequencer shift state -function SetDefaultSeqShift() - local debug = false - if debug or m.debug then ConMsg("SetDefaultSeqShift()") end - - m.seqShift = 0 - m.seqShiftMin = 0 - m.seqShiftMax = 0 - seqShiftVal.label = tostring(m.seqShift) -end --- Set default sequencer repeat state -function SetDefaultSeqRepeat() - local debug = false - if debug or m.debug then ConMsg("SetDefaultSeqRepeat()") end - - GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) - local gridSize = m.reaGrid * m.ppqn - local itemLength = GetItemLength() - - -- start - if pExtState.loopStartG then - m.loopStartG = pExtState.loopStartG - seqLoopStartDrop.val1 = m.loopStartG - else - m.loopStartG = 1 - seqLoopStartDrop.val1 = m.loopStartG - end - - -- length - if pExtState.loopLenG then - m.loopLenG = pExtState.loopLenG - seqLoopLenDrop.val1 = m.loopLenG - else - m.loopLenG = 1 - seqLoopLenDrop.val1 = m.loopLenG - end - - -- amount - if pExtState.loopNum then - m.loopNum = pExtState.loopNum - seqLoopNumDrop.val1 = m.loopNum - else - m.loopNum = 1 - seqLoopNumDrop.val1 = m.loopNum - end - - m.loopMaxRep = math.floor(itemLength / gridSize) - - for i = 1, m.loopMaxRep do - seqLoopStartDrop.val2[i] = i - seqLoopNumDrop.val2[i] = i - seqLoopLenDrop.val2[i] = i - end -end - --- Reset sequencer sections -seqSldrText.onRClick = function() - local debug = false - if debug or m.debug then ConMsg("seqSldrText.onLClick()") end - - gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Sequence Sliders") - if result == 1 then - if seqGridRad.val1 == 1 then -- 1/16ths - for k, v in pairs(t_seqSliders) do -- reset the sliders - v.val1 = m.seqGrid16[k] - end -- in pairs(t_seqSliders) - pExtState.seqGrid16 = nil - - elseif seqGridRad.val1 == 2 then -- 1/8ths - for k, v in pairs(t_seqSliders) do -- reset the sliders - v.val1 = m.seqGrid8[k] - end -- in pairs(t_seqSliders) - pExtState.seqGrid8 = nil - - elseif seqGridRad.val1 == 3 then -- 1/4ths - for k, v in pairs(t_seqSliders) do -- reset the sliders - v.val1 = m.seqGrid4[k] - end -- in pairs(t_seqSliders) - pExtState.seqGrid4 = nil - - end -- seqGridRad - pExtSaveStateF = true -- set the ext state save flag - end -- result -end --- Reset sequencer velocity slider -seqAccSldrText.onRClick = function() - local debug = false - if debug or m.debug then ConMsg("seqAccSldrText.onRClick()") end - - gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Accent Sliders") - - if result == 1 then - seqAccRSldr.val1 = m.accentLow - if pExtState.seqAccRSldrLo then pExtState.seqAccRSldrLo = nil end - seqAccRSldr.val2 = m.accentHigh - if pExtState.seqAccRSldrHi then pExtState.seqAccRSldrHi = nil end - seqAccProbSldr.val1 = m.accentProb - if pExtState.seqAccProb then pExtState.seqAccProb = nil end - pExtSaveStateF = true -- set the ext state save flag - end -- result -end --- Reset sequencer legato slider -seqLegSldrText.onRClick = function() - local debug = false - if debug or m.debug then ConMsg("seqLegSldrText.onLClick()") end - - gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Legato Slider") - - if result == 1 then - seqLegProbSldr.val1 = m.legatoProb - if pExtState.seqLegProb then pExtState.seqLegProb = nil end - pExtSaveStateF = true - end -- result -end --- Reset sequencer shift -seqShiftText.onRClick = function() - local debug = false - if debug or m.debug then ConMsg("seqShiftText.onRClick") end - - gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Note Shift") - - if result == 1 then - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 - seqShiftVal.label = tostring(m.seqShift) - InsertNotes() - end -- result -end --- Reset sequencer repeat -seqLoopText.onRClick = function() - local debug = false - if debug or m.debug then ConMsg("seqLoopText.onRClick") end - - gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Repeat|Glue Repeat") - - if result == 1 then - -- reset the GUI and repeat flag - m.seqRepeatF = false - seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 - seqOptionsCb.onLClick() - -- reset the drop down lists and clear pExtState - seqLoopStartDrop.val1 = 1; m.loopStartG = 1 - if pExtState.loopStartG then pExtState.loopStartG = nil end - seqLoopLenDrop.val1 = 1; m.loopLenG = 1 - if pExtState.loopLenG then pExtState.loopLenG = nil end - seqLoopNumDrop.val1 = 1; m.loopNum = 1 - if pExtState.loopNum then pExtState.loopNum = nil end - pExtSaveStateF = true -- set the ext state save flag - InsertNotes() - - elseif result == 2 then - m.loopGlueF = true - InsertNotes() - -- reset the GUI and repeat flag - m.seqRepeatF = false - seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 - seqOptionsCb.onLClick() - -- reset the drop down lists and pExtState - seqLoopStartDrop.val1 = 1; m.loopStartG = 1 - if pExtState.loopStartG then pExtState.loopStartG = nil end - seqLoopLenDrop.val1 = 1; m.loopLenG = 1 - if pExtState.loopLenG then pExtState.loopLenG = nil end - seqLoopNumDrop.val1 = 1; m.loopNum = 1 - if pExtState.loopNum then pExtState.loopNum = nil end - pExtSaveStateF = true -- set the ext state save flag - end -- result - -end -- onRClick - -------------------------------------------------------------------------------- -- Euclidiser -------------------------------------------------------------------------------- @@ -2483,7 +2483,7 @@ function MainLoop() DrawGUI() e.gScaleState = false -- prevent zoom code from running every loop - -- Save last mouse state since GUI was refreshed + -- Save or reset last mouse state since GUI was refreshed gLastMouseCap = gfx.mouse_cap gLastMouseX, gLastMouseY = gfx.mouse_x, gfx.mouse_y gfx.mouse_wheel = 0 -- reset gfx.mouse_wheel @@ -2509,6 +2509,16 @@ function MainLoop() if m.activeEditor then m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) if m.activeTake then + m.currTakeID = string.sub(tostring(m.activeTake),11) + if m.currTakeID ~= m.lastTakeID then + m.lastTakeID = m.currTakeID + -- purge undo/redo buffers and grab new note data + m.notebuf.i = 1 + PurgeNoteBuf() + SetDefaultSeqShift() + SetDefaultSeqRepeat() + GetNotesFromTake() + end ShowMessage(msgText, 0) -- clear old messages -- check for changes in the active take if the "Permute" scale is selected if scaleDrop.val2[scaleDrop.val1] == "Permute" then From d92c264d658e03b17e1432e9180543596c848a2b Mon Sep 17 00:00:00 2001 From: RobU23 Date: Wed, 24 May 2017 21:00:39 +0100 Subject: [PATCH 10/33] take switching clean up --- .../RobU - MIDI Ex Machina.lua | 403 +++++++++--------- 1 file changed, 206 insertions(+), 197 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 0af2d1d..f89cb90 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -943,141 +943,139 @@ function InsertNotes() if debug or m.debug then ConMsg("InsertNotes()") end local i = 1 - if m.activeTake then - local gridSize = math.floor(m.reaGrid * m.ppqn) - local itemLenP = GetItemLength() - local noteShift = math.floor(m.seqShift * gridSize) - local t1 = GetNoteBuf() - - -- note shifter - if debug or m.debug then ConMsg("Shifting...") end - local t2 = {} -- temp table for note shifter (no undo) - CopyTable(t1, t2) - for k, v in pairs(t2) do - v[3] = v[3] + noteShift - v[4] = v[4] + noteShift - if v[3] < 0 then - v[3] = itemLenP + v[3] - v[4] = itemLenP + v[4] - if v[4] > itemLenP then v[4] = itemLenP end - elseif v[3] >= itemLenP then - v[3] = v[3] - itemLenP - v[4] = v[4] - itemLenP + + local gridSize = math.floor(m.reaGrid * m.ppqn) + local itemLenP = GetItemLength() + local noteShift = math.floor(m.seqShift * gridSize) + local t1 = GetNoteBuf() + + -- note shifter + if debug or m.debug then ConMsg("Shifting...") end + local t2 = {} -- temp table for note shifter (no undo) + CopyTable(t1, t2) + for k, v in pairs(t2) do + v[3] = v[3] + noteShift + v[4] = v[4] + noteShift + if v[3] < 0 then + v[3] = itemLenP + v[3] + v[4] = itemLenP + v[4] + if v[4] > itemLenP then v[4] = itemLenP end + elseif v[3] >= itemLenP then + v[3] = v[3] - itemLenP + v[4] = v[4] - itemLenP + end + end -- for k, v t2 + + -- note repeater + if m.seqRepeatF then + if debug or m.debug then ConMsg("Repeating...") end + DeleteNotes() + t3 = {} -- temp table for note repeater (for glueing) + local loopStartP = (m.loopStartG -1) * gridSize + local loopLenP = m.loopLenG * gridSize + local loopEndP = loopStartP + loopLenP + local loopNum = m.loopNum + local i = 1 + local writeOffP = 0 + if loopStartP > 0 then writeOffP = -loopStartP else writeOffP = 0 end + + -- pre-repeat + for k, v in pairs(t2) do + if v[3] >= 0 and v[3] < loopStartP then + t3[i] = {} + t3[i][1] = v[1] -- selected + t3[i][2] = v[2] -- muted + t3[i][3] = v[3] -- startppqn + t3[i][4] = v[4] -- endppqn + if not t3[i][9] then t3[i][4] = t3[i][4] - m.legato end -- handle legatolessness + t3[i][5] = v[5] -- length + t3[i][6] = v[6] -- channel + t3[i][7] = v[7] -- pitch + t3[i][8] = v[8] -- vel + t3[i][9] = v[9] -- legato + reaper.MIDI_InsertNote(m.activeTake, t3[i][1], t3[i][2], t3[i][3], t3[i][4], t3[i][6], t3[i][7], t3[i][8], false) + i = i + 1 end - end -- for k, v t2 - - -- note repeater - if m.seqRepeatF then - if debug or m.debug then ConMsg("Repeating...") end - DeleteNotes() - t3 = {} -- temp table for note repeater (for glueing) - local loopStartP = (m.loopStartG -1) * gridSize - local loopLenP = m.loopLenG * gridSize - local loopEndP = loopStartP + loopLenP - local loopNum = m.loopNum - local i = 1 - local writeOffP = 0 - if loopStartP > 0 then writeOffP = -loopStartP else writeOffP = 0 end - - -- pre-repeat - for k, v in pairs(t2) do - if v[3] >= 0 and v[3] < loopStartP then - t3[i] = {} - t3[i][1] = v[1] -- selected - t3[i][2] = v[2] -- muted - t3[i][3] = v[3] -- startppqn - t3[i][4] = v[4] -- endppqn - if not t3[i][9] then t3[i][4] = t3[i][4] - m.legato end -- handle legatolessness - t3[i][5] = v[5] -- length - t3[i][6] = v[6] -- channel - t3[i][7] = v[7] -- pitch - t3[i][8] = v[8] -- vel - t3[i][9] = v[9] -- legato - reaper.MIDI_InsertNote(m.activeTake, t3[i][1], t3[i][2], t3[i][3], t3[i][4], t3[i][6], t3[i][7], t3[i][8], false) - i = i + 1 - end - end -- k, v in pairs(t2) - pre-repeat - writeOffP = writeOffP + loopStartP - - -- repeat - while loopNum > 0 do - for k, v in pairs(t2) do - if v[3] >= loopStartP and v[3] < loopEndP then - t3[i] = {} - t3[i][1] = v[1] -- selected - t3[i][2] = v[2] -- muted - t3[i][3] = v[3] + writeOffP -- startppqn - if v[4] > loopEndP then t3[i][4] = loopEndP + writeOffP else t3[i][4] = v[4] + writeOffP end -- endppqn - if not t3[i][9] then t3[i][4] = t3[i][4] - m.legato end -- handle legatolessness - t3[i][5] = v[5] -- length - t3[i][6] = v[6] -- channel - t3[i][7] = v[7] -- pitch - t3[i][8] = v[8] -- vel - t3[i][9] = v[9] -- legato - reaper.MIDI_InsertNote(m.activeTake, t3[i][1], t3[i][2], t3[i][3], t3[i][4], t3[i][6], t3[i][7], t3[i][8], false) - i = i + 1 - end -- if v[3] - - end -- for k, v t3 - repeat - loopNum = loopNum - 1 - writeOffP = writeOffP + loopLenP - end -- while loopNum > 0 - - -- post-repeat - local written = loopStartP + (loopLenP * m.loopNum) - local remLenP = itemLenP - written - local readStartP = loopStartP + loopLenP - local readEndP = readStartP + remLenP - local writeOffP = written - readStartP - + end -- k, v in pairs(t2) - pre-repeat + writeOffP = writeOffP + loopStartP + + -- repeat + while loopNum > 0 do for k, v in pairs(t2) do - if v[3] >= readStartP and v[3] < readEndP then + if v[3] >= loopStartP and v[3] < loopEndP then t3[i] = {} t3[i][1] = v[1] -- selected t3[i][2] = v[2] -- muted t3[i][3] = v[3] + writeOffP -- startppqn - if v[4] > itemLenP then t3[i][4] = itemLenP else t3[i][4] = v[4] + writeOffP end -- endppqn + if v[4] > loopEndP then t3[i][4] = loopEndP + writeOffP else t3[i][4] = v[4] + writeOffP end -- endppqn if not t3[i][9] then t3[i][4] = t3[i][4] - m.legato end -- handle legatolessness - t3[i][5] = v[5] -- channel + t3[i][5] = v[5] -- length t3[i][6] = v[6] -- channel t3[i][7] = v[7] -- pitch t3[i][8] = v[8] -- vel t3[i][9] = v[9] -- legato reaper.MIDI_InsertNote(m.activeTake, t3[i][1], t3[i][2], t3[i][3], t3[i][4], t3[i][6], t3[i][7], t3[i][8], false) i = i + 1 - end - end -- k, v in pairs(t2) - post-repeat - - reaper.MIDI_Sort(m.activeTake) - reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off - - else -- not m.seqRepeatF - if debug or m.debug then ConMsg("No repeat...") end - DeleteNotes() - - if m.loopGlueF then - if debug or m.debug then ConMsg("Glueing...") end - t4 = NewNoteBuf(); CopyTable(t3, t4) - if debug or m.debug then PrintNotes(t4) end - for k, v in pairs(t4) do - reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) - end - m.loopGlueF = false - - else -- not glueing - if debug or m.debug then ConMsg("no glueing, inserting shift table (t2)") end - for k, v in pairs(t2) do -- use the post-shifter table - if not v[9] then v[4] = v[4] - m.legato end -- handle legatolessness - reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) - end -- for k, v t2 - end -- m.loopGlueF - - reaper.MIDI_Sort(m.activeTake) - reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off - end -- m.seqRepeatF - else - if debug or m.debug then ConMsg("No Active Take") end - end -- m.activeTake + end -- if v[3] + + end -- for k, v t3 - repeat + loopNum = loopNum - 1 + writeOffP = writeOffP + loopLenP + end -- while loopNum > 0 + + -- post-repeat + local written = loopStartP + (loopLenP * m.loopNum) + local remLenP = itemLenP - written + local readStartP = loopStartP + loopLenP + local readEndP = readStartP + remLenP + local writeOffP = written - readStartP + + for k, v in pairs(t2) do + if v[3] >= readStartP and v[3] < readEndP then + t3[i] = {} + t3[i][1] = v[1] -- selected + t3[i][2] = v[2] -- muted + t3[i][3] = v[3] + writeOffP -- startppqn + if v[4] > itemLenP then t3[i][4] = itemLenP else t3[i][4] = v[4] + writeOffP end -- endppqn + if not t3[i][9] then t3[i][4] = t3[i][4] - m.legato end -- handle legatolessness + t3[i][5] = v[5] -- channel + t3[i][6] = v[6] -- channel + t3[i][7] = v[7] -- pitch + t3[i][8] = v[8] -- vel + t3[i][9] = v[9] -- legato + reaper.MIDI_InsertNote(m.activeTake, t3[i][1], t3[i][2], t3[i][3], t3[i][4], t3[i][6], t3[i][7], t3[i][8], false) + i = i + 1 + end + end -- k, v in pairs(t2) - post-repeat + + reaper.MIDI_Sort(m.activeTake) + reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off + + else -- not m.seqRepeatF + if debug or m.debug then ConMsg("No repeat...") end + DeleteNotes() + + if m.loopGlueF then + if debug or m.debug then ConMsg("Glueing...") end + t4 = NewNoteBuf(); CopyTable(t3, t4) + if debug or m.debug then PrintNotes(t4) end + for k, v in pairs(t4) do + reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) + end + m.loopGlueF = false + + else -- not glueing + if debug or m.debug then ConMsg("no glueing, inserting shift table (t2)") end + for k, v in pairs(t2) do -- use the post-shifter table + if not v[9] then v[4] = v[4] - m.legato end -- handle legatolessness + reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) + end -- for k, v t2 + end -- m.loopGlueF + + reaper.MIDI_Sort(m.activeTake) + reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off + end -- m.seqRepeatF + end -------------------------------------------------------------------------------- -- PrintNotes - arg note_buffer t; print note_buffer to reaper console @@ -1480,6 +1478,24 @@ randomBtn.onLClick = function() pExtSaveStateF = true end --m.activeTake end + +-- Set randomiser default options +function SetDefaultRndOptions() + local debug = false + if debug or m.debug then ConMsg("SetDefaultRndOptions()") end + + -- if randomiser options were saved to project state, load them + if pExtState.noteOptionsCb then + m.rndAllNotesF = pExtState.noteOptionsCb[1] == true and true or false + m.rndFirstNoteF = pExtState.noteOptionsCb[2] == true and true or false + m.rndOctX2F = pExtState.noteOptionsCb[3] == true and true or false + end + + -- set randomiser options using defaults, or loaded project state + noteOptionsCb.val1[1] = (true and m.rndAllNotesF) and 1 or 0 -- all notes + noteOptionsCb.val1[2] = (true and m.rndFirstNoteF) and 1 or 0 -- first note root + noteOptionsCb.val1[3] = (true and m.rndOctX2F) and 1 or 0 -- octave doubler +end -- Randomiser options toggle logic noteOptionsCb.onLClick = function() local debug = false @@ -1492,6 +1508,7 @@ noteOptionsCb.onLClick = function() pExtSaveStateF = true if debug or m.debug then PrintTable(noteOptionsCb.val1) end end + -- Root Key droplist keyDrop.onLClick = function() local debug = false @@ -1565,24 +1582,8 @@ function SetDefaultScaleOpts() SetScale(m.curScaleName, m.scales, m.preNoteProbTable) --set chosen scale UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) -- set sliders labels to current scale notes end --- Set default randomiser options -function SetDefaultRndOptions() - local debug = false - if debug or m.debug then ConMsg("SetDefaultRndOptions()") end - - -- if randomiser options were saved to project state, load them - if pExtState.noteOptionsCb then - m.rndAllNotesF = pExtState.noteOptionsCb[1] == true and true or false - m.rndFirstNoteF = pExtState.noteOptionsCb[2] == true and true or false - m.rndOctX2F = pExtState.noteOptionsCb[3] == true and true or false - end - -- set randomiser options using defaults, or loaded project state - noteOptionsCb.val1[1] = (true and m.rndAllNotesF) and 1 or 0 -- all notes - noteOptionsCb.val1[2] = (true and m.rndFirstNoteF) and 1 or 0 -- first note root - noteOptionsCb.val1[3] = (true and m.rndOctX2F) and 1 or 0 -- octave doubler -end --- Set default randomiser sliders +-- Set randomiser note slider defaults function SetDefaultRndSliders() local debug = false if debug or m.debug then ConMsg("SetDefaultRndSliders()") end @@ -1603,8 +1604,7 @@ function SetDefaultRndSliders() octProbSldr.val1 = m.rndOctProb end end - --- Reset note probability sliders +-- Reset randomiser note sliders probSldrText.onRClick = function() local debug = false if debug or m.debug then ConMsg("probSldrText.onRClick()") end @@ -1624,7 +1624,8 @@ probSldrText.onRClick = function() pExtSaveStateF = true -- set the ext state save flag end -- result end --- Reset octave probability slider + +-- Reset octave slider octProbText.onRClick = function() local debug = false if debug or m.debug then ConMsg("octProbText.onRClick()") end @@ -1963,7 +1964,7 @@ seqShiftText.onRClick = function() if debug or m.debug then ConMsg("seqShiftText.onRClick") end gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Note Shift") + local result = gfx.showmenu("Reset Note Shift|Glue Shift") if result == 1 then m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 @@ -2265,18 +2266,73 @@ euclidBtn.onLClick = function() pExtSaveStateF = true end -- m.activeTake end --- Euclidiser options + +-- Set euclid default options +function SetDefaultEucOptions() + local debug = false + if debug or m.debug then ConMsg("SetDefaultEucOptions()") end + + -- if euclidean options were saved to project state, load them + if pExtState.eucOptionsCb then + m.eucF = pExtState.eucOptionsCb[1] == true and true or false + m.eucAccentF = pExtState.eucOptionsCb[2] == true and true or false + m.eucRndNotesF = pExtState.eucOptionsCb[3] == true and true or false + end + + -- set euclidean options using defaults, or loaded project state + eucOptionsCb.val1[1] = (true and m.eucF) and 1 or 0 -- generate + eucOptionsCb.val1[2] = (true and m.eucAccentF) and 1 or 0 -- accents + eucOptionsCb.val1[3] = (true and m.eucRndNotesF) and 1 or 0 -- randomise notes +end + +-- Euclidiser options logic eucOptionsCb.onLClick = function() local debug = false if debug or m.debug then ConMsg("eucOptionsCb.onLClick()") end - m.eucF = eucOptionsCb.val1[1] == 1 and true or false -- Generate - m.eucAccentF = eucOptionsCb.val1[2] == 1 and true or false -- Accent + m.eucF = eucOptionsCb.val1[1] == 1 and true or false -- Generate + m.eucAccentF = eucOptionsCb.val1[2] == 1 and true or false -- Accent m.eucRndNotesF = eucOptionsCb.val1[3] == 1 and true or false -- Randomise notes + pExtState.eucOptionsCb = {m.eucF, m.eucAccentF, m.eucRndNotesF} pExtSaveStateF = true if debug or m.debug then PrintTable(eucOptionsCb.val1) end end + +-- Set euclid slider defaults +function SetDefaultEucSliders() + local debug = false + if debug or m.debug then ConMsg("SetDefaultEucSliders()") end + + -- if euclidean sliders were saved to project state, load them + if pExtState.eucSliders then + for k, v in pairs(t_euclidSliders) do + v.val1 = pExtState.eucSliders[k] + end + else + + euclidPulsesSldr.val1 = m.eucPulses + euclidStepsSldr.val1 = m.eucSteps + euclidRotationSldr.val1 = m.eucRot + end -- load pExtState +end +-- Reset euclid sliders +txtEuclidLabel.onRClick = function() + local debug = false + if debug or m.debug then ConMsg("txtEuclidLabel.onLClick()") end + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Euclid Sliders") + + if result == 1 then + euclidPulsesSldr.val1 = m.eucPulses + euclidStepsSldr.val1 = m.eucSteps + euclidRotationSldr.val1 = m.eucRot + pExtSaveStateF = true + pExtState.eucSliders = nil + end -- result +end + -- Euclid pulses slider euclidPulsesSldr.onMove = function() local debug = false @@ -2314,57 +2370,6 @@ euclidRotationSldr.onMove = function() end end --- Set default euclid options -function SetDefaultEucOptions() - local debug = false - if debug or m.debug then ConMsg("SetDefaultEucOptions()") end - - -- if euclidean options were saved to project state, load them - if pExtState.eucOptionsCb then - m.eucF = pExtState.eucOptionsCb[1] == true and true or false - m.eucAccentF = pExtState.eucOptionsCb[2] == true and true or false - m.eucRndNotesF = pExtState.eucOptionsCb[3] == true and true or false - end - - -- set euclidean options using defaults, or loaded project state - eucOptionsCb.val1[1] = (true and m.eucF) and 1 or 0 -- generate - eucOptionsCb.val1[2] = (true and m.eucAccentF) and 1 or 0 -- accents - eucOptionsCb.val1[3] = (true and m.eucRndNotesF) and 1 or 0 -- randomise notes -end --- Set default euclid sliders -function SetDefaultEucSliders() - local debug = false - if debug or m.debug then ConMsg("SetDefaultEucSliders()") end - - -- if euclidean sliders were saved to project state, load them - if pExtState.eucSliders then - for k, v in pairs(t_euclidSliders) do - v.val1 = pExtState.eucSliders[k] - end - else - - euclidPulsesSldr.val1 = m.eucPulses - euclidStepsSldr.val1 = m.eucSteps - euclidRotationSldr.val1 = m.eucRot - end -- load pExtState -end - --- Reset euclidean sliders -txtEuclidLabel.onRClick = function() - local debug = false - if debug or m.debug then ConMsg("txtEuclidLabel.onLClick()") end - - gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Euclid Sliders") - - if result == 1 then - euclidPulsesSldr.val1 = m.eucPulses - euclidStepsSldr.val1 = m.eucSteps - euclidRotationSldr.val1 = m.eucRot - pExtSaveStateF = true - pExtState.eucSliders = nil - end -- result -end -------------------------------------------------------------------------------- -- Draw GUI @@ -2474,6 +2479,7 @@ function MainLoop() end -- if resized, set scale flag and reset gfx if m.zoomF == true then + if debug or m.debug then ConMsg("m.zoomF == true") end e.gScaleState = true gfx.quit() InitGFX() @@ -2511,10 +2517,13 @@ function MainLoop() if m.activeTake then m.currTakeID = string.sub(tostring(m.activeTake),11) if m.currTakeID ~= m.lastTakeID then + if debug or m.debug then ConMsg("switched MIDI item...") end m.lastTakeID = m.currTakeID -- purge undo/redo buffers and grab new note data m.notebuf.i = 1 PurgeNoteBuf() + t = GetNoteBuf() + ClearTable(t) SetDefaultSeqShift() SetDefaultSeqRepeat() GetNotesFromTake() From 9f83e9fd135f6b4be37e711012487787a165e726 Mon Sep 17 00:00:00 2001 From: RobU Date: Thu, 25 May 2017 07:27:47 +0100 Subject: [PATCH 11/33] fix for no media item in GetItemLength() --- .../RobU - MIDI Ex Machina.lua | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index f89cb90..50124c8 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -88,7 +88,7 @@ m.defFont = e.Lucinda; m.defFontSz = 15 m.oct = 4; m.key = 1; m.root = 0 -- (options, except m.root) -- midi editor, take, grid -m.activeEditor, m.activeTake = nil, nil +m.activeEditor, m.activeTake, m.mediaItem = nil, nil, nil m.currTakeID, m.lastTakeID = "", "" m.ppqn = 960; -- default ppqn, no idea how to check if this has been changed.. m.reaGrid = 0 @@ -427,22 +427,25 @@ function GetItemLength() if debug or m.debug then ConMsg("GetItemLength()") end mItem = reaper.GetSelectedMediaItem(0, 0) - mItemLen = reaper.GetMediaItemInfo_Value(mItem, "D_LENGTH") - mBPM, mBPI = reaper.GetProjectTimeSignature2(0) - msPerMin = 60000 - msPerQN = msPerMin / mBPM - numQNPerItem = (mItemLen * 1000) / msPerQN - numBarsPerItem = numQNPerItem / 4 - ItemPPQN = numQNPerItem * m.ppqn - if debug or m.debug then - --ConMsg("ItemLen (ms) = " .. mItemLen) - --ConMsg("mBPM = " .. mBPM) - --ConMsg("MS Per QN = " .. msPerQN) - ConMsg("Num of QNs = " .. numQNPerItem) - ConMsg("Num of Measures = " .. numBarsPerItem) - ConMsg("Itemlen (ppqn) = " .. ItemPPQN) + if mItem then + if debug or m.debug then ConMsg("mItem = " .. tostring(mItem)) end + mItemLen = reaper.GetMediaItemInfo_Value(mItem, "D_LENGTH") + mBPM, mBPI = reaper.GetProjectTimeSignature2(0) + msPerMin = 60000 + msPerQN = msPerMin / mBPM + numQNPerItem = (mItemLen * 1000) / msPerQN + numBarsPerItem = numQNPerItem / 4 + ItemPPQN = numQNPerItem * m.ppqn + if debug or m.debug then + --ConMsg("ItemLen (ms) = " .. mItemLen) + --ConMsg("mBPM = " .. mBPM) + --ConMsg("MS Per QN = " .. msPerQN) + --ConMsg("Num of QNs = " .. numQNPerItem) + --ConMsg("Num of Measures = " .. numBarsPerItem) + ConMsg("Itemlen (ppqn) = " .. ItemPPQN) + end + return math.floor(ItemPPQN) end - return math.floor(ItemPPQN) end -------------------------------------------------------------------------------- -- GetReaperGrid() - get the current grid size, set global var m.reaGrid @@ -2412,11 +2415,20 @@ function InitMidiExMachina() -- grab the midi editor, and active take m.activeEditor = reaper.MIDIEditor_GetActive() if m.activeEditor then + if debug or m.debug then ConMsg("activeEditor = " .. tostring(m.activeEditor)) end m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) - __ = NewNoteBuf() + if m.activeTake then + if debug or m.debug then ConMsg("activeTake = " .. tostring(m.activeTake)) end + __ = NewNoteBuf() + -- get the take's parent media item + m.mediaItem = reaper.GetMediaItemTake_Item(m.activeTake) + reaper.SetMediaItemSelected(m.mediaItem, true) + reaper.UpdateArrange() + -- get some item info + GetItemLength() + GetNotesFromTake() -- grab the original note data (if any...) + end if not m.activeTake then ConMsg("InitMidiExMachina() - No Active Take") end - else - ConMsg("InitMidiMachina() - No Active MIDI Editor") end -- m.activeEditor -- Load ProjectExtState @@ -2427,9 +2439,7 @@ function InitMidiExMachina() end -- pExtStateStr end -- pExtLoadStateF - -- get some item info - GetItemLength() - GetNotesFromTake() -- grab the original note data (if any...) + -- set GUI defaults or restore from project state SetDefaultWindowOpts(); SetDefaultLayer() From 4186a2857a1f85671256d55e1c7e2f6fd0a1003c Mon Sep 17 00:00:00 2001 From: RobU Date: Fri, 26 May 2017 07:03:20 +0100 Subject: [PATCH 12/33] minor exit code update in prep for reset of shifter and repeater --- .../MIDI Ex Machina/RobU - MIDI Ex Machina.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 50124c8..08c0678 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -2511,16 +2511,20 @@ function MainLoop() -- Defer 'MainLoop' if not explicitly quiting (esc) if char ~= -1 and char ~= 27 then reaper.defer(MainLoop) - elseif pExtSaveStateF then -- quiting, save script state - pExtStateStr = pickle(pExtState) - reaper.SetProjExtState(0, "MEM", "pExtState", pExtStateStr ) - --pExtSaveStateF = false + else + -- reset the shifter and repeater + -- add code here... + if pExtSaveStateF then -- quiting, save script state + pExtStateStr = pickle(pExtState) + reaper.SetProjExtState(0, "MEM", "pExtState", pExtStateStr ) + --pExtSaveStateF = false + end end -- Update Reaper GFX gfx.update() - -- check for midi editor and take + -- check for midi editor, take, and media item m.activeEditor = reaper.MIDIEditor_GetActive() if m.activeEditor then m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) From 17b54a6b0b8c43a38f468b7d71b7ef3b33c476b1 Mon Sep 17 00:00:00 2001 From: RobU23 Date: Fri, 26 May 2017 21:55:52 +0100 Subject: [PATCH 13/33] debug tweaks --- .../RobU - MIDI Ex Machina.lua | 79 +++++++++---------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 08c0678..9ccaf6e 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -413,8 +413,7 @@ local function PurgeNoteBuf() while m.notebuf.max > m.notebuf.i do m.notebuf[m.notebuf.max] = nil - if debug or m.debug then ConMsg("purging buffer " .. tostring(m.notebuf.max)) - end + if debug or m.debug then ConMsg("purging buffer " .. tostring(m.notebuf.max)) end m.notebuf.max = m.notebuf.max - 1 end end @@ -456,6 +455,7 @@ function GetReaperGrid(gridRad) if m.activeTake then m.reaGrid, __, __ = reaper.MIDI_GetGrid(m.activeTake) -- returns quarter notes + if debug or m.debug then ConMsg("m.reaGrid = " .. tostring(m.reaGrid)) end if gridRad then -- if a grid object was passed, update it if m.reaGrid == 0.25 then gridRad.val1 = 1 -- 1/16 elseif m.reaGrid == 0.5 then gridRad.val1 = 2 -- 1/8 @@ -495,7 +495,7 @@ end -------------------------------------------------------------------------------- function GetNotesFromTake() local debug = false - if debug or m.debug then ConMsg("\nGetNotesFromTake()") end + if debug or m.debug then ConMsg("GetNotesFromTake()") end local i, t if m.activeTake then @@ -523,7 +523,7 @@ function GetNotesFromTake() t[i][9] = rem == 0 and true or false end -- for i end -- num_notes - if debug or m.debug then PrintNotes(t) end + if debug and m.debug then PrintNotes(t) end else -- no active take if debug or m.debug then ConMsg("No Active Take") end end -- m.activeTake @@ -645,7 +645,6 @@ end -------------------------------------------------------------------------------- function SetScale(scaleName, allScales, scale) local debug = false - if debug or m.debug then ConMsg("SetScale()") end ClearTable(scale) for i = 1, #allScales, 1 do @@ -662,7 +661,7 @@ function SetScale(scaleName, allScales, scale) break end end - if debug or m.debug then ConMsg("scaleName = " .. tostring(scaleName)) end + if debug or m.debug then ConMsg("SetScale() - scaleName = " .. tostring(scaleName)) end end -------------------------------------------------------------------------------- -- SetSeqGridSizes() @@ -749,13 +748,13 @@ end -------------------------------------------------------------------------------- function RandomiseNotesPoly(noteProbTable) local debug = false - if debug or m.debug then ConMsg("\nRandomiseNotesPoly()") end + if debug or m.debug then ConMsg("RandomiseNotesPoly()") end m.dupes.i = 1 local i = 1 local t1, t2 = GetNoteBuf(), NewNoteBuf() CopyTable(t1, t2) - if debug or m.debug then PrintNotes(t1) end + if debug and m.debug then PrintNotes(t1) end while t2[i] do if t2[i][1] == true or m.rndAllNotesF then -- if selected, or all notes flag is true @@ -769,7 +768,7 @@ function RandomiseNotesPoly(noteProbTable) end -- while t1[i] PurgeNoteBuf() - if debug or m.debug then PrintNotes(t2) end + if debug and m.debug then PrintNotes(t2) end InsertNotes() if m.rndPermuteF and m.activeTake then __, pHash = reaper.MIDI_GetHash(m.activeTake, false, 0) @@ -781,7 +780,7 @@ end -------------------------------------------------------------------------------- function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) local debug = false - if debug or m.debug then ConMsg("\nGenSequence()") end + if debug or m.debug then ConMsg("GenSequence()") end local t = NewNoteBuf() GetReaperGrid() -- populates m.reaGrid @@ -839,7 +838,7 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) end -- newNote end -- itemPos < itemLength - if debug or m.debug then PrintNotes(t) end + if debug and m.debug then PrintNotes(t) end PurgeNoteBuf() --if not m.seqRndNotesF then InsertNotes() end InsertNotes() @@ -849,7 +848,7 @@ end -------------------------------------------------------------------------------- function GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) local debug = false - if debug or m.debug then ConMsg("\nGenBjorklund()") end + if debug or m.debug then ConMsg("GenBjorklund()") end local floor = math.floor local t, t2 = NewNoteBuf(), GetNoteBuf() @@ -911,7 +910,7 @@ end -------------------------------------------------------------------------------- function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) local debug = false - if debug or m.debug then ConMsg("\nGenNoteAttributes()") end + if debug or m.debug then ConMsg("GenNoteAttributes()") end if not accF and not legF then return end local t1, t2 = GetNoteBuf(), NewNoteBuf() @@ -1061,7 +1060,7 @@ function InsertNotes() if m.loopGlueF then if debug or m.debug then ConMsg("Glueing...") end t4 = NewNoteBuf(); CopyTable(t3, t4) - if debug or m.debug then PrintNotes(t4) end + if debug and m.debug then PrintNotes(t4) end for k, v in pairs(t4) do reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) end @@ -1294,7 +1293,7 @@ local t_Textboxes = {probSldrText, octProbText, seqGridText, seqSldrText, seqShi -- Window zoom droplist zoomDrop.onLClick = function() -- window scaling local debug = false - if debug or m.debug then ConMsg("zoomDrop.onLClick()") end + if debug or m.debug then ConMsg("\nzoomDrop.onLClick()") end if zoomDrop.val1 == 1 then e.gScale = 0.7 elseif zoomDrop.val1 == 2 then e.gScale = 0.8 @@ -1322,7 +1321,7 @@ end -- Layer 1 button layerBtn01.onLClick = function() -- randomiser local debug = false - if debug or m.debug then ConMsg("layerBtn01.onLClick() (note randomiser)") end + if debug or m.debug then ConMsg("\nlayerBtn01.onLClick() (note randomiser)") end e.gActiveLayer = 1 zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_green) @@ -1343,7 +1342,7 @@ end -- Layer 2 button layerBtn02.onLClick = function() -- sequencer local debug = false - if debug or m.debug then ConMsg("layerBtn02.onLClick() (sequencer)") end + if debug or m.debug then ConMsg("\nlayerBtn02.onLClick() (sequencer)") end e.gActiveLayer = 2 zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_yellow) @@ -1364,7 +1363,7 @@ end -- Layer 3 button layerBtn03.onLClick = function() -- euclidean local debug = false - if debug or m.debug then ConMsg("layerBtn03.onLClick() (euclid)") end + if debug or m.debug then ConMsg("\nlayerBtn03.onLClick() (euclid)") end e.gActiveLayer = 3 zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_orange) @@ -1385,7 +1384,7 @@ end -- Layer 4 button layerBtn04.onLClick = function() -- options local debug = false - if debug or m.debug then ConMsg("layerBtn04.onLClick() (options)") end + if debug or m.debug then ConMsg("\nlayerBtn04.onLClick() (options)") end e.gActiveLayer = 4 zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_grey5) @@ -1406,7 +1405,7 @@ end -- Undo button undoBtn.onLClick = function() -- undo local debug = false - if debug or m.debug then ConMsg("undoBtn.onLClick()") end + if debug or m.debug then ConMsg("\nundoBtn.onLClick()") end UndoNoteBuf() InsertNotes() @@ -1415,7 +1414,7 @@ end -- Redo button redoBtn.onLClick = function() -- redo local debug = false - if debug or m.debug then ConMsg("redoBtn.onLClick()") end + if debug or m.debug then ConMsg("\nredoBtn.onLClick()") end if m.notebuf[m.notebuf.i + 1] ~= nil then --PrintNotes(m.notebuf[m.notebuf.i + 1]) @@ -1423,7 +1422,7 @@ redoBtn.onLClick = function() -- redo InsertNotes() --PrintNotes(m.notebuf[m.notebuf.i]) else - if debug or m.debug then ConMsg("\nnothing to redo...") end + if debug or m.debug then ConMsg("nothing to redo...") end end end -- Set default window options @@ -1515,7 +1514,7 @@ end -- Root Key droplist keyDrop.onLClick = function() local debug = false - if debug or m.debug then ConMsg("keyDrop.onLClick()") end + if debug or m.debug then ConMsg("\nkeyDrop.onLClick()") end m.key = keyDrop.val1 m.root = SetRootNote(m.oct, m.key) @@ -1528,7 +1527,7 @@ end -- Octave droplist octDrop.onLClick = function() local debug = false - if debug or m.debug then ConMsg("octDrop.onLClick()") end + if debug or m.debug then ConMsg("\noctDrop.onLClick()") end m.oct = octDrop.val1 m.root = SetRootNote(m.oct, m.key) @@ -1540,7 +1539,7 @@ end -- Scale droplist scaleDrop.onLClick = function() local debug = false - if debug or m.debug then ConMsg("scaleDrop.onLClick()") end + if debug or m.debug then ConMsg("\nscaleDrop.onLClick()") end SetScale(scaleDrop.val2[scaleDrop.val1], m.scales, m.preNoteProbTable) if m.rndPermuteF then noteOptionsCb.val1[1] = 0 @@ -1610,7 +1609,7 @@ end -- Reset randomiser note sliders probSldrText.onRClick = function() local debug = false - if debug or m.debug then ConMsg("probSldrText.onRClick()") end + if debug or m.debug then ConMsg("\nprobSldrText.onRClick()") end gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Note Sliders") @@ -1631,7 +1630,7 @@ end -- Reset octave slider octProbText.onRClick = function() local debug = false - if debug or m.debug then ConMsg("octProbText.onRClick()") end + if debug or m.debug then ConMsg("\noctProbText.onRClick()") end gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Octave Slider") @@ -1810,7 +1809,7 @@ end -- Reset sequencer grid sliders seqSldrText.onRClick = function() local debug = false - if debug or m.debug then ConMsg("seqSldrText.onLClick()") end + if debug or m.debug then ConMsg("\nseqSldrText.onLClick()") end gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Sequence Sliders") @@ -1840,7 +1839,7 @@ end -- Sequencer grid toggle logic seqGridRad.onLClick = function() -- change grid size local debug = false - if debug or m.debug then ConMsg("seqGridRad.onLClick()") end + if debug or m.debug then ConMsg("\nseqGridRad.onLClick()") end if m.activeTake then @@ -1921,7 +1920,7 @@ end -- function -- Reset sequencer velocity slider seqAccSldrText.onRClick = function() local debug = false - if debug or m.debug then ConMsg("seqAccSldrText.onRClick()") end + if debug or m.debug then ConMsg("\nseqAccSldrText.onRClick()") end gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Accent Sliders") @@ -1939,7 +1938,7 @@ end -- Reset sequencer legato sliders seqLegSldrText.onRClick = function() local debug = false - if debug or m.debug then ConMsg("seqLegSldrText.onLClick()") end + if debug or m.debug then ConMsg("\nseqLegSldrText.onLClick()") end gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Legato Slider") @@ -1964,7 +1963,7 @@ end -- Reset sequence shifter state seqShiftText.onRClick = function() local debug = false - if debug or m.debug then ConMsg("seqShiftText.onRClick") end + if debug or m.debug then ConMsg("\nseqShiftText.onRClick") end gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Note Shift|Glue Shift") @@ -1978,7 +1977,7 @@ end -- Sequence shifter left seqShiftLBtn.onLClick = function() local debug = false - if debug or m.debug then ConMsg("seqShiftLBtn()") end + if debug or m.debug then ConMsg("\nseqShiftLBtn()") end local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() @@ -1996,7 +1995,7 @@ end -- Sequence shifter right seqShiftRBtn.onLClick = function() local debug = false - if debug or m.debug then ConMsg("seqShiftRBtn()") end + if debug or m.debug then ConMsg("\nseqShiftRBtn()") end local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() @@ -2059,7 +2058,7 @@ end -- Reset sequencer repeater seqLoopText.onRClick = function() local debug = false - if debug or m.debug then ConMsg("seqLoopText.onRClick") end + if debug or m.debug then ConMsg("\nseqLoopText.onRClick") end gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Repeat|Glue Repeat") @@ -2100,7 +2099,7 @@ end -- onRClick -- Sequencer repeater functions seqLoopStartDrop.onLClick = function() local debug = false - if debug or m.debug then ConMsg("seqLoopStartDrop.onLClick()") end + if debug or m.debug then ConMsg("\nseqLoopStartDrop.onLClick()") end GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) local gridSizeP = m.reaGrid * m.ppqn @@ -2152,7 +2151,7 @@ end -- Sequencer repeat length seqLoopLenDrop.onLClick = function() local debug = false - if debug or m.debug then ConMsg("seqLoopLenDrop.onLClick()") end + if debug or m.debug then ConMsg("\nseqLoopLenDrop.onLClick()") end GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) local gridSizeP = m.reaGrid * m.ppqn @@ -2197,7 +2196,7 @@ end -- Sequencer repeat amount seqLoopNumDrop.onLClick = function() local debug = false - if debug or m.debug then ConMsg("seqLoopNumDrop.onLClick()") end + if debug or m.debug then ConMsg("\nseqLoopNumDrop.onLClick()") end GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) local gridSizeP = m.reaGrid * m.ppqn @@ -2322,7 +2321,7 @@ end -- Reset euclid sliders txtEuclidLabel.onRClick = function() local debug = false - if debug or m.debug then ConMsg("txtEuclidLabel.onLClick()") end + if debug or m.debug then ConMsg("\ntxtEuclidLabel.onLClick()") end gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Euclid Sliders") @@ -2449,7 +2448,7 @@ function InitMidiExMachina() SetDefaultSeqGridSliders(); SetDefaultAccLegSliders() SetDefaultEucOptions(); SetDefaultEucSliders() - if debug or m.debug then ConMsg("End InitMidiExMachina()\n") end + if debug or m.debug then ConMsg("End InitMidiExMachina()") end end -------------------------------------------------------------------------------- -- InitGFX From 2a68aa06b8b355599b8b9b8c8d85f043a44b5cd0 Mon Sep 17 00:00:00 2001 From: RobU Date: Sun, 28 May 2017 20:40:43 +0100 Subject: [PATCH 14/33] shift/repeat glue fiasco... --- .../RobU - MIDI Ex Machina.lua | 157 ++++++++++++------ 1 file changed, 106 insertions(+), 51 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 9ccaf6e..8a706cb 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -116,6 +116,7 @@ m.seqGrid16 = {8, 8, 0, 4} -- sane default sequencer note length slider values m.seqGrid8 = {0, 8, 2, 2} -- sane default sequencer note length slider values m.seqGrid4 = {0, 2, 8, 1} -- sane default sequencer note length slider values m.seqShift = 0; m.seqShiftMin = -16; m.seqShiftMax = 16 -- shift notes left-right from sequencer +m.shiftGlueF = false m.loopStartG, m.loopLenG, m.loopNum, m.loopMaxRep = 0, 0, 0, 0 -- repeat values for GUI m.t_loopStart, m.t_loopNum, m.t_loopLen = {}, {}, {} -- repeat value tables m.loopGlueF = false @@ -944,30 +945,31 @@ function InsertNotes() local debug = false if debug or m.debug then ConMsg("InsertNotes()") end - local i = 1 - local gridSize = math.floor(m.reaGrid * m.ppqn) local itemLenP = GetItemLength() local noteShift = math.floor(m.seqShift * gridSize) - local t1 = GetNoteBuf() + local t1, t2, t3, t4 = GetNoteBuf(), nil, nil, nil -- note shifter - if debug or m.debug then ConMsg("Shifting...") end - local t2 = {} -- temp table for note shifter (no undo) + if debug or m.debug then ConMsg("Not glueing shifter...") end + t2 = {} -- temp table for note shifter (no undo) CopyTable(t1, t2) for k, v in pairs(t2) do v[3] = v[3] + noteShift v[4] = v[4] + noteShift + if v[3] < 0 then v[3] = itemLenP + v[3] v[4] = itemLenP + v[4] if v[4] > itemLenP then v[4] = itemLenP end + elseif v[3] >= itemLenP then v[3] = v[3] - itemLenP v[4] = v[4] - itemLenP end end -- for k, v t2 + -- note repeater if m.seqRepeatF then if debug or m.debug then ConMsg("Repeating...") end @@ -1058,16 +1060,16 @@ function InsertNotes() DeleteNotes() if m.loopGlueF then - if debug or m.debug then ConMsg("Glueing...") end + if debug or m.debug then ConMsg("Glueing repeater...") end t4 = NewNoteBuf(); CopyTable(t3, t4) if debug and m.debug then PrintNotes(t4) end for k, v in pairs(t4) do reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) - end m.loopGlueF = false + end - else -- not glueing - if debug or m.debug then ConMsg("no glueing, inserting shift table (t2)") end + else -- not glueing repeater + if debug or m.debug then ConMsg("no glueing repeater, inserting shift table (t2)") end for k, v in pairs(t2) do -- use the post-shifter table if not v[9] then v[4] = v[4] - m.legato end -- handle legatolessness reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) @@ -1078,6 +1080,14 @@ function InsertNotes() reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off end -- m.seqRepeatF + if m.shiftGlueF then + -- glue using t2 and new note buf + elseif m.loopGlueF then + -- glue using t3 and new note buf + else -- no glueing going on + end + + end -------------------------------------------------------------------------------- -- PrintNotes - arg note_buffer t; print note_buffer to reaper console @@ -1653,7 +1663,7 @@ sequenceBtn.onLClick = function() if debug or m.debug then ConMsg("\nsequenceBtn.onLClick()") end if m.activeTake then - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn off repeat + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn off repeat InsertNotes() m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence seqShiftVal.label = tostring(m.seqShift) @@ -1960,7 +1970,33 @@ function SetDefaultSeqShift() m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) end --- Reset sequence shifter state +-- Reset sequence shifter +function ResetSeqShifter() + local debug = false + if debug or m.debug then ConMsg("ResetSeqShifter()") end + + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 + seqShiftVal.label = tostring(m.seqShift) + if debug or m.debug then + ConMsg("Reset m.seqShift, m.seqShiftMin, m.seqShiftMax to 0") + ConMsg("Reset shifter label to m.seqShift") + end + InsertNotes() +end +-- Glue sequence shifter +function GlueSeqShifter() + local debug = false + if debug or m.debug then ConMsg("GlueSeqShifter()") end + if debug or m.debug then ConMsg("TBC...") end + m.shiftGlueF = true + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn off repeat + InsertNotes() + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence + seqShiftVal.label = tostring(m.seqShift) + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn on repeat + InsertNotes() +end +-- Right-click handler seqShiftText.onRClick = function() local debug = false if debug or m.debug then ConMsg("\nseqShiftText.onRClick") end @@ -1969,9 +2005,9 @@ seqShiftText.onRClick = function() local result = gfx.showmenu("Reset Note Shift|Glue Shift") if result == 1 then - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 - seqShiftVal.label = tostring(m.seqShift) - InsertNotes() + ResetSeqShifter() + elseif result == 2 then + GlueSeqShifter() end -- result end -- Sequence shifter left @@ -2056,6 +2092,48 @@ function SetDefaultSeqRepeat() end end -- Reset sequencer repeater +function ResetSeqRepeater() + local debug = false + if debug or m.debug then ConMsg("ResetSeqRepeater()") end + -- reset the GUI and repeat flag + m.seqRepeatF = false + seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 + seqOptionsCb.onLClick() -- why ??? + -- reset the drop down lists and clear pExtState + seqLoopStartDrop.val1 = 1; m.loopStartG = 1 + -- reset the program ext state + if pExtState.loopStartG then pExtState.loopStartG = nil end + seqLoopLenDrop.val1 = 1; m.loopLenG = 1 + if pExtState.loopLenG then pExtState.loopLenG = nil end + seqLoopNumDrop.val1 = 1; m.loopNum = 1 + if pExtState.loopNum then pExtState.loopNum = nil end + pExtSaveStateF = true -- set the ext state save flag + InsertNotes() +end +-- Glue sequencer repeater +function GlueSeqRepeater() + local debug = false + if debug or m.debug then ConMsg("GlueSeqRepeater()") end + m.loopGlueF = true + InsertNotes() + -- reset the GUI and repeat flag + m.seqRepeatF = false + seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 + seqOptionsCb.onLClick() + -- reset the drop down lists and pExtState + seqLoopStartDrop.val1 = 1; m.loopStartG = 1 + -- reset the shifter (implicit when glueing the loop) + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 + seqShiftVal.label = tostring(m.seqShift) + -- reset the program ext state + if pExtState.loopStartG then pExtState.loopStartG = nil end + seqLoopLenDrop.val1 = 1; m.loopLenG = 1 + if pExtState.loopLenG then pExtState.loopLenG = nil end + seqLoopNumDrop.val1 = 1; m.loopNum = 1 + if pExtState.loopNum then pExtState.loopNum = nil end + pExtSaveStateF = true -- set the ext state save flag +end +-- Right-click handler seqLoopText.onRClick = function() local debug = false if debug or m.debug then ConMsg("\nseqLoopText.onRClick") end @@ -2064,35 +2142,9 @@ seqLoopText.onRClick = function() local result = gfx.showmenu("Reset Repeat|Glue Repeat") if result == 1 then - -- reset the GUI and repeat flag - m.seqRepeatF = false - seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 - seqOptionsCb.onLClick() - -- reset the drop down lists and clear pExtState - seqLoopStartDrop.val1 = 1; m.loopStartG = 1 - if pExtState.loopStartG then pExtState.loopStartG = nil end - seqLoopLenDrop.val1 = 1; m.loopLenG = 1 - if pExtState.loopLenG then pExtState.loopLenG = nil end - seqLoopNumDrop.val1 = 1; m.loopNum = 1 - if pExtState.loopNum then pExtState.loopNum = nil end - pExtSaveStateF = true -- set the ext state save flag - InsertNotes() - + ResetSeqRepeater() elseif result == 2 then - m.loopGlueF = true - InsertNotes() - -- reset the GUI and repeat flag - m.seqRepeatF = false - seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 - seqOptionsCb.onLClick() - -- reset the drop down lists and pExtState - seqLoopStartDrop.val1 = 1; m.loopStartG = 1 - if pExtState.loopStartG then pExtState.loopStartG = nil end - seqLoopLenDrop.val1 = 1; m.loopLenG = 1 - if pExtState.loopLenG then pExtState.loopLenG = nil end - seqLoopNumDrop.val1 = 1; m.loopNum = 1 - if pExtState.loopNum then pExtState.loopNum = nil end - pExtSaveStateF = true -- set the ext state save flag + GlueSeqRepeater() end -- result end -- onRClick @@ -2479,13 +2531,7 @@ function MainLoop() Shift = gfx.mouse_cap & 8 == 8 Alt = gfx.mouse_cap & 16 == 16 - -- Check and save window position - __, pExtState.win_x, pExtState.win_y, __, __ = gfx.dock(-1,0,0,0,0) - if m.win_x ~= pExtState.win_x or m.win_y ~= pExtState.win_y then - m.win_x = pExtState.win_x - m.win_y = pExtState.win_y - pExtSaveStateF = true - end + -- if resized, set scale flag and reset gfx if m.zoomF == true then if debug or m.debug then ConMsg("m.zoomF == true") end @@ -2511,8 +2557,17 @@ function MainLoop() if char ~= -1 and char ~= 27 then reaper.defer(MainLoop) else - -- reset the shifter and repeater - -- add code here... + -- reset the shifter and repeater here... + ResetSeqRepeater() + ResetSeqShifter() + -- Check and save window position + __, pExtState.win_x, pExtState.win_y, __, __ = gfx.dock(-1,0,0,0,0) + if m.win_x ~= pExtState.win_x or m.win_y ~= pExtState.win_y then + m.win_x = pExtState.win_x + m.win_y = pExtState.win_y + pExtSaveStateF = true + end + if pExtSaveStateF then -- quiting, save script state pExtStateStr = pickle(pExtState) reaper.SetProjExtState(0, "MEM", "pExtState", pExtStateStr ) From b34120e95906cfe4a9225c5fc2df49ef5be7b1e3 Mon Sep 17 00:00:00 2001 From: RobU Date: Sun, 28 May 2017 21:50:22 +0100 Subject: [PATCH 15/33] move repeater to separate function rework repeater and shifter glue functions --- .../RobU - MIDI Ex Machina.lua | 265 +++++++++--------- 1 file changed, 137 insertions(+), 128 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 8a706cb..7f0ae4a 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -939,6 +939,110 @@ function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) InsertNotes() end -------------------------------------------------------------------------------- +-- SeqRepeater() - repeat a range of notes x times +-------------------------------------------------------------------------------- +function SeqRepeater(t1) + local debug = false + if debug or m.debug then ConMsg("SeqRepeater()") end + + local gridSize = math.floor(m.reaGrid * m.ppqn) + local itemLenP = GetItemLength() + local t2 = nil + + -- note repeater + if m.loopGlueF then + if debug or m.debug then ConMsg("Repeater glued...") end + t2 = NewNoteBuf() -- new buffer for repeating + m.loopGlueF = false + else + if debug or m.debug then ConMsg("Repeater not glued...") end + t2 = {} -- temp table for repeating + end + + local loopStartP = (m.loopStartG -1) * gridSize + local loopLenP = m.loopLenG * gridSize + local loopEndP = loopStartP + loopLenP + local loopNum = m.loopNum + local i = 1 + local writeOffP = 0 + if loopStartP > 0 then writeOffP = -loopStartP else writeOffP = 0 end + + -- pre-repeat + if debug or m.debug then ConMsg("pre repeat ...") end + for k, v in pairs(t1) do + if v[3] >= 0 and v[3] < loopStartP then + t2[i] = {} + t2[i][1] = v[1] -- selected + t2[i][2] = v[2] -- muted + t2[i][3] = v[3] -- startppqn + t2[i][4] = v[4] -- endppqn + if not t2[i][9] then t2[i][4] = t2[i][4] - m.legato end -- handle legatolessness + t2[i][5] = v[5] -- length + t2[i][6] = v[6] -- channel + t2[i][7] = v[7] -- pitch + t2[i][8] = v[8] -- vel + t2[i][9] = v[9] -- legato + reaper.MIDI_InsertNote(m.activeTake, t2[i][1], t2[i][2], t2[i][3], t2[i][4], t2[i][6], t2[i][7], t2[i][8], false) + i = i + 1 + end + end -- k, v in pairs(t1) - pre-repeat + writeOffP = writeOffP + loopStartP + + -- repeat + if debug or m.debug then ConMsg("repeat ...") end + while loopNum > 0 do + for k, v in pairs(t1) do + if v[3] >= loopStartP and v[3] < loopEndP then + t2[i] = {} + t2[i][1] = v[1] -- selected + t2[i][2] = v[2] -- muted + t2[i][3] = v[3] + writeOffP -- startppqn + if v[4] > loopEndP then t2[i][4] = loopEndP + writeOffP else t2[i][4] = v[4] + writeOffP end -- endppqn + if not t2[i][9] then t2[i][4] = t2[i][4] - m.legato end -- handle legatolessness + t2[i][5] = v[5] -- length + t2[i][6] = v[6] -- channel + t2[i][7] = v[7] -- pitch + t2[i][8] = v[8] -- vel + t2[i][9] = v[9] -- legato + reaper.MIDI_InsertNote(m.activeTake, t2[i][1], t2[i][2], t2[i][3], t2[i][4], t2[i][6], t2[i][7], t2[i][8], false) + i = i + 1 + end -- if v[3] + + end -- for k, v t1 - repeat + loopNum = loopNum - 1 + writeOffP = writeOffP + loopLenP + end -- while loopNum > 0 + + -- post-repeat + if debug or m.debug then ConMsg("post repeat ...") end + local written = loopStartP + (loopLenP * m.loopNum) + local remLenP = itemLenP - written + local readStartP = loopStartP + loopLenP + local readEndP = readStartP + remLenP + local writeOffP = written - readStartP + + for k, v in pairs(t1) do + if v[3] >= readStartP and v[3] < readEndP then + t2[i] = {} + t2[i][1] = v[1] -- selected + t2[i][2] = v[2] -- muted + t2[i][3] = v[3] + writeOffP -- startppqn + if v[4] > itemLenP then t2[i][4] = itemLenP else t2[i][4] = v[4] + writeOffP end -- endppqn + if not t2[i][9] then t2[i][4] = t2[i][4] - m.legato end -- handle legatolessness + t2[i][5] = v[5] -- channel + t2[i][6] = v[6] -- channel + t2[i][7] = v[7] -- pitch + t2[i][8] = v[8] -- vel + t2[i][9] = v[9] -- legato + reaper.MIDI_InsertNote(m.activeTake, t2[i][1], t2[i][2], t2[i][3], t2[i][4], t2[i][6], t2[i][7], t2[i][8], false) + i = i + 1 + end + end -- k, v in pairs(t1) - post-repeat + + return t2 + +end +-------------------------------------------------------------------------------- -- InsertNotes() - insert current note buffer in the active take -------------------------------------------------------------------------------- function InsertNotes() @@ -948,146 +1052,48 @@ function InsertNotes() local gridSize = math.floor(m.reaGrid * m.ppqn) local itemLenP = GetItemLength() local noteShift = math.floor(m.seqShift * gridSize) - local t1, t2, t3, t4 = GetNoteBuf(), nil, nil, nil + local t1, t2, t3 = GetNoteBuf(), nil, nil -- note shifter - if debug or m.debug then ConMsg("Not glueing shifter...") end - t2 = {} -- temp table for note shifter (no undo) + if m.shiftGlueF then + if debug or m.debug then ConMsg("Shifter glued ...") end + t2 = NewNoteBuf() -- new note buffer for glueing + m.shiftGlueF = false + else + if debug or m.debug then ConMsg("Shifter not glued ...") end + t2 = {} -- temp table for note shifter (no undo) + end + CopyTable(t1, t2) for k, v in pairs(t2) do v[3] = v[3] + noteShift v[4] = v[4] + noteShift - if v[3] < 0 then v[3] = itemLenP + v[3] v[4] = itemLenP + v[4] if v[4] > itemLenP then v[4] = itemLenP end - elseif v[3] >= itemLenP then v[3] = v[3] - itemLenP v[4] = v[4] - itemLenP end end -- for k, v t2 - -- note repeater - if m.seqRepeatF then - if debug or m.debug then ConMsg("Repeating...") end - DeleteNotes() - t3 = {} -- temp table for note repeater (for glueing) - local loopStartP = (m.loopStartG -1) * gridSize - local loopLenP = m.loopLenG * gridSize - local loopEndP = loopStartP + loopLenP - local loopNum = m.loopNum - local i = 1 - local writeOffP = 0 - if loopStartP > 0 then writeOffP = -loopStartP else writeOffP = 0 end - - -- pre-repeat - for k, v in pairs(t2) do - if v[3] >= 0 and v[3] < loopStartP then - t3[i] = {} - t3[i][1] = v[1] -- selected - t3[i][2] = v[2] -- muted - t3[i][3] = v[3] -- startppqn - t3[i][4] = v[4] -- endppqn - if not t3[i][9] then t3[i][4] = t3[i][4] - m.legato end -- handle legatolessness - t3[i][5] = v[5] -- length - t3[i][6] = v[6] -- channel - t3[i][7] = v[7] -- pitch - t3[i][8] = v[8] -- vel - t3[i][9] = v[9] -- legato - reaper.MIDI_InsertNote(m.activeTake, t3[i][1], t3[i][2], t3[i][3], t3[i][4], t3[i][6], t3[i][7], t3[i][8], false) - i = i + 1 - end - end -- k, v in pairs(t2) - pre-repeat - writeOffP = writeOffP + loopStartP - - -- repeat - while loopNum > 0 do - for k, v in pairs(t2) do - if v[3] >= loopStartP and v[3] < loopEndP then - t3[i] = {} - t3[i][1] = v[1] -- selected - t3[i][2] = v[2] -- muted - t3[i][3] = v[3] + writeOffP -- startppqn - if v[4] > loopEndP then t3[i][4] = loopEndP + writeOffP else t3[i][4] = v[4] + writeOffP end -- endppqn - if not t3[i][9] then t3[i][4] = t3[i][4] - m.legato end -- handle legatolessness - t3[i][5] = v[5] -- length - t3[i][6] = v[6] -- channel - t3[i][7] = v[7] -- pitch - t3[i][8] = v[8] -- vel - t3[i][9] = v[9] -- legato - reaper.MIDI_InsertNote(m.activeTake, t3[i][1], t3[i][2], t3[i][3], t3[i][4], t3[i][6], t3[i][7], t3[i][8], false) - i = i + 1 - end -- if v[3] - - end -- for k, v t3 - repeat - loopNum = loopNum - 1 - writeOffP = writeOffP + loopLenP - end -- while loopNum > 0 - - -- post-repeat - local written = loopStartP + (loopLenP * m.loopNum) - local remLenP = itemLenP - written - local readStartP = loopStartP + loopLenP - local readEndP = readStartP + remLenP - local writeOffP = written - readStartP - - for k, v in pairs(t2) do - if v[3] >= readStartP and v[3] < readEndP then - t3[i] = {} - t3[i][1] = v[1] -- selected - t3[i][2] = v[2] -- muted - t3[i][3] = v[3] + writeOffP -- startppqn - if v[4] > itemLenP then t3[i][4] = itemLenP else t3[i][4] = v[4] + writeOffP end -- endppqn - if not t3[i][9] then t3[i][4] = t3[i][4] - m.legato end -- handle legatolessness - t3[i][5] = v[5] -- channel - t3[i][6] = v[6] -- channel - t3[i][7] = v[7] -- pitch - t3[i][8] = v[8] -- vel - t3[i][9] = v[9] -- legato - reaper.MIDI_InsertNote(m.activeTake, t3[i][1], t3[i][2], t3[i][3], t3[i][4], t3[i][6], t3[i][7], t3[i][8], false) - i = i + 1 - end - end -- k, v in pairs(t2) - post-repeat - - reaper.MIDI_Sort(m.activeTake) - reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off - - else -- not m.seqRepeatF - if debug or m.debug then ConMsg("No repeat...") end - DeleteNotes() - - if m.loopGlueF then - if debug or m.debug then ConMsg("Glueing repeater...") end - t4 = NewNoteBuf(); CopyTable(t3, t4) - if debug and m.debug then PrintNotes(t4) end - for k, v in pairs(t4) do - reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) - m.loopGlueF = false - end - - else -- not glueing repeater - if debug or m.debug then ConMsg("no glueing repeater, inserting shift table (t2)") end - for k, v in pairs(t2) do -- use the post-shifter table - if not v[9] then v[4] = v[4] - m.legato end -- handle legatolessness - reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) - end -- for k, v t2 - end -- m.loopGlueF - - reaper.MIDI_Sort(m.activeTake) - reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off - end -- m.seqRepeatF - - if m.shiftGlueF then - -- glue using t2 and new note buf - elseif m.loopGlueF then - -- glue using t3 and new note buf - else -- no glueing going on - end - + if m.seqRepeatF then + t3 = SeqRepeater(t2) + else + t3 = {}; CopyTable(t2, t3) + end + + DeleteNotes() + for k, v in pairs(t3) do + if not v[9] then v[4] = v[4] - m.legato end -- handle legatolessness + reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) + end -- for k, v t3 + reaper.MIDI_Sort(m.activeTake) + reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off + end -------------------------------------------------------------------------------- -- PrintNotes - arg note_buffer t; print note_buffer to reaper console @@ -1987,14 +1993,13 @@ end function GlueSeqShifter() local debug = false if debug or m.debug then ConMsg("GlueSeqShifter()") end - if debug or m.debug then ConMsg("TBC...") end m.shiftGlueF = true m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn off repeat InsertNotes() m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence seqShiftVal.label = tostring(m.seqShift) m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn on repeat - InsertNotes() + InsertNotes() end -- Right-click handler seqShiftText.onRClick = function() @@ -2114,17 +2119,21 @@ end function GlueSeqRepeater() local debug = false if debug or m.debug then ConMsg("GlueSeqRepeater()") end - m.loopGlueF = true + m.loopGlueF = true InsertNotes() + + -- reset the shifter (implicit when glueing the loop) + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 + seqShiftVal.label = tostring(m.seqShift) + -- reset the GUI and repeat flag m.seqRepeatF = false seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 seqOptionsCb.onLClick() + -- reset the drop down lists and pExtState seqLoopStartDrop.val1 = 1; m.loopStartG = 1 - -- reset the shifter (implicit when glueing the loop) - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 - seqShiftVal.label = tostring(m.seqShift) + -- reset the program ext state if pExtState.loopStartG then pExtState.loopStartG = nil end seqLoopLenDrop.val1 = 1; m.loopLenG = 1 From 54eed216b6f9d578c6ceeb57088cc261df8c9bd0 Mon Sep 17 00:00:00 2001 From: RobU Date: Sun, 28 May 2017 23:07:36 +0100 Subject: [PATCH 16/33] start of reflow - see notes... --- .../RobU - MIDI Ex Machina.lua | 163 ++++++++++-------- 1 file changed, 91 insertions(+), 72 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 7f0ae4a..d1d1fd6 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -755,6 +755,7 @@ function RandomiseNotesPoly(noteProbTable) local i = 1 local t1, t2 = GetNoteBuf(), NewNoteBuf() CopyTable(t1, t2) + if debug and m.debug then PrintNotes(t1) end while t2[i] do @@ -1476,25 +1477,39 @@ end randomBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nrandomBtn.onLClick()") end + if not m.activeTake then return end + + -- backup and turn off shift + local t_shift = table.pack(m.seqShift, m.seqShiftMin, m.seqShiftMax) + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift + seqShiftVal.label = tostring(m.seqShift) + + -- turn off repeat + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false + + GenProbTable(m.preNoteProbTable, t_noteSliders, m.noteProbTable) + if #m.noteProbTable == 0 then return end + GenOctaveTable(m.octProbTable, octProbSldr) + GetNotesFromTake() + RandomiseNotesPoly(m.noteProbTable) + + -- restore and turn shift back on + m.seqShift, m.seqShiftMin, m.seqShiftMax = table.unpack(t_shift) + seqShiftVal.label = tostring(m.seqShift) + -- turn on repeat + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false + InsertNotes() + + -- set project ext state + pExtState.noteSliders = {} + + for k, v in pairs(t_noteSliders) do + pExtState.noteSliders[k] = v.val1 + end + + pExtState.rndOctProb = octProbSldr.val1 + pExtSaveStateF = true - if m.activeTake then - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift - seqShiftVal.label = tostring(m.seqShift) - GenProbTable(m.preNoteProbTable, t_noteSliders, m.noteProbTable) - if #m.noteProbTable == 0 then return end - GenOctaveTable(m.octProbTable, octProbSldr) - GetNotesFromTake() - RandomiseNotesPoly(m.noteProbTable) - -- set project ext state - pExtState.noteSliders = {} - - for k, v in pairs(t_noteSliders) do - pExtState.noteSliders[k] = v.val1 - end - - pExtState.rndOctProb = octProbSldr.val1 - pExtSaveStateF = true - end --m.activeTake end -- Set randomiser default options @@ -1667,66 +1682,70 @@ end sequenceBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nsequenceBtn.onLClick()") end + if not m.activeTake then return end - if m.activeTake then - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn off repeat - InsertNotes() - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence - seqShiftVal.label = tostring(m.seqShift) - - if m.seqF then - SetSeqGridSizes(t_seqSliders) - GenProbTable(m.preSeqProbTable, t_seqSliders, m.seqProbTable) - GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) - GenLegatoTable(m.legProbTable, seqLegProbSldr) - GetNotesFromTake() - GenSequence(m.seqProbTable, m.accProbTable, seqAccRSldr, m.legProbTable) - if m.seqRndNotesF then - randomBtn.onLClick() -- call RandomiseNotes - end - - else -- not m.seqF - GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) - GenLegatoTable(m.legProbTable, seqLegProbSldr) - GetNotesFromTake() - GenNoteAttributes(m.seqAccentF, m.accProbTable, seqAccRSldr, m.seqLegatoF, m.legProbTable) - - if m.seqRndNotesF then - randomBtn.onLClick() -- call RandomiseNotes - end - end -- m.seqF + -- backup and turn off shift + local t_shift = table.pack(m.seqShift, m.seqShiftMin, m.seqShiftMax) + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence + seqShiftVal.label = tostring(m.seqShift) + -- turn off repeat + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false + InsertNotes() + + if m.seqF then + SetSeqGridSizes(t_seqSliders) + GenProbTable(m.preSeqProbTable, t_seqSliders, m.seqProbTable) + GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) + GenLegatoTable(m.legProbTable, seqLegProbSldr) + GetNotesFromTake() + GenSequence(m.seqProbTable, m.accProbTable, seqAccRSldr, m.legProbTable) + + else -- not m.seqF + GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) + GenLegatoTable(m.legProbTable, seqLegProbSldr) + GetNotesFromTake() + GenNoteAttributes(m.seqAccentF, m.accProbTable, seqAccRSldr, m.seqLegatoF, m.legProbTable) - -- set project ext state - if seqGridRad.val1 == 1 then -- 1/16 grid - pExtState.seqGrid16 = {} - for k, v in pairs (t_seqSliders) do - pExtState.seqGrid16[k] = v.val1 - end + -- restore and turn shift back on + m.seqShift, m.seqShiftMin, m.seqShiftMax = table.unpack(t_shift) + seqShiftVal.label = tostring(m.seqShift) + InsertNotes() + end -- m.seqF + + -- turn on repeat + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false + + if m.seqRndNotesF then + randomBtn.onLClick() -- call RandomiseNotes + end + + -- set project ext state + if seqGridRad.val1 == 1 then -- 1/16 grid + pExtState.seqGrid16 = {} + for k, v in pairs (t_seqSliders) do + pExtState.seqGrid16[k] = v.val1 end - - if seqGridRad.val1 == 2 then -- 1/8 grid - pExtState.seqGrid8 = {} - for k, v in pairs (t_seqSliders) do - pExtState.seqGrid8[k] = v.val1 - end + end + + if seqGridRad.val1 == 2 then -- 1/8 grid + pExtState.seqGrid8 = {} + for k, v in pairs (t_seqSliders) do + pExtState.seqGrid8[k] = v.val1 end - - if seqGridRad.val1 == 3 then -- 1/4 grid - pExtState.seqGrid4 = {} - for k, v in pairs (t_seqSliders) do - pExtState.seqGrid4[k] = v.val1 - end + end + + if seqGridRad.val1 == 3 then -- 1/4 grid + pExtState.seqGrid4 = {} + for k, v in pairs (t_seqSliders) do + pExtState.seqGrid4[k] = v.val1 end + end - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn on repeat - InsertNotes() - pExtState.seqAccRSldrLo = seqAccRSldr.val1 - pExtState.seqAccRSldrHi = seqAccRSldr.val2 - pExtState.seqAccProb = seqAccProbSldr.val1 - pExtState.seqLegProb = seqLegProbSldr.val1 - - pExtSaveStateF = true - end --m.activeTake + pExtState.seqAccRSldrLo = seqAccRSldr.val1 + pExtState.seqAccRSldrHi = seqAccRSldr.val2 + pExtState.seqAccProb = seqAccProbSldr.val1 + pExtState.seqLegProb = seqLegProbSldr.val1 + pExtSaveStateF = true end -- Set sequencer options defaults From 0defbccefdee4016f4622d2e717340dfe3450986 Mon Sep 17 00:00:00 2001 From: RobU23 Date: Sat, 3 Jun 2017 22:40:47 +0100 Subject: [PATCH 17/33] shifter to separate function removed unnecessary calls to get buffer remove pextstate for shifter and repeater --- .../RobU - MIDI Ex Machina.lua | 149 ++++++++---------- 1 file changed, 65 insertions(+), 84 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index d1d1fd6..043099a 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -106,7 +106,8 @@ m.seqFirstNoteF = true -- first note always (option) m.seqAccentF = true -- generate accents (option) m.seqLegatoF = false -- use legato (option) m.seqRndNotesF = true -- randomise notes (option) -m.seqRepeatF = false -- repeat sequence by grid length (option - not implemented yet) +m.seqRepeatF = false -- repeat sequence by grid length +m.seqShiftF = false -- shift sequence by grid length m.legato = 10 -- default legatolessness value m.legQ = 240 m.accentLow = 100; m.accentHigh = 127; m.accentProb = 3 -- default values (options) @@ -501,7 +502,7 @@ function GetNotesFromTake() local i, t if m.activeTake then local _retval, num_notes, num_cc, num_sysex = reaper.MIDI_CountEvts(m.activeTake) - if num_notes > 0 then + if num_notes > 0 then t = GetNoteBuf(); if t == nil then t = NewNoteBuf() end local div, rem, noteLen ClearTable(t) @@ -525,6 +526,7 @@ function GetNotesFromTake() end -- for i end -- num_notes if debug and m.debug then PrintNotes(t) end + return t else -- no active take if debug or m.debug then ConMsg("No Active Take") end end -- m.activeTake @@ -807,7 +809,6 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) if newNote == -1 then itemPos = itemPos + gridSize restCount = restCount + 1 - else noteStart = itemPos noteLen = newNote * m.ppqn @@ -853,10 +854,8 @@ function GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) if debug or m.debug then ConMsg("GenBjorklund()") end local floor = math.floor - local t, t2 = NewNoteBuf(), GetNoteBuf() - CopyTable(t2, t) + local t = NewNoteBuf() GetReaperGrid() -- populates m.reaGrid - --t = GetNoteBuf(); if t == nil then t = NewNoteBuf() end -- pre-undo ClearTable(t) local itemPos = 0 local gridSize = m.reaGrid * m.ppqn @@ -939,6 +938,45 @@ function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) PurgeNoteBuf() InsertNotes() end + +-------------------------------------------------------------------------------- +-- SeqShifter() - shift notes left / right +-------------------------------------------------------------------------------- +function SeqShifter(t1) + local debug = false + if debug or m.debug then ConMsg("SeqShifter()") end + + local gridSize = math.floor(m.reaGrid * m.ppqn) + local itemLenP = GetItemLength() + local noteShift = math.floor(m.seqShift * gridSize) + local t2 = nil + + -- note shifter + if m.shiftGlueF then + if debug or m.debug then ConMsg("Shifter glued ...") end + t2 = NewNoteBuf() -- new note buffer for glueing + m.shiftGlueF = false + else + if debug or m.debug then ConMsg("Shifter not glued ...") end + t2 = {} -- temp table for note shifter (no undo) + end + + CopyTable(t1, t2) + for k, v in pairs(t2) do + v[3] = v[3] + noteShift + v[4] = v[4] + noteShift + if v[3] < 0 then + v[3] = itemLenP + v[3] + v[4] = itemLenP + v[4] + if v[4] > itemLenP then v[4] = itemLenP end + elseif v[3] >= itemLenP then + v[3] = v[3] - itemLenP + v[4] = v[4] - itemLenP + end + end -- for k, v t2 + + return t2 +end -------------------------------------------------------------------------------- -- SeqRepeater() - repeat a range of notes x times -------------------------------------------------------------------------------- @@ -1050,35 +1088,15 @@ function InsertNotes() local debug = false if debug or m.debug then ConMsg("InsertNotes()") end - local gridSize = math.floor(m.reaGrid * m.ppqn) - local itemLenP = GetItemLength() - local noteShift = math.floor(m.seqShift * gridSize) local t1, t2, t3 = GetNoteBuf(), nil, nil -- note shifter - if m.shiftGlueF then - if debug or m.debug then ConMsg("Shifter glued ...") end - t2 = NewNoteBuf() -- new note buffer for glueing - m.shiftGlueF = false + if m.seqShiftF then + t2 = SeqShifter(t1) else - if debug or m.debug then ConMsg("Shifter not glued ...") end - t2 = {} -- temp table for note shifter (no undo) + t2 = {}; CopyTable(t1, t2) end - CopyTable(t1, t2) - for k, v in pairs(t2) do - v[3] = v[3] + noteShift - v[4] = v[4] + noteShift - if v[3] < 0 then - v[3] = itemLenP + v[3] - v[4] = itemLenP + v[4] - if v[4] > itemLenP then v[4] = itemLenP end - elseif v[3] >= itemLenP then - v[3] = v[3] - itemLenP - v[4] = v[4] - itemLenP - end - end -- for k, v t2 - -- note repeater if m.seqRepeatF then t3 = SeqRepeater(t2) @@ -1490,7 +1508,7 @@ randomBtn.onLClick = function() GenProbTable(m.preNoteProbTable, t_noteSliders, m.noteProbTable) if #m.noteProbTable == 0 then return end GenOctaveTable(m.octProbTable, octProbSldr) - GetNotesFromTake() + GetNotesFromTake() RandomiseNotesPoly(m.noteProbTable) -- restore and turn shift back on @@ -1502,14 +1520,11 @@ randomBtn.onLClick = function() -- set project ext state pExtState.noteSliders = {} - for k, v in pairs(t_noteSliders) do pExtState.noteSliders[k] = v.val1 end - pExtState.rndOctProb = octProbSldr.val1 pExtSaveStateF = true - end -- Set randomiser default options @@ -1726,21 +1741,18 @@ sequenceBtn.onLClick = function() pExtState.seqGrid16[k] = v.val1 end end - if seqGridRad.val1 == 2 then -- 1/8 grid pExtState.seqGrid8 = {} for k, v in pairs (t_seqSliders) do pExtState.seqGrid8[k] = v.val1 end end - if seqGridRad.val1 == 3 then -- 1/4 grid pExtState.seqGrid4 = {} for k, v in pairs (t_seqSliders) do pExtState.seqGrid4[k] = v.val1 end - end - + end pExtState.seqAccRSldrLo = seqAccRSldr.val1 pExtState.seqAccRSldrHi = seqAccRSldr.val2 pExtState.seqAccProb = seqAccProbSldr.val1 @@ -2002,6 +2014,7 @@ function ResetSeqShifter() m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) + m.seqShiftF = false if debug or m.debug then ConMsg("Reset m.seqShift, m.seqShiftMin, m.seqShiftMax to 0") ConMsg("Reset shifter label to m.seqShift") @@ -2017,6 +2030,7 @@ function GlueSeqShifter() InsertNotes() m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence seqShiftVal.label = tostring(m.seqShift) + m.seqShiftF = false m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn on repeat InsertNotes() end @@ -2045,8 +2059,10 @@ seqShiftLBtn.onLClick = function() if m.seqShift <= m.seqShiftMin then m.seqShift = 0 + m.seqShiftF = false else m.seqShift = m.seqShift - 1 + m.seqShiftF = true end seqShiftVal.label = tostring(m.seqShift) @@ -2063,8 +2079,10 @@ seqShiftRBtn.onLClick = function() if m.seqShift >= m.seqShiftMax then m.seqShift = 0 + m.seqShiftF = false else m.seqShift = m.seqShift + 1 + m.seqShiftF = true end seqShiftVal.label = tostring(m.seqShift) @@ -2081,33 +2099,18 @@ function SetDefaultSeqRepeat() local itemLength = GetItemLength() -- start - if pExtState.loopStartG then - m.loopStartG = pExtState.loopStartG - seqLoopStartDrop.val1 = m.loopStartG - else m.loopStartG = 1 - seqLoopStartDrop.val1 = m.loopStartG - end + seqLoopStartDrop.val1 = m.loopStartG -- length - if pExtState.loopLenG then - m.loopLenG = pExtState.loopLenG - seqLoopLenDrop.val1 = m.loopLenG - else m.loopLenG = 1 - seqLoopLenDrop.val1 = m.loopLenG - end + seqLoopLenDrop.val1 = m.loopLenG -- amount - if pExtState.loopNum then - m.loopNum = pExtState.loopNum - seqLoopNumDrop.val1 = m.loopNum - else m.loopNum = 1 - seqLoopNumDrop.val1 = m.loopNum - end + seqLoopNumDrop.val1 = m.loopNum - m.loopMaxRep = math.floor(itemLength / gridSize) + m.loopMaxRep = math.floor(itemLength / gridSize) for i = 1, m.loopMaxRep do seqLoopStartDrop.val2[i] = i @@ -2122,16 +2125,11 @@ function ResetSeqRepeater() -- reset the GUI and repeat flag m.seqRepeatF = false seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 - seqOptionsCb.onLClick() -- why ??? - -- reset the drop down lists and clear pExtState + seqOptionsCb.onLClick() -- will insert notes from the last buffer if necessary + -- reset the drop down lists seqLoopStartDrop.val1 = 1; m.loopStartG = 1 - -- reset the program ext state - if pExtState.loopStartG then pExtState.loopStartG = nil end seqLoopLenDrop.val1 = 1; m.loopLenG = 1 - if pExtState.loopLenG then pExtState.loopLenG = nil end seqLoopNumDrop.val1 = 1; m.loopNum = 1 - if pExtState.loopNum then pExtState.loopNum = nil end - pExtSaveStateF = true -- set the ext state save flag InsertNotes() end -- Glue sequencer repeater @@ -2154,12 +2152,12 @@ function GlueSeqRepeater() seqLoopStartDrop.val1 = 1; m.loopStartG = 1 -- reset the program ext state - if pExtState.loopStartG then pExtState.loopStartG = nil end + --if pExtState.loopStartG then pExtState.loopStartG = nil end seqLoopLenDrop.val1 = 1; m.loopLenG = 1 - if pExtState.loopLenG then pExtState.loopLenG = nil end + --if pExtState.loopLenG then pExtState.loopLenG = nil end seqLoopNumDrop.val1 = 1; m.loopNum = 1 - if pExtState.loopNum then pExtState.loopNum = nil end - pExtSaveStateF = true -- set the ext state save flag + --if pExtState.loopNum then pExtState.loopNum = nil end + --pExtSaveStateF = true -- set the ext state save flag end -- Right-click handler seqLoopText.onRClick = function() @@ -2223,10 +2221,6 @@ seqLoopStartDrop.onLClick = function() if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end - -- set project ext state - --pExtState.oct = m.oct - --pExtState.root = m.root - --pExtSaveStateF = true end -- Sequencer repeat length seqLoopLenDrop.onLClick = function() @@ -2267,11 +2261,6 @@ seqLoopLenDrop.onLClick = function() if debug or m.debug then ConMsg("m.loopStartG = " .. tostring(m.t_loopStart[m.loopStartG])) end if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end - - -- set project ext state - --pExtState.oct = m.oct - --pExtState.root = m.root - --pExtSaveStateF = true end -- Sequencer repeat amount seqLoopNumDrop.onLClick = function() @@ -2304,11 +2293,6 @@ seqLoopNumDrop.onLClick = function() if debug or m.debug then ConMsg("m.loopStartG = " .. tostring(m.t_loopStart[m.loopStartG])) end if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end - - -- set project ext state - --pExtState.oct = m.oct - --pExtState.root = m.root - --pExtSaveStateF = true end -------------------------------------------------------------------------------- @@ -2518,8 +2502,6 @@ function InitMidiExMachina() end -- pExtStateStr end -- pExtLoadStateF - - -- set GUI defaults or restore from project state SetDefaultWindowOpts(); SetDefaultLayer() SetDefaultScaleOpts() @@ -2559,7 +2541,6 @@ function MainLoop() Shift = gfx.mouse_cap & 8 == 8 Alt = gfx.mouse_cap & 16 == 16 - -- if resized, set scale flag and reset gfx if m.zoomF == true then if debug or m.debug then ConMsg("m.zoomF == true") end From 47a38eefae181efc90ee5a5eb1314871b9ae9735 Mon Sep 17 00:00:00 2001 From: RobU Date: Sun, 4 Jun 2017 11:29:46 +0100 Subject: [PATCH 18/33] moved main button code below all other functions --- .../RobU - MIDI Ex Machina.lua | 276 +++++++++--------- 1 file changed, 136 insertions(+), 140 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 043099a..f2f18aa 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -1491,42 +1491,6 @@ end -------------------------------------------------------------------------------- -- Note Randomiser -------------------------------------------------------------------------------- --- Randomiser button -randomBtn.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\nrandomBtn.onLClick()") end - if not m.activeTake then return end - - -- backup and turn off shift - local t_shift = table.pack(m.seqShift, m.seqShiftMin, m.seqShiftMax) - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift - seqShiftVal.label = tostring(m.seqShift) - - -- turn off repeat - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false - - GenProbTable(m.preNoteProbTable, t_noteSliders, m.noteProbTable) - if #m.noteProbTable == 0 then return end - GenOctaveTable(m.octProbTable, octProbSldr) - GetNotesFromTake() - RandomiseNotesPoly(m.noteProbTable) - - -- restore and turn shift back on - m.seqShift, m.seqShiftMin, m.seqShiftMax = table.unpack(t_shift) - seqShiftVal.label = tostring(m.seqShift) - -- turn on repeat - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false - InsertNotes() - - -- set project ext state - pExtState.noteSliders = {} - for k, v in pairs(t_noteSliders) do - pExtState.noteSliders[k] = v.val1 - end - pExtState.rndOctProb = octProbSldr.val1 - pExtSaveStateF = true -end - -- Set randomiser default options function SetDefaultRndOptions() local debug = false @@ -1693,73 +1657,6 @@ end -------------------------------------------------------------------------------- -- Sequencer -------------------------------------------------------------------------------- --- Sequencer button -sequenceBtn.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\nsequenceBtn.onLClick()") end - if not m.activeTake then return end - - -- backup and turn off shift - local t_shift = table.pack(m.seqShift, m.seqShiftMin, m.seqShiftMax) - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence - seqShiftVal.label = tostring(m.seqShift) - -- turn off repeat - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false - InsertNotes() - - if m.seqF then - SetSeqGridSizes(t_seqSliders) - GenProbTable(m.preSeqProbTable, t_seqSliders, m.seqProbTable) - GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) - GenLegatoTable(m.legProbTable, seqLegProbSldr) - GetNotesFromTake() - GenSequence(m.seqProbTable, m.accProbTable, seqAccRSldr, m.legProbTable) - - else -- not m.seqF - GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) - GenLegatoTable(m.legProbTable, seqLegProbSldr) - GetNotesFromTake() - GenNoteAttributes(m.seqAccentF, m.accProbTable, seqAccRSldr, m.seqLegatoF, m.legProbTable) - - -- restore and turn shift back on - m.seqShift, m.seqShiftMin, m.seqShiftMax = table.unpack(t_shift) - seqShiftVal.label = tostring(m.seqShift) - InsertNotes() - end -- m.seqF - - -- turn on repeat - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false - - if m.seqRndNotesF then - randomBtn.onLClick() -- call RandomiseNotes - end - - -- set project ext state - if seqGridRad.val1 == 1 then -- 1/16 grid - pExtState.seqGrid16 = {} - for k, v in pairs (t_seqSliders) do - pExtState.seqGrid16[k] = v.val1 - end - end - if seqGridRad.val1 == 2 then -- 1/8 grid - pExtState.seqGrid8 = {} - for k, v in pairs (t_seqSliders) do - pExtState.seqGrid8[k] = v.val1 - end - end - if seqGridRad.val1 == 3 then -- 1/4 grid - pExtState.seqGrid4 = {} - for k, v in pairs (t_seqSliders) do - pExtState.seqGrid4[k] = v.val1 - end - end - pExtState.seqAccRSldrLo = seqAccRSldr.val1 - pExtState.seqAccRSldrHi = seqAccRSldr.val2 - pExtState.seqAccProb = seqAccProbSldr.val1 - pExtState.seqLegProb = seqLegProbSldr.val1 - pExtSaveStateF = true -end - -- Set sequencer options defaults function SetDefaultSeqOptions() local debug = false @@ -2150,8 +2047,6 @@ function GlueSeqRepeater() -- reset the drop down lists and pExtState seqLoopStartDrop.val1 = 1; m.loopStartG = 1 - - -- reset the program ext state --if pExtState.loopStartG then pExtState.loopStartG = nil end seqLoopLenDrop.val1 = 1; m.loopLenG = 1 --if pExtState.loopLenG then pExtState.loopLenG = nil end @@ -2298,41 +2193,6 @@ end -------------------------------------------------------------------------------- -- Euclidiser -------------------------------------------------------------------------------- --- Euclidiser button -euclidBtn.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\neuclidBtn.onLClick()") end - - if m.activeTake then - if m.eucF then - if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end - GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) - GetNotesFromTake() - GenBjorklund(euclidPulsesSldr, euclidStepsSldr, euclidRotationSldr, m.accProbTable, seqAccRSldr) - if m.eucRndNotesF then - randomBtn.onLClick() -- call RandomiseNotes - end - - else -- not m.eucF - if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end - GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) - GetNotesFromTake() - GenNoteAttributes(m.eucAccentF, m.accProbTable, seqAccRSldr, false, m.legProbTable) - if m.eucRndNotesF then - if debug or m.debug then ConMsg("m.eucRndNotesF = " .. tostring(m.eucRndNotesF)) end - randomBtn.onLClick() -- call RandomiseNotes - end - end -- m.eucF - - -- set project ext state - pExtState.eucSliders = {} - for k, v in pairs(t_euclidSliders) do - pExtState.eucSliders[k] = v.val1 - end - pExtSaveStateF = true - end -- m.activeTake -end - -- Set euclid default options function SetDefaultEucOptions() local debug = false @@ -2436,6 +2296,142 @@ euclidRotationSldr.onMove = function() end end +-- Main action buttons +-- Randomiser +randomBtn.onLClick = function() + local debug = false + if debug or m.debug then ConMsg("\nrandomBtn.onLClick()") end + if not m.activeTake then return end + + -- backup and turn off shift + local t_shift = table.pack(m.seqShift, m.seqShiftMin, m.seqShiftMax) + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift + seqShiftVal.label = tostring(m.seqShift) + + -- turn off repeat + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false + + GenProbTable(m.preNoteProbTable, t_noteSliders, m.noteProbTable) + if #m.noteProbTable == 0 then return end + GenOctaveTable(m.octProbTable, octProbSldr) + GetNotesFromTake() + RandomiseNotesPoly(m.noteProbTable) + + -- restore and turn shift back on + m.seqShift, m.seqShiftMin, m.seqShiftMax = table.unpack(t_shift) + seqShiftVal.label = tostring(m.seqShift) + -- turn on repeat + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false + InsertNotes() + + -- set project ext state + pExtState.noteSliders = {} + for k, v in pairs(t_noteSliders) do + pExtState.noteSliders[k] = v.val1 + end + pExtState.rndOctProb = octProbSldr.val1 + pExtSaveStateF = true +end +-- Sequencer +sequenceBtn.onLClick = function() + local debug = false + if debug or m.debug then ConMsg("\nsequenceBtn.onLClick()") end + if not m.activeTake then return end + + -- backup and turn off shift + local t_shift = table.pack(m.seqShift, m.seqShiftMin, m.seqShiftMax) + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence + seqShiftVal.label = tostring(m.seqShift) + -- turn off repeat + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false + InsertNotes() + + if m.seqF then + SetSeqGridSizes(t_seqSliders) + GenProbTable(m.preSeqProbTable, t_seqSliders, m.seqProbTable) + GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) + GenLegatoTable(m.legProbTable, seqLegProbSldr) + GetNotesFromTake() + GenSequence(m.seqProbTable, m.accProbTable, seqAccRSldr, m.legProbTable) + + else -- not m.seqF + GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) + GenLegatoTable(m.legProbTable, seqLegProbSldr) + GetNotesFromTake() + GenNoteAttributes(m.seqAccentF, m.accProbTable, seqAccRSldr, m.seqLegatoF, m.legProbTable) + + -- restore and turn shift back on + m.seqShift, m.seqShiftMin, m.seqShiftMax = table.unpack(t_shift) + seqShiftVal.label = tostring(m.seqShift) + InsertNotes() + end -- m.seqF + + -- turn on repeat + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false + + if m.seqRndNotesF then + randomBtn.onLClick() -- call RandomiseNotes + end + + -- set project ext state + if seqGridRad.val1 == 1 then -- 1/16 grid + pExtState.seqGrid16 = {} + for k, v in pairs (t_seqSliders) do + pExtState.seqGrid16[k] = v.val1 + end + end + if seqGridRad.val1 == 2 then -- 1/8 grid + pExtState.seqGrid8 = {} + for k, v in pairs (t_seqSliders) do + pExtState.seqGrid8[k] = v.val1 + end + end + if seqGridRad.val1 == 3 then -- 1/4 grid + pExtState.seqGrid4 = {} + for k, v in pairs (t_seqSliders) do + pExtState.seqGrid4[k] = v.val1 + end + end + pExtState.seqAccRSldrLo = seqAccRSldr.val1 + pExtState.seqAccRSldrHi = seqAccRSldr.val2 + pExtState.seqAccProb = seqAccProbSldr.val1 + pExtState.seqLegProb = seqLegProbSldr.val1 + pExtSaveStateF = true +end +-- Euclidiser +euclidBtn.onLClick = function() + local debug = false + if debug or m.debug then ConMsg("\neuclidBtn.onLClick()") end + + if m.activeTake then + if m.eucF then + if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end + GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) + GetNotesFromTake() + GenBjorklund(euclidPulsesSldr, euclidStepsSldr, euclidRotationSldr, m.accProbTable, seqAccRSldr) + if m.eucRndNotesF then + randomBtn.onLClick() -- call RandomiseNotes + end + + else -- not m.eucF + if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end + GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) + GetNotesFromTake() + GenNoteAttributes(m.eucAccentF, m.accProbTable, seqAccRSldr, false, m.legProbTable) + if m.eucRndNotesF then + if debug or m.debug then ConMsg("m.eucRndNotesF = " .. tostring(m.eucRndNotesF)) end + randomBtn.onLClick() -- call RandomiseNotes + end + end -- m.eucF + + -- set project ext state + pExtState.eucSliders = {} + for k, v in pairs(t_euclidSliders) do + pExtState.eucSliders[k] = v.val1 + end + pExtSaveStateF = true + end -- m.activeTake +end -------------------------------------------------------------------------------- -- Draw GUI From ebdec9613ece3d61f56b7e75d6f504508fcdb1f9 Mon Sep 17 00:00:00 2001 From: RobU Date: Sun, 4 Jun 2017 21:59:57 +0100 Subject: [PATCH 19/33] logic for repeat moved inside m.seqF shift restore removed glue repeat/shift before randomising --- .../RobU - MIDI Ex Machina.lua | 88 ++++++++++--------- 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index f2f18aa..7df3371 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -110,9 +110,9 @@ m.seqRepeatF = false -- repeat sequence by grid length m.seqShiftF = false -- shift sequence by grid length m.legato = 10 -- default legatolessness value m.legQ = 240 -m.accentLow = 100; m.accentHigh = 127; m.accentProb = 3 -- default values (options) +m.accentLow = 100; m.accentHigh = 127; m.accentProb = 5 -- default values (options) -- accentLow/High - min 0, max 127; accentProb - min 0, max 10 -m.legatoProb = 3 -- default value (option - min 0, max 10) +m.legatoProb = 5 -- default value (option - min 0, max 10) m.seqGrid16 = {8, 8, 0, 4} -- sane default sequencer note length slider values m.seqGrid8 = {0, 8, 2, 2} -- sane default sequencer note length slider values m.seqGrid4 = {0, 2, 8, 1} -- sane default sequencer note length slider values @@ -493,7 +493,7 @@ function GetPermuteScaleFromTake(t) end -- m.activeTake end -------------------------------------------------------------------------------- --- GetNotesFromTake() - fill a note buffer from the active take +-- GetNotesFromTake() - fill a note buffer from the active take, returns a table -------------------------------------------------------------------------------- function GetNotesFromTake() local debug = false @@ -749,7 +749,7 @@ end -------------------------------------------------------------------------------- -- RandomiseNotesPoly(noteProbTable) -------------------------------------------------------------------------------- -function RandomiseNotesPoly(noteProbTable) +function RandomiseNotesPoly() local debug = false if debug or m.debug then ConMsg("RandomiseNotesPoly()") end @@ -765,7 +765,7 @@ function RandomiseNotesPoly(noteProbTable) if i == 1 and m.rndFirstNoteF then -- if selected, the first not is always root of scale t2[i][7] = m.root else - t2[i][7] = GetUniqueNote(t1, i, noteProbTable, m.octProbTable) + t2[i][7] = GetUniqueNote(t1, i, m.noteProbTable, m.octProbTable) end end i = i + 1 @@ -1908,10 +1908,11 @@ end function ResetSeqShifter() local debug = false if debug or m.debug then ConMsg("ResetSeqShifter()") end - + + m.seqShiftF = false m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) - m.seqShiftF = false + if debug or m.debug then ConMsg("Reset m.seqShift, m.seqShiftMin, m.seqShiftMax to 0") ConMsg("Reset shifter label to m.seqShift") @@ -2301,28 +2302,26 @@ end randomBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nrandomBtn.onLClick()") end - if not m.activeTake then return end + if not m.activeTake then return end - -- backup and turn off shift - local t_shift = table.pack(m.seqShift, m.seqShiftMin, m.seqShiftMax) - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift + -- turn off and reset shift + m.seqShiftF = false + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) - -- turn off repeat - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false + -- turn off and reset repeat + m.seqRepeatF = false + seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 + seqLoopStartDrop.val1 = 1; m.loopStartG = 1 + seqLoopLenDrop.val1 = 1; m.loopLenG = 1 + seqLoopNumDrop.val1 = 1; m.loopNum = 1 + -- generate the probability tables GenProbTable(m.preNoteProbTable, t_noteSliders, m.noteProbTable) if #m.noteProbTable == 0 then return end GenOctaveTable(m.octProbTable, octProbSldr) - GetNotesFromTake() - RandomiseNotesPoly(m.noteProbTable) - - -- restore and turn shift back on - m.seqShift, m.seqShiftMin, m.seqShiftMax = table.unpack(t_shift) - seqShiftVal.label = tostring(m.seqShift) - -- turn on repeat - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false - InsertNotes() + GetNotesFromTake() -- grab the current take data + RandomiseNotesPoly() -- set project ext state pExtState.noteSliders = {} @@ -2338,41 +2337,50 @@ sequenceBtn.onLClick = function() if debug or m.debug then ConMsg("\nsequenceBtn.onLClick()") end if not m.activeTake then return end - -- backup and turn off shift + -- turn off and reset shift local t_shift = table.pack(m.seqShift, m.seqShiftMin, m.seqShiftMax) - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) - -- turn off repeat - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false - InsertNotes() - + + -- backup repeat + local t_repeat = table.pack(m.loopStartG, m.loopLenG, m.loopNum, m.seqRepeatF) + if m.seqF then + if m.seqRepeatF then -- temporarily turn off repeat + m.seqRepeatF = false + seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 + seqLoopStartDrop.val1 = 1; m.loopStartG = 1 + seqLoopLenDrop.val1 = 1; m.loopLenG = 1 + seqLoopNumDrop.val1 = 1; m.loopNum = 1 + InsertNotes() + end SetSeqGridSizes(t_seqSliders) GenProbTable(m.preSeqProbTable, t_seqSliders, m.seqProbTable) GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) GenLegatoTable(m.legProbTable, seqLegProbSldr) GetNotesFromTake() GenSequence(m.seqProbTable, m.accProbTable, seqAccRSldr, m.legProbTable) - + if m.seqRndNotesF then randomBtn.onLClick() end + -- restore and turn on repeat + m.loopStartG, m.loopLenG, m.loopNum, m.seqRepeatF = table.unpack(t_repeat) + seqLoopNumDrop.val1 = m.loopNum + seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 + seqLoopStartDrop.val1 = m.loopStartG + seqLoopLenDrop.val1 = m.loopLenG + seqLoopNumDrop.val1 = m.loopNum + if m.seqRepeatF then InsertNotes() end + else -- not m.seqF GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) GenLegatoTable(m.legProbTable, seqLegProbSldr) GetNotesFromTake() GenNoteAttributes(m.seqAccentF, m.accProbTable, seqAccRSldr, m.seqLegatoF, m.legProbTable) - -- restore and turn shift back on - m.seqShift, m.seqShiftMin, m.seqShiftMax = table.unpack(t_shift) - seqShiftVal.label = tostring(m.seqShift) - InsertNotes() + if m.seqRndNotesF then + randomBtn.onLClick() + end end -- m.seqF - -- turn on repeat - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false - - if m.seqRndNotesF then - randomBtn.onLClick() -- call RandomiseNotes - end - -- set project ext state if seqGridRad.val1 == 1 then -- 1/16 grid pExtState.seqGrid16 = {} From 2f3318d9f247727563283798a90a9e31ab6fa6f2 Mon Sep 17 00:00:00 2001 From: RobU Date: Mon, 5 Jun 2017 07:20:32 +0100 Subject: [PATCH 20/33] turn off shift & repeat while using euclidiser --- .../MIDI Ex Machina/RobU - MIDI Ex Machina.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 7df3371..6949c04 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -2411,6 +2411,18 @@ euclidBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\neuclidBtn.onLClick()") end + -- turn off and reset shift + m.seqShiftF = false + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 + seqShiftVal.label = tostring(m.seqShift) + + -- turn off and reset repeat + m.seqRepeatF = false + seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 + seqLoopStartDrop.val1 = 1; m.loopStartG = 1 + seqLoopLenDrop.val1 = 1; m.loopLenG = 1 + seqLoopNumDrop.val1 = 1; m.loopNum = 1 + if m.activeTake then if m.eucF then if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end From 199e0b9ccb00bde66abb78e4b58bed6442d5b955 Mon Sep 17 00:00:00 2001 From: RobU Date: Mon, 5 Jun 2017 16:02:26 +0100 Subject: [PATCH 21/33] tidy reset shift and repeat code in seqGridRad, randomBtn.onLClick, and euclidBtn.onLClick --- .../RobU - MIDI Ex Machina.lua | 157 +++++++++--------- 1 file changed, 74 insertions(+), 83 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 6949c04..1ca7cb8 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -89,7 +89,7 @@ m.oct = 4; m.key = 1; m.root = 0 -- (options, except m.root) -- midi editor, take, grid m.activeEditor, m.activeTake, m.mediaItem = nil, nil, nil -m.currTakeID, m.lastTakeID = "", "" +m.currTake, m.lastTake = "", "" m.ppqn = 960; -- default ppqn, no idea how to check if this has been changed.. m.reaGrid = 0 @@ -525,7 +525,7 @@ function GetNotesFromTake() t[i][9] = rem == 0 and true or false end -- for i end -- num_notes - if debug and m.debug then PrintNotes(t) end + if debug or m.debug then PrintNotes(t) end return t else -- no active take if debug or m.debug then ConMsg("No Active Take") end @@ -1694,6 +1694,8 @@ seqOptionsCb.onLClick = function() if pExtState.seqOptionsCb then if pExtState.seqOptionsCb[6] ~= m.seqRepeatF then InsertNotes() end + else + if m.seqRepeatF then InsertNotes() end end pExtState.seqOptionsCb = {m.seqF, m.seqFirstNoteF, m.seqAccentF, m.seqLegatoF, m.seqRndNotesF, m.seqRepeatF} @@ -1780,59 +1782,6 @@ seqSldrText.onRClick = function() pExtSaveStateF = true -- set the ext state save flag end -- result end --- Sequencer grid toggle logic -seqGridRad.onLClick = function() -- change grid size - local debug = false - if debug or m.debug then ConMsg("\nseqGridRad.onLClick()") end - - if m.activeTake then - - if seqGridRad.val1 == 1 then -- 1/16 grid - reaper.MIDIEditor_OnCommand(m.activeEditor, 40192) -- set grid - if pExtState.seqGrid16 then - for k, v in pairs(t_seqSliders) do - v.val1 = pExtState.seqGrid16[k] - end -- in pairs(t_seqSliders) - else -- not pExtState.seqGrid16 - for k, v in pairs(t_seqSliders) do - v.val1 = m.seqGrid16[k] - end -- in pairs(t_seqSliders) - end -- if pExtState.seqGrid16 - - elseif seqGridRad.val1 == 2 then -- 1/8 grid - reaper.MIDIEditor_OnCommand(m.activeEditor, 40197) -- set grid - if pExtState.seqGrid8 then - for k, v in pairs(t_seqSliders) do - v.val1 = pExtState.seqGrid8[k] - end -- in pairs(t_seqSliders) - else -- not pExtState.seqGrid8 - for k, v in pairs(t_seqSliders) do - v.val1 = m.seqGrid8[k] - end -- in pairs(t_seqSliders) - end -- if pExtState.seqGrid8 - - elseif seqGridRad.val1 == 3 then -- 1/4 grid - reaper.MIDIEditor_OnCommand(m.activeEditor, 40201) -- set grid - if pExtState.seqGrid4 then -- 1/4 grid - for k, v in pairs(t_seqSliders) do - v.val1 = pExtState.seqGrid4[k] - end -- in pairs(t_seqSliders) - else -- not pExtState.seqGrid4 - for k, v in pairs(t_seqSliders) do - v.val1 = m.seqGrid4[k] - end -- in pairs(t_seqSliders) - end -- pExtState.seqGrid4 - end -- seGridRad - - -- reset the shift state - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 - seqShiftVal.label = tostring(m.seqShift) - GetNotesFromTake() -- force an undo point on grid change - --InsertNotes() - pExtSaveStateF = true - - end -- m.activeTake -end -- Set sequencer accent & legato slider defaults function SetDefaultAccLegSliders() @@ -2029,6 +1978,8 @@ function ResetSeqRepeater() seqLoopLenDrop.val1 = 1; m.loopLenG = 1 seqLoopNumDrop.val1 = 1; m.loopNum = 1 InsertNotes() + pExtState.seqOptionsCb[6] = m.seqRepeatF + pExtSaveStateF = true end -- Glue sequencer repeater function GlueSeqRepeater() @@ -2297,24 +2248,16 @@ euclidRotationSldr.onMove = function() end end --- Main action buttons +-- Main action elements -- Randomiser randomBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nrandomBtn.onLClick()") end if not m.activeTake then return end - -- turn off and reset shift - m.seqShiftF = false - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 - seqShiftVal.label = tostring(m.seqShift) - - -- turn off and reset repeat - m.seqRepeatF = false - seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 - seqLoopStartDrop.val1 = 1; m.loopStartG = 1 - seqLoopLenDrop.val1 = 1; m.loopLenG = 1 - seqLoopNumDrop.val1 = 1; m.loopNum = 1 + -- turn off and reset shifter and repeater + ResetSeqShifter() + ResetSeqRepeater() -- generate the probability tables GenProbTable(m.preNoteProbTable, t_noteSliders, m.noteProbTable) @@ -2406,22 +2349,64 @@ sequenceBtn.onLClick = function() pExtState.seqLegProb = seqLegProbSldr.val1 pExtSaveStateF = true end +-- Sequencer grid toggle logic +seqGridRad.onLClick = function() -- change grid size + local debug = false + if debug or m.debug then ConMsg("\nseqGridRad.onLClick()") end + + if m.activeTake then + + if seqGridRad.val1 == 1 then -- 1/16 grid + reaper.MIDIEditor_OnCommand(m.activeEditor, 40192) -- set grid + if pExtState.seqGrid16 then + for k, v in pairs(t_seqSliders) do + v.val1 = pExtState.seqGrid16[k] + end -- in pairs(t_seqSliders) + else -- not pExtState.seqGrid16 + for k, v in pairs(t_seqSliders) do + v.val1 = m.seqGrid16[k] + end -- in pairs(t_seqSliders) + end -- if pExtState.seqGrid16 + + elseif seqGridRad.val1 == 2 then -- 1/8 grid + reaper.MIDIEditor_OnCommand(m.activeEditor, 40197) -- set grid + if pExtState.seqGrid8 then + for k, v in pairs(t_seqSliders) do + v.val1 = pExtState.seqGrid8[k] + end -- in pairs(t_seqSliders) + else -- not pExtState.seqGrid8 + for k, v in pairs(t_seqSliders) do + v.val1 = m.seqGrid8[k] + end -- in pairs(t_seqSliders) + end -- if pExtState.seqGrid8 + + elseif seqGridRad.val1 == 3 then -- 1/4 grid + reaper.MIDIEditor_OnCommand(m.activeEditor, 40201) -- set grid + if pExtState.seqGrid4 then -- 1/4 grid + for k, v in pairs(t_seqSliders) do + v.val1 = pExtState.seqGrid4[k] + end -- in pairs(t_seqSliders) + else -- not pExtState.seqGrid4 + for k, v in pairs(t_seqSliders) do + v.val1 = m.seqGrid4[k] + end -- in pairs(t_seqSliders) + end -- pExtState.seqGrid4 + end -- seGridRad + + -- turn off and reset shifter and repeater + ResetSeqShifter() + ResetSeqRepeater() + + end -- m.activeTake +end -- Euclidiser euclidBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\neuclidBtn.onLClick()") end - -- turn off and reset shift - m.seqShiftF = false - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 - seqShiftVal.label = tostring(m.seqShift) - - -- turn off and reset repeat - m.seqRepeatF = false - seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 - seqLoopStartDrop.val1 = 1; m.loopStartG = 1 - seqLoopLenDrop.val1 = 1; m.loopLenG = 1 - seqLoopNumDrop.val1 = 1; m.loopNum = 1 + -- turn off and reset shifter and repeater + ResetSeqShifter() + ResetSeqRepeater() if m.activeTake then if m.eucF then @@ -2497,6 +2482,7 @@ function InitMidiExMachina() if debug or m.debug then ConMsg("activeEditor = " .. tostring(m.activeEditor)) end m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) if m.activeTake then + m.lastTake = m.activeTake if debug or m.debug then ConMsg("activeTake = " .. tostring(m.activeTake)) end __ = NewNoteBuf() -- get the take's parent media item @@ -2608,17 +2594,22 @@ function MainLoop() if m.activeEditor then m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) if m.activeTake then - m.currTakeID = string.sub(tostring(m.activeTake),11) - if m.currTakeID ~= m.lastTakeID then + if m.activeTake ~= m.lastTake then if debug or m.debug then ConMsg("switched MIDI item...") end - m.lastTakeID = m.currTakeID + -- switch to last take + reaper.SetActiveTake(m.lastTake) + -- reset shift and repeat + ResetSeqShifter() + ResetSeqRepeater() + InsertNotes() + -- switch to new take + reaper.SetActiveTake(m.activeTake) + m.lastTake = m.activeTake -- purge undo/redo buffers and grab new note data m.notebuf.i = 1 PurgeNoteBuf() t = GetNoteBuf() ClearTable(t) - SetDefaultSeqShift() - SetDefaultSeqRepeat() GetNotesFromTake() end ShowMessage(msgText, 0) -- clear old messages From bda686144618876705cfce499da51506b2313de0 Mon Sep 17 00:00:00 2001 From: RobU Date: Wed, 7 Jun 2017 07:51:40 +0100 Subject: [PATCH 22/33] more repeater and shifter clean-up --- .../RobU - MIDI Ex Machina.lua | 39 +++++++------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 1ca7cb8..162d4d8 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -1866,7 +1866,6 @@ function ResetSeqShifter() ConMsg("Reset m.seqShift, m.seqShiftMin, m.seqShiftMax to 0") ConMsg("Reset shifter label to m.seqShift") end - InsertNotes() end -- Glue sequence shifter function GlueSeqShifter() @@ -1891,6 +1890,7 @@ seqShiftText.onRClick = function() if result == 1 then ResetSeqShifter() + InsertNotes() elseif result == 2 then GlueSeqShifter() end -- result @@ -1972,12 +1972,11 @@ function ResetSeqRepeater() -- reset the GUI and repeat flag m.seqRepeatF = false seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 - seqOptionsCb.onLClick() -- will insert notes from the last buffer if necessary -- reset the drop down lists seqLoopStartDrop.val1 = 1; m.loopStartG = 1 seqLoopLenDrop.val1 = 1; m.loopLenG = 1 seqLoopNumDrop.val1 = 1; m.loopNum = 1 - InsertNotes() + -- save state pExtState.seqOptionsCb[6] = m.seqRepeatF pExtSaveStateF = true end @@ -1989,13 +1988,10 @@ function GlueSeqRepeater() InsertNotes() -- reset the shifter (implicit when glueing the loop) - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 - seqShiftVal.label = tostring(m.seqShift) + ResetSeqShifter() -- reset the GUI and repeat flag - m.seqRepeatF = false - seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 - seqOptionsCb.onLClick() + ResetSeqRepeater() -- reset the drop down lists and pExtState seqLoopStartDrop.val1 = 1; m.loopStartG = 1 @@ -2016,6 +2012,7 @@ seqLoopText.onRClick = function() if result == 1 then ResetSeqRepeater() + InsertNotes() elseif result == 2 then GlueSeqRepeater() end -- result @@ -2258,7 +2255,7 @@ randomBtn.onLClick = function() -- turn off and reset shifter and repeater ResetSeqShifter() ResetSeqRepeater() - + InsertNotes() -- generate the probability tables GenProbTable(m.preNoteProbTable, t_noteSliders, m.noteProbTable) if #m.noteProbTable == 0 then return end @@ -2282,8 +2279,7 @@ sequenceBtn.onLClick = function() -- turn off and reset shift local t_shift = table.pack(m.seqShift, m.seqShiftMin, m.seqShiftMax) - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 - seqShiftVal.label = tostring(m.seqShift) + ResetSeqShifter() -- backup repeat local t_repeat = table.pack(m.loopStartG, m.loopLenG, m.loopNum, m.seqRepeatF) @@ -2396,7 +2392,7 @@ seqGridRad.onLClick = function() -- change grid size -- turn off and reset shifter and repeater ResetSeqShifter() ResetSeqRepeater() - + InsertNotes() end -- m.activeTake end -- Euclidiser @@ -2407,7 +2403,7 @@ euclidBtn.onLClick = function() -- turn off and reset shifter and repeater ResetSeqShifter() ResetSeqRepeater() - + InsertNotes() if m.activeTake then if m.eucF then if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end @@ -2482,7 +2478,7 @@ function InitMidiExMachina() if debug or m.debug then ConMsg("activeEditor = " .. tostring(m.activeEditor)) end m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) if m.activeTake then - m.lastTake = m.activeTake + m.lastTake = nil if debug or m.debug then ConMsg("activeTake = " .. tostring(m.activeTake)) end __ = NewNoteBuf() -- get the take's parent media item @@ -2569,8 +2565,9 @@ function MainLoop() reaper.defer(MainLoop) else -- reset the shifter and repeater here... - ResetSeqRepeater() - ResetSeqShifter() + --ResetSeqRepeater() + --ResetSeqShifter() + --InsertNotes() -- Check and save window position __, pExtState.win_x, pExtState.win_y, __, __ = gfx.dock(-1,0,0,0,0) if m.win_x ~= pExtState.win_x or m.win_y ~= pExtState.win_y then @@ -2596,21 +2593,15 @@ function MainLoop() if m.activeTake then if m.activeTake ~= m.lastTake then if debug or m.debug then ConMsg("switched MIDI item...") end - -- switch to last take - reaper.SetActiveTake(m.lastTake) -- reset shift and repeat ResetSeqShifter() - ResetSeqRepeater() - InsertNotes() - -- switch to new take - reaper.SetActiveTake(m.activeTake) - m.lastTake = m.activeTake + ResetSeqRepeater() -- purge undo/redo buffers and grab new note data m.notebuf.i = 1 PurgeNoteBuf() t = GetNoteBuf() ClearTable(t) - GetNotesFromTake() + m.lastTake = m.activeTake end ShowMessage(msgText, 0) -- clear old messages -- check for changes in the active take if the "Permute" scale is selected From cf48ff5564f298435936ba6f303644e1915e26a3 Mon Sep 17 00:00:00 2001 From: RobU Date: Wed, 7 Jun 2017 22:37:34 +0100 Subject: [PATCH 23/33] no message --- .../MIDI Ex Machina/RobU - MIDI Ex Machina.lua | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 162d4d8..4d071b8 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -1861,18 +1861,13 @@ function ResetSeqShifter() m.seqShiftF = false m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) - - if debug or m.debug then - ConMsg("Reset m.seqShift, m.seqShiftMin, m.seqShiftMax to 0") - ConMsg("Reset shifter label to m.seqShift") - end end -- Glue sequence shifter function GlueSeqShifter() local debug = false if debug or m.debug then ConMsg("GlueSeqShifter()") end m.shiftGlueF = true - m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn off repeat + m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Turn off repeat if on... InsertNotes() m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence seqShiftVal.label = tostring(m.seqShift) @@ -2508,6 +2503,8 @@ function InitMidiExMachina() SetDefaultSeqGridSliders(); SetDefaultAccLegSliders() SetDefaultEucOptions(); SetDefaultEucSliders() + -- some pExtState stuff required early... + pExtState.seqOptionsCb = {} if debug or m.debug then ConMsg("End InitMidiExMachina()") end end -------------------------------------------------------------------------------- @@ -2564,10 +2561,11 @@ function MainLoop() if char ~= -1 and char ~= 27 then reaper.defer(MainLoop) else + if debug or m.debug then ConMsg("quitting.....") end -- reset the shifter and repeater here... --ResetSeqRepeater() --ResetSeqShifter() - --InsertNotes() + InsertNotes() -- Check and save window position __, pExtState.win_x, pExtState.win_y, __, __ = gfx.dock(-1,0,0,0,0) if m.win_x ~= pExtState.win_x or m.win_y ~= pExtState.win_y then @@ -2592,7 +2590,7 @@ function MainLoop() m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) if m.activeTake then if m.activeTake ~= m.lastTake then - if debug or m.debug then ConMsg("switched MIDI item...") end + if debug or m.debug then ConMsg("\nswitched MIDI item...") end -- reset shift and repeat ResetSeqShifter() ResetSeqRepeater() From dab7f5d50705ecea9f85cd46f7e443b7fd23178a Mon Sep 17 00:00:00 2001 From: RobU Date: Sat, 10 Jun 2017 15:42:15 +0100 Subject: [PATCH 24/33] Added accessor methods for element colour, element label, and element label colour (get & set) --- MIDI Editor/MIDI Ex Machina/eGUI.lua | 57 +++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/eGUI.lua b/MIDI Editor/MIDI Ex Machina/eGUI.lua index cbd8c7c..c3dca86 100644 --- a/MIDI Editor/MIDI Ex Machina/eGUI.lua +++ b/MIDI Editor/MIDI Ex Machina/eGUI.lua @@ -144,11 +144,11 @@ function e.Element:new(tab, x,y,w,h, rgba, label, font, font_sz, font_rgba, val1 end end elm.tab = bf - elm.def_xywh = {x,y,w,h, font_sz} -- default coordinates, used for zoom and some Element initialisation + elm.def_xywh = {x,y,w,h, font_sz} -- default coordinates for zoom and some Element initialisation elm.x, elm.y, elm.w, elm.h = x, y, w, h -- position and size elm.r, elm.g, elm.b, elm.a = table.unpack(rgba) -- Element colour elm.label, elm.font, elm.font_sz, elm.font_rgba = label, font, font_sz, font_rgba -- all things fonty - elm.val1 = val1; elm.val2 = val2 -- general purpose variables or tables + elm.val1 = val1; elm.val2 = val2 -- general purpose variables or tables elm.min, elm.max, elm.step = min, max, step -- for incrementing or decrementing values setmetatable(elm, self) self.__index = self @@ -157,7 +157,7 @@ end -------------------------------------------------------------------------------- -- Element Class Methods -------------------------------------------------------------------------------- -function e.Element:update_zoom() -- generic e.Element scaling +function e.Element:update_zoom() -- element scaling if not e.gScaleState then return end self.x = math.ceil(self.def_xywh[1] * e.gScale) -- update x position self.w = math.ceil(self.def_xywh[3] * e.gScale) -- update width @@ -187,12 +187,12 @@ end -------------------------------------------------------------------------------- function e.Element:mouseLClick() return gfx.mouse_cap & 1 == 0 and gLastMouseCap & 1 == 1 and - self:pointIN(gfx.mouse_x, gfx.mouse_y) and self:pointIN(gMouseOX, gMouseOY) + self:pointIN(gfx.mouse_x, gfx.mouse_y) and self:pointIN(gMouseOX, gMouseOY) end -------------------------------------------------------------------------------- function e.Element:mouseRClick() return gfx.mouse_cap & 2 == 0 and gLastMouseCap & 2 == 2 and - self:pointIN(gfx.mouse_x, gfx.mouse_y) and self:pointIN(gMouseOX, gMouseOY) + self:pointIN(gfx.mouse_x, gfx.mouse_y) and self:pointIN(gMouseOX, gMouseOY) end -------------------------------------------------------------------------------- function e.Element:mouseRDown() @@ -203,11 +203,48 @@ function e.Element:mouseMDown() return gfx.mouse_cap & 64 == 64 and self:pointIN(gMouseOX, gMouseOY) end -------------------------------------------------------------------------------- -function e.Element:draw_frame() -- generic e.Element frame drawing +function e.Element:draw_frame() gfx.rect(self.x, self.y, self.w, self.h, false) -- frame1 gfx.roundrect(self.x, self.y, self.w - 1, self.h - 1, 3, true) -- frame2 end -------------------------------------------------------------------------------- +function e.Element:getSetColour(col) + if type(col) == "table" then + if #col == 4 then + local safe = true + for k, v in pairs(col) do + if v < 0 or v > 1 then safe = false end + end + if safe == true then + self.r, self.g, self.b, self.a = table.unpack(col) + end + end + end + return table.pack(self.r, self.g, self.b, self.a) +end +-------------------------------------------------------------------------------- +function e.Element:getSetLabel(str) + if type(str) == "string" then + self.label = str + end + return self.label +end +-------------------------------------------------------------------------------- +function e.Element:getSetLabelColour(col) + if type(col) == "table" then + if #col == 4 then + local safe = true + for k, v in pairs(col) do + if v < 0 or v > 1 then safe = false end + end + if safe == true then + self.font_rgba = col + end + end + end + return self.font_rgba +end +-------------------------------------------------------------------------------- -- Metatable funtion for child classes(args = Child, Parent Class) -------------------------------------------------------------------------------- function e.extended(Child, Parent) @@ -246,11 +283,11 @@ end --------------------------------------------------------------------------------- function e.Button:draw() if (self.tab & (1 << e.gActiveLayer)) == 0 and self.tab ~= 0 then return end - self:update_zoom() + self:update_zoom() local a = self.a -- local alpha value for highlight -- Get mouse state - if self:mouseIN() then a = a + 0.1 end -- if in e.Element, increase opacity - if self:mouseLDown() then a = a + 0.2 end -- if e.Element clicked, increase opacity more + if self:mouseIN() then a = a + 0.1 end -- if in e.Element, increase opacity + if self:mouseLDown() then a = a + 0.2 end -- if e.Element clicked, increase opacity more -- in elm L_up (released and was previously pressed), run onLClick (user defined) if self:mouseLClick() and self.onLClick then self.onLClick() end -- in elm R_up (released and was previously pressed), run onRClick (user defined) @@ -296,7 +333,7 @@ function e.Checkbox:set_val1() local tOptions = self.val2 -- the table of options local optIdx = math.floor(((gfx.mouse_y - y) / h) * #tOptions) + 1 if optIdx < 1 then optIdx = 1 elseif optIdx > #tOptions then optIdx = #tOptions end - if tOptState[optIdx] == 0 then tOptState[optIdx] = 1 + if tOptState[optIdx] == 0 then tOptState[optIdx] = 1 elseif tOptState[optIdx] == 1 then tOptState[optIdx] = 0 end end -------------------------------------------------------------------------------- From bc85574bb9a86017d0c35a34e540a79703b0e277 Mon Sep 17 00:00:00 2001 From: RobU Date: Sat, 10 Jun 2017 15:42:59 +0100 Subject: [PATCH 25/33] updated to use new GUI accessor methods fixed change item lost notes when activating repeat bug.. --- .../RobU - MIDI Ex Machina.lua | 110 ++++++++++-------- 1 file changed, 60 insertions(+), 50 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 4d071b8..42be5ec 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -1195,8 +1195,8 @@ local layerBtn04 = e.Button:new({0}, 305, m.win_h - 25, 100, 20, e.col_grey5, "O local undoBtn = e.Button:new({0}, m.win_w-85, m.win_h -25, 40, 20, e.col_grey5, "Undo", m.defFont, m.defFontSz, e.col_grey7) local redoBtn = e.Button:new({0}, m.win_w-45, m.win_h -25, 40, 20, e.col_grey5, "Redo", m.defFont, m.defFontSz, e.col_grey7) -- Persistent window element table -t_winElements = {winFrame, zoomDrop, winText, layerBtn01, layerBtn02, layerBtn03, layerBtn04, undoBtn, redoBtn} - +local t_winElements = {winFrame, zoomDrop, winText, undoBtn, redoBtn} +local t_winLayers = {layerBtn01, layerBtn02, layerBtn03, layerBtn04} -------------------------------------------------------------------------------- -- Common Elements -------------------------------------------------------------------------------- @@ -1357,18 +1357,20 @@ end layerBtn01.onLClick = function() -- randomiser local debug = false if debug or m.debug then ConMsg("\nlayerBtn01.onLClick() (note randomiser)") end - - e.gActiveLayer = 1 - zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_green) - winText.r, winText.g, winText.b, winText.a = table.unpack(e.col_green) - layerBtn01.font_rgba = e.col_grey8 -- highlight layer 1 - layerBtn01.r, layerBtn01.g, layerBtn01.b, layerBtn01.a = table.unpack(e.col_green) - layerBtn02.font_rgba = e.col_grey7 - layerBtn02.r, layerBtn02.g, layerBtn02.b, layerBtn02.a = table.unpack(e.col_grey5) - layerBtn03.font_rgba = e.col_grey7 - layerBtn03.r, layerBtn03.g, layerBtn03.b, layerBtn03.a = table.unpack(e.col_grey5) - layerBtn04.font_rgba = e.col_grey7 - layerBtn04.r, layerBtn04.g, layerBtn04.b, layerBtn04.a = table.unpack(e.col_grey5) + -- set active layer + e.gActiveLayer = 1 + -- set zoom and window text elements to highlight colour + zoomDrop:getSetColour(e.col_green) + winText:getSetColour(e.col_green) + -- reset all layer buttons to default colour + for k, v in pairs(t_winLayers) do + v:getSetColour(e.col_grey5) + v:getSetLabelColour(e.gol_grey7) + end + -- set current layer to highlight colour + layerBtn01:getSetColour(e.col_green) + layerBtn01:getSetLabelColour(e.col_grey8) + -- set zoom state flag e.gScaleState = true -- set project ext state pExtState.activeLayer = e.gActiveLayer @@ -1378,20 +1380,22 @@ end layerBtn02.onLClick = function() -- sequencer local debug = false if debug or m.debug then ConMsg("\nlayerBtn02.onLClick() (sequencer)") end - + -- set active layer e.gActiveLayer = 2 - zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_yellow) - winText.r, winText.g, winText.b, winText.a = table.unpack(e.col_yellow) - layerBtn01.font_rgba = e.col_grey7 - layerBtn01.r, layerBtn01.g, layerBtn01.b, layerBtn01.a = table.unpack(e.col_grey5) - layerBtn02.font_rgba = e.col_grey8 -- highlight layer 2 - layerBtn02.r, layerBtn02.g, layerBtn02.b, layerBtn02.a = table.unpack(e.col_yellow) - layerBtn03.font_rgba = e.col_grey7 - layerBtn03.r, layerBtn03.g, layerBtn03.b, layerBtn03.a = table.unpack(e.col_grey5) - layerBtn04.font_rgba = e.col_grey7 - layerBtn04.r, layerBtn04.g, layerBtn04.b, layerBtn04.a = table.unpack(e.col_grey5) + -- set zoom and window text elements to highlight colour + zoomDrop:getSetColour(e.col_yellow) + winText:getSetColour(e.col_yellow) + -- reset all layer buttons to default colour + for k, v in pairs(t_winLayers) do + v:getSetColour(e.col_grey5) + v:getSetLabelColour(e.gol_grey7) + end + -- set current layer to highlight colour + layerBtn02:getSetColour(e.col_yellow) + layerBtn02:getSetLabelColour(e.col_grey8) + -- set zoom state flag e.gScaleState = true - -- set project ext state + -- set project ext state pExtState.activeLayer = e.gActiveLayer pExtSaveStateF = true end @@ -1399,20 +1403,22 @@ end layerBtn03.onLClick = function() -- euclidean local debug = false if debug or m.debug then ConMsg("\nlayerBtn03.onLClick() (euclid)") end - + -- set active layer e.gActiveLayer = 3 - zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_orange) - winText.r, winText.g, winText.b, winText.a = table.unpack(e.col_orange) - layerBtn01.font_rgba = e.col_grey7 - layerBtn01.r, layerBtn01.g, layerBtn01.b, layerBtn01.a = table.unpack(e.col_grey5) - layerBtn02.font_rgba = e.col_grey7 - layerBtn02.r, layerBtn02.g, layerBtn02.b, layerBtn02.a = table.unpack(e.col_grey5) - layerBtn03.font_rgba = e.col_grey8 -- highlight layer 3 - layerBtn03.r, layerBtn03.g, layerBtn03.b, layerBtn03.a = table.unpack(e.col_orange) - layerBtn04.font_rgba = e.col_grey7 - layerBtn04.r, layerBtn04.g, layerBtn04.b, layerBtn04.a = table.unpack(e.col_grey5) + -- set zoom and window text elements to highlight colour + zoomDrop:getSetColour(e.col_orange) + winText:getSetColour(e.col_orange) + -- reset all layer buttons to default colour + for k, v in pairs(t_winLayers) do + v:getSetColour(e.col_grey5) + v:getSetLabelColour(e.gol_grey7) + end + -- set current layer to highlight colour + layerBtn03:getSetColour(e.col_orange) + layerBtn03:getSetLabelColour(e.col_grey8) + -- set zoom state flag e.gScaleState = true - -- set project ext state + -- set project ext state pExtState.activeLayer = e.gActiveLayer pExtSaveStateF = true end @@ -1420,20 +1426,22 @@ end layerBtn04.onLClick = function() -- options local debug = false if debug or m.debug then ConMsg("\nlayerBtn04.onLClick() (options)") end - + -- set active layer e.gActiveLayer = 4 - zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_grey5) - winText.r, winText.g, winText.b, winText.a = table.unpack(e.col_grey5) - layerBtn01.font_rgba = e.col_grey7 - layerBtn01.r, layerBtn01.g, layerBtn01.b, layerBtn01.a = table.unpack(e.col_grey5) - layerBtn02.font_rgba = e.col_grey7 - layerBtn02.r, layerBtn02.g, layerBtn02.b, layerBtn02.a = table.unpack(e.col_grey5) - layerBtn03.font_rgba = e.col_grey7 - layerBtn03.r, layerBtn03.g, layerBtn03.b, layerBtn03.a = table.unpack(e.col_grey5) - layerBtn04.font_rgba = e.col_grey8 -- highlight layer 4 - layerBtn04.r, layerBtn04.g, layerBtn04.b, layerBtn04.a = table.unpack(e.col_grey6) + -- set zoom and window text elements to highlight colour + zoomDrop:getSetColour(e.col_grey5) + winText:getSetColour(e.col_grey5) + -- reset all layer buttons to default colour + for k, v in pairs(t_winLayers) do + v:getSetColour(e.col_grey5) + v:getSetLabelColour(e.gol_grey7) + end + -- set current layer to highlight colour + layerBtn04:getSetColour(e.col_grey6) + layerBtn04:getSetLabelColour(e.col_grey8) + -- set zoom state flag e.gScaleState = true - -- set project ext state + -- set project ext state pExtState.activeLayer = e.gActiveLayer pExtSaveStateF = true end @@ -2434,6 +2442,7 @@ end -------------------------------------------------------------------------------- function DrawGUI() for key, winElms in pairs(t_winElements) do winElms:draw() end + for key, winLays in pairs(t_winLayers) do winLays:draw() end --for key, frame in pairs(t_Frames) do frame:draw() end for key, check in pairs(t_Checkboxes) do check:draw() end for key, radio in pairs(t_RadButtons) do radio:draw() end @@ -2600,6 +2609,7 @@ function MainLoop() t = GetNoteBuf() ClearTable(t) m.lastTake = m.activeTake + GetNotesFromTake() end ShowMessage(msgText, 0) -- clear old messages -- check for changes in the active take if the "Permute" scale is selected From acd2667094b040eb812ae4c7730bd54a14efb0c3 Mon Sep 17 00:00:00 2001 From: RobU Date: Mon, 19 Jun 2017 15:36:01 +0100 Subject: [PATCH 26/33] many bugfixes for sequencing, shifting, and repeating --- .../RobU - MIDI Ex Machina.lua | 135 ++++++++---------- 1 file changed, 60 insertions(+), 75 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 42be5ec..eff0d38 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -73,9 +73,9 @@ local p = require 'persistence' -- currently unused, i.e. no preset save, load, -------------------------------------------------------------------------------- m = {} -- all ex machina data -- user changeable defaults are marked with "(option)" -m.debug = true +m.debug = false -- window -m.win_title = "RobU : MIDI Ex Machina - v1.3.2"; m.win_dockstate = 0 +m.win_title = "RobU : MIDI Ex Machina - v1.37"; m.win_dockstate = 0 m.win_x = 10; m.win_y = 10; m.win_w = 900; m.win_h = 280 -- window dimensions m.win_bg = {0, 0, 0} -- background colour m.def_zoom = 4 -- 100% (option) @@ -162,8 +162,6 @@ m.preSeqProbTable = {}; m.seqProbTable = {} m.accProbTable = {}; m.octProbTable = {} m.legProbTable = {} -pExtSaveStateF = false -- when true, update the pExtState for saving -pExtLoadStateF = true -- when true, load the pExtState pExtState = {} -- Reaper project ext state table pExtStateStr = "" -- pickled string. a nom a nom a nom... -------------------------------------------------------------------------------- @@ -1341,16 +1339,17 @@ zoomDrop.onLClick = function() -- window scaling elseif zoomDrop.val1 == 9 then e.gScale = 1.8 elseif zoomDrop.val1 == 10 then e.gScale = 2.0 end + pExtState.zoomDrop = zoomDrop.val1 if debug or m.debug then ConMsg("zoom = " .. tostring(e.gScale)) end - -- Save state, close and reopen GFX window - if not pExtState.win_x then + + -- set soom + if pExtState.win_x ~= m.win_x then __, m.win_x, m.win_y, __, __ = gfx.dock(-1,0,0,0,0) - else - -- set project ext state - pExtState.zoomDrop = zoomDrop.val1 - pExtSaveStateF = true + pExtState.win_x = m.win_x + pExtState.win_y = m.win_y end + m.zoomF = true end -- Layer 1 button @@ -1374,7 +1373,7 @@ layerBtn01.onLClick = function() -- randomiser e.gScaleState = true -- set project ext state pExtState.activeLayer = e.gActiveLayer - pExtSaveStateF = true + end -- Layer 2 button layerBtn02.onLClick = function() -- sequencer @@ -1396,8 +1395,7 @@ layerBtn02.onLClick = function() -- sequencer -- set zoom state flag e.gScaleState = true -- set project ext state - pExtState.activeLayer = e.gActiveLayer - pExtSaveStateF = true + pExtState.activeLayer = e.gActiveLayer end -- Layer 3 button layerBtn03.onLClick = function() -- euclidean @@ -1419,8 +1417,7 @@ layerBtn03.onLClick = function() -- euclidean -- set zoom state flag e.gScaleState = true -- set project ext state - pExtState.activeLayer = e.gActiveLayer - pExtSaveStateF = true + pExtState.activeLayer = e.gActiveLayer end -- Layer 4 button layerBtn04.onLClick = function() -- options @@ -1442,8 +1439,7 @@ layerBtn04.onLClick = function() -- options -- set zoom state flag e.gScaleState = true -- set project ext state - pExtState.activeLayer = e.gActiveLayer - pExtSaveStateF = true + pExtState.activeLayer = e.gActiveLayer end -- Undo button undoBtn.onLClick = function() -- undo @@ -1476,10 +1472,12 @@ function SetDefaultWindowOpts() if pExtState.zoomDrop then zoomDrop.val1 = pExtState.zoomDrop end - if pExtState.win_x or pExtState.win_y then + + if pExtState.win_x then -- set the windown position m.win_x = pExtState.win_x m.win_y = pExtState.win_y end + zoomDrop.onLClick() end -- Set default layer @@ -1524,8 +1522,9 @@ noteOptionsCb.onLClick = function() m.rndAllNotesF = noteOptionsCb.val1[1] == 1 and true or false -- All / Sel Notes m.rndFirstNoteF = noteOptionsCb.val1[2] == 1 and true or false -- 1st Note Root m.rndOctX2F = noteOptionsCb.val1[3] == 1 and true or false -- Octave X2 + pExtState.noteOptionsCb = {m.rndAllNotesF, m.rndFirstNoteF, m.rndOctX2F} - pExtSaveStateF = true + if debug or m.debug then PrintTable(noteOptionsCb.val1) end end @@ -1537,10 +1536,10 @@ keyDrop.onLClick = function() m.key = keyDrop.val1 m.root = SetRootNote(m.oct, m.key) UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) + -- set project ext state pExtState.key = m.key pExtState.root = m.root - pExtSaveStateF = true end -- Octave droplist octDrop.onLClick = function() @@ -1549,10 +1548,10 @@ octDrop.onLClick = function() m.oct = octDrop.val1 m.root = SetRootNote(m.oct, m.key) + -- set project ext state pExtState.oct = m.oct pExtState.root = m.root - pExtSaveStateF = true end -- Scale droplist scaleDrop.onLClick = function() @@ -1564,9 +1563,9 @@ scaleDrop.onLClick = function() m.rndAllNotesF = false end UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) + -- set project ext state pExtState.curScaleName = scaleDrop.val2[scaleDrop.val1] - pExtSaveStateF = true end -- Set default scale options @@ -1636,12 +1635,12 @@ probSldrText.onRClick = function() for k, v in pairs(t_noteSliders) do -- reset the sliders if v.label ~= "" then v.val1 = 1 end end -- in pairs(t_noteSliders) + if pExtState.noteSliders then -- write the new proj ext state for k, v in pairs(t_noteSliders) do if v.label ~= "" then pExtState.noteSliders[k] = v.val1 end end -- in pairs(t_noteSliders) end -- pExtState.noteSliders - pExtSaveStateF = true -- set the ext state save flag end -- result end @@ -1658,7 +1657,6 @@ octProbText.onRClick = function() if pExtState.rndOctProb then -- write the new proj ext state pExtState.rndOctProb = nil end -- pExtState.noteSliders - pExtSaveStateF = true -- set the ext state save flag end -- result end @@ -1687,6 +1685,9 @@ function SetDefaultSeqOptions() seqOptionsCb.val1[4] = (true and m.seqLegatoF) and 1 or 0 -- legato seqOptionsCb.val1[5] = (true and m.seqRndNotesF) and 1 or 0 -- random notes seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 -- repeat + + -- store the project state + pExtState.seqOptionsCb = {m.seqF, m.seqFirstNoteF, m.seqAccentF, m.seqLegatoF, m.seqRndNotesF, m.seqRepeatF} end -- Sequencer options toggle logic seqOptionsCb.onLClick = function() @@ -1707,7 +1708,7 @@ seqOptionsCb.onLClick = function() end pExtState.seqOptionsCb = {m.seqF, m.seqFirstNoteF, m.seqAccentF, m.seqLegatoF, m.seqRndNotesF, m.seqRepeatF} - pExtSaveStateF = true + if debug or m.debug then PrintTable(seqOptionsCb.val1) end end @@ -1787,7 +1788,6 @@ seqSldrText.onRClick = function() pExtState.seqGrid4 = nil end -- seqGridRad - pExtSaveStateF = true -- set the ext state save flag end -- result end @@ -1833,7 +1833,6 @@ seqAccSldrText.onRClick = function() if pExtState.seqAccRSldrHi then pExtState.seqAccRSldrHi = nil end seqAccProbSldr.val1 = m.accentProb if pExtState.seqAccProb then pExtState.seqAccProb = nil end - pExtSaveStateF = true -- set the ext state save flag end -- result end -- Reset sequencer legato sliders @@ -1847,7 +1846,6 @@ seqLegSldrText.onRClick = function() if result == 1 then seqLegProbSldr.val1 = m.legatoProb if pExtState.seqLegProb then pExtState.seqLegProb = nil end - pExtSaveStateF = true end -- result end @@ -1981,7 +1979,6 @@ function ResetSeqRepeater() seqLoopNumDrop.val1 = 1; m.loopNum = 1 -- save state pExtState.seqOptionsCb[6] = m.seqRepeatF - pExtSaveStateF = true end -- Glue sequencer repeater function GlueSeqRepeater() @@ -1998,12 +1995,8 @@ function GlueSeqRepeater() -- reset the drop down lists and pExtState seqLoopStartDrop.val1 = 1; m.loopStartG = 1 - --if pExtState.loopStartG then pExtState.loopStartG = nil end seqLoopLenDrop.val1 = 1; m.loopLenG = 1 - --if pExtState.loopLenG then pExtState.loopLenG = nil end seqLoopNumDrop.val1 = 1; m.loopNum = 1 - --if pExtState.loopNum then pExtState.loopNum = nil end - --pExtSaveStateF = true -- set the ext state save flag end -- Right-click handler seqLoopText.onRClick = function() @@ -2173,7 +2166,7 @@ eucOptionsCb.onLClick = function() m.eucRndNotesF = eucOptionsCb.val1[3] == 1 and true or false -- Randomise notes pExtState.eucOptionsCb = {m.eucF, m.eucAccentF, m.eucRndNotesF} - pExtSaveStateF = true + if debug or m.debug then PrintTable(eucOptionsCb.val1) end end @@ -2206,7 +2199,6 @@ txtEuclidLabel.onRClick = function() euclidPulsesSldr.val1 = m.eucPulses euclidStepsSldr.val1 = m.eucSteps euclidRotationSldr.val1 = m.eucRot - pExtSaveStateF = true pExtState.eucSliders = nil end -- result end @@ -2258,7 +2250,7 @@ randomBtn.onLClick = function() -- turn off and reset shifter and repeater ResetSeqShifter() ResetSeqRepeater() - InsertNotes() + --InsertNotes() -- generate the probability tables GenProbTable(m.preNoteProbTable, t_noteSliders, m.noteProbTable) if #m.noteProbTable == 0 then return end @@ -2272,7 +2264,6 @@ randomBtn.onLClick = function() pExtState.noteSliders[k] = v.val1 end pExtState.rndOctProb = octProbSldr.val1 - pExtSaveStateF = true end -- Sequencer sequenceBtn.onLClick = function() @@ -2281,15 +2272,16 @@ sequenceBtn.onLClick = function() if not m.activeTake then return end -- turn off and reset shift - local t_shift = table.pack(m.seqShift, m.seqShiftMin, m.seqShiftMax) + local t_shift = table.pack(m.seqShift, m.seqShiftMin, m.seqShiftMax) -- required? ResetSeqShifter() -- backup repeat local t_repeat = table.pack(m.loopStartG, m.loopLenG, m.loopNum, m.seqRepeatF) if m.seqF then - if m.seqRepeatF then -- temporarily turn off repeat - m.seqRepeatF = false + if m.seqRepeatF then -- temporarily turn off repeat, if it was on + m.seqRepeatF = false -- remember it was on... + m.seqRepeatState = true seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 seqLoopStartDrop.val1 = 1; m.loopStartG = 1 seqLoopLenDrop.val1 = 1; m.loopLenG = 1 @@ -2303,14 +2295,18 @@ sequenceBtn.onLClick = function() GetNotesFromTake() GenSequence(m.seqProbTable, m.accProbTable, seqAccRSldr, m.legProbTable) if m.seqRndNotesF then randomBtn.onLClick() end - -- restore and turn on repeat - m.loopStartG, m.loopLenG, m.loopNum, m.seqRepeatF = table.unpack(t_repeat) - seqLoopNumDrop.val1 = m.loopNum - seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 - seqLoopStartDrop.val1 = m.loopStartG - seqLoopLenDrop.val1 = m.loopLenG - seqLoopNumDrop.val1 = m.loopNum - if m.seqRepeatF then InsertNotes() end + -- restore and turn on repeat, if it was previously on... + if m.seqRepeatState then + m.loopStartG, m.loopLenG, m.loopNum, m.seqRepeatF = table.unpack(t_repeat) + seqLoopNumDrop.val1 = m.loopNum + seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 + seqLoopStartDrop.val1 = m.loopStartG + seqLoopLenDrop.val1 = m.loopLenG + seqLoopNumDrop.val1 = m.loopNum + InsertNotes() + m.seqRepeatState = false + end + -- if m.seqRepeatF then InsertNotes() end else -- not m.seqF GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) @@ -2318,9 +2314,7 @@ sequenceBtn.onLClick = function() GetNotesFromTake() GenNoteAttributes(m.seqAccentF, m.accProbTable, seqAccRSldr, m.seqLegatoF, m.legProbTable) - if m.seqRndNotesF then - randomBtn.onLClick() - end + if m.seqRndNotesF then randomBtn.onLClick() end end -- m.seqF -- set project ext state @@ -2342,11 +2336,11 @@ sequenceBtn.onLClick = function() pExtState.seqGrid4[k] = v.val1 end end + pExtState.seqOptionsCb = {m.seqF, m.seqFirstNoteF, m.seqAccentF, m.seqLegatoF, m.seqRndNotesF, m.seqRepeatF} pExtState.seqAccRSldrLo = seqAccRSldr.val1 pExtState.seqAccRSldrHi = seqAccRSldr.val2 pExtState.seqAccProb = seqAccProbSldr.val1 pExtState.seqLegProb = seqLegProbSldr.val1 - pExtSaveStateF = true end -- Sequencer grid toggle logic seqGridRad.onLClick = function() -- change grid size @@ -2433,7 +2427,6 @@ euclidBtn.onLClick = function() for k, v in pairs(t_euclidSliders) do pExtState.eucSliders[k] = v.val1 end - pExtSaveStateF = true end -- m.activeTake end @@ -2497,13 +2490,11 @@ function InitMidiExMachina() end -- m.activeEditor -- Load ProjectExtState - if pExtLoadStateF then - __, pExtStateStr = reaper.GetProjExtState(0, "MEM", "pExtState") - if pExtStateStr ~= "" then - pExtState = unpickle(pExtStateStr) - end -- pExtStateStr - end -- pExtLoadStateF - + __, pExtStateStr = reaper.GetProjExtState(0, "MEM", "pExtState") + if pExtStateStr ~= "" then + pExtState = unpickle(pExtStateStr) + end -- pExtStateStr + -- set GUI defaults or restore from project state SetDefaultWindowOpts(); SetDefaultLayer() SetDefaultScaleOpts() @@ -2513,7 +2504,7 @@ function InitMidiExMachina() SetDefaultEucOptions(); SetDefaultEucSliders() -- some pExtState stuff required early... - pExtState.seqOptionsCb = {} + if not pExtState.seqOptionsCb then pExtState.seqOptionsCb = {} end if debug or m.debug then ConMsg("End InitMidiExMachina()") end end -------------------------------------------------------------------------------- @@ -2534,6 +2525,7 @@ end -- Mainloop -------------------------------------------------------------------------------- function MainLoop() + local debug = false -- Update mouse state and position if gfx.mouse_cap & 1 == 1 and gLastMouseCap & 1 == 0 or -- L mouse gfx.mouse_cap & 2 == 2 and gLastMouseCap & 2 == 0 or -- R mouse @@ -2571,23 +2563,16 @@ function MainLoop() reaper.defer(MainLoop) else if debug or m.debug then ConMsg("quitting.....") end - -- reset the shifter and repeater here... - --ResetSeqRepeater() - --ResetSeqShifter() - InsertNotes() + + InsertNotes() -- capture any shifted or repeated notes + -- Check and save window position __, pExtState.win_x, pExtState.win_y, __, __ = gfx.dock(-1,0,0,0,0) - if m.win_x ~= pExtState.win_x or m.win_y ~= pExtState.win_y then - m.win_x = pExtState.win_x - m.win_y = pExtState.win_y - pExtSaveStateF = true - end - if pExtSaveStateF then -- quiting, save script state - pExtStateStr = pickle(pExtState) - reaper.SetProjExtState(0, "MEM", "pExtState", pExtStateStr ) - --pExtSaveStateF = false - end + -- Pickle + pExtStateStr = pickle(pExtState) + reaper.SetProjExtState(0, "MEM", "pExtState", pExtStateStr ) + end -- Update Reaper GFX From a94b2c81c231e12ad631c0c80d47032be9b93734 Mon Sep 17 00:00:00 2001 From: RobU Date: Tue, 20 Jun 2017 09:18:43 +0100 Subject: [PATCH 27/33] moved legato to InsertNotes() added helper quantise function for legato --- .../RobU - MIDI Ex Machina.lua | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index eff0d38..e5df5ba 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -109,7 +109,7 @@ m.seqRndNotesF = true -- randomise notes (option) m.seqRepeatF = false -- repeat sequence by grid length m.seqShiftF = false -- shift sequence by grid length m.legato = 10 -- default legatolessness value -m.legQ = 240 +m.legQ = 240 -- default is 1/16 - is set when changing the grid m.accentLow = 100; m.accentHigh = 127; m.accentProb = 5 -- default values (options) -- accentLow/High - min 0, max 127; accentProb - min 0, max 10 m.legatoProb = 5 -- default value (option - min 0, max 10) @@ -491,6 +491,15 @@ function GetPermuteScaleFromTake(t) end -- m.activeTake end -------------------------------------------------------------------------------- +-- Quantise(ppqn) note length quantisation +-------------------------------------------------------------------------------- +function Quantise(ppqn) + local div = math.floor(ppqn / m.legQ + 0.5) + if div < 1 then div = 1 end + local leg = ppqn % m.legQ + return div * m.legQ, leg +end +-------------------------------------------------------------------------------- -- GetNotesFromTake() - fill a note buffer from the active take, returns a table -------------------------------------------------------------------------------- function GetNotesFromTake() @@ -502,7 +511,7 @@ function GetNotesFromTake() local _retval, num_notes, num_cc, num_sysex = reaper.MIDI_CountEvts(m.activeTake) if num_notes > 0 then t = GetNoteBuf(); if t == nil then t = NewNoteBuf() end - local div, rem, noteLen + local div, leg, noteLen ClearTable(t) for i = 1, num_notes do _retval, selected, muted, startppq, endppq, channel, pitch, velocity = reaper.MIDI_GetNote(m.activeTake, i-1) @@ -510,17 +519,19 @@ function GetNotesFromTake() t[i][1] = selected t[i][2] = muted t[i][3] = startppq + --t[i][3] = Quantise(startppq) noteLen = endppq - startppq div = math.floor(noteLen / m.legQ + 0.5) if div < 1 then div = 1 end - rem = noteLen % m.legQ + leg = noteLen % m.legQ noteLen = div * m.legQ t[i][4] = startppq + noteLen + --t[i][4], leg = Quantise(endppq) t[i][5] = noteLen t[i][6] = channel t[i][7] = pitch t[i][8] = velocity - t[i][9] = rem == 0 and true or false + t[i][9] = leg == 0 and true or false end -- for i end -- num_notes if debug or m.debug then PrintNotes(t) end @@ -1013,7 +1024,7 @@ function SeqRepeater(t1) t2[i][2] = v[2] -- muted t2[i][3] = v[3] -- startppqn t2[i][4] = v[4] -- endppqn - if not t2[i][9] then t2[i][4] = t2[i][4] - m.legato end -- handle legatolessness + --if not t2[i][9] then t2[i][4] = t2[i][4] - m.legato end -- handle legatolessness t2[i][5] = v[5] -- length t2[i][6] = v[6] -- channel t2[i][7] = v[7] -- pitch @@ -1035,7 +1046,7 @@ function SeqRepeater(t1) t2[i][2] = v[2] -- muted t2[i][3] = v[3] + writeOffP -- startppqn if v[4] > loopEndP then t2[i][4] = loopEndP + writeOffP else t2[i][4] = v[4] + writeOffP end -- endppqn - if not t2[i][9] then t2[i][4] = t2[i][4] - m.legato end -- handle legatolessness + --if not t2[i][9] then t2[i][4] = t2[i][4] - m.legato end -- handle legatolessness t2[i][5] = v[5] -- length t2[i][6] = v[6] -- channel t2[i][7] = v[7] -- pitch @@ -1065,7 +1076,7 @@ function SeqRepeater(t1) t2[i][2] = v[2] -- muted t2[i][3] = v[3] + writeOffP -- startppqn if v[4] > itemLenP then t2[i][4] = itemLenP else t2[i][4] = v[4] + writeOffP end -- endppqn - if not t2[i][9] then t2[i][4] = t2[i][4] - m.legato end -- handle legatolessness + --if not t2[i][9] then t2[i][4] = t2[i][4] - m.legato end -- handle legatolessness t2[i][5] = v[5] -- channel t2[i][6] = v[6] -- channel t2[i][7] = v[7] -- pitch @@ -1104,6 +1115,7 @@ function InsertNotes() DeleteNotes() for k, v in pairs(t3) do + v[4] = Quantise(v[4]) if not v[9] then v[4] = v[4] - m.legato end -- handle legatolessness reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) end -- for k, v t3 From 2191237baa8e0fe9a399cf655d3fc27dee5a2b53 Mon Sep 17 00:00:00 2001 From: RobU Date: Tue, 11 Jul 2017 07:42:49 +0100 Subject: [PATCH 28/33] Initial code for euclidean rhythm presets --- .../RobU - MIDI Ex Machina.lua | 117 +++++++++++++----- 1 file changed, 87 insertions(+), 30 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index e5df5ba..fe0464d 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -28,9 +28,12 @@ @donation https://www.paypal.me/RobUrquhart @link Reaper http://reaper.fm @link Forum Thread http://reaper.fm -@version 1.3.2 +@version 1.3.7 @author RobU @changelog + v1.3.7 + added sequence repeater + many bug fixes v1.3.2 fixed bug all note sliders at zero causes crash added sequencer note shifter (left / right by grid size) @@ -152,10 +155,39 @@ m.scales = { -- a list of scales available to the note randomiser, more can be added manually if required -- each value is the interval step from the root note of the scale (0) including the octave (12) +m.euclidPresets = { + -- Euclidean Rhythms + {2, 5, 0, name = "Persian 1"}, + {3, 7, 0, name = "Bulgarian 1"}, + {4, 9, 0, name = "Turkish"}, + {5, 11, 0, name = "Classical"}, + {5, 16, 0, name = "Brazilian 1"}, + -- Reverse Euclidean Rhythms + {2, 3, 2, name = "Latin America"}, + {3, 4, 2, name = "Trinidad"}, + {3, 5, 0, name = "Persian 2"}, + {3, 8, 0, name = "West African 1"}, + {4, 7, 0, name = "Bulgarian 2"}, + {4, 11, 0, name = "Frank Zappa"}, + {5, 6, 2, name = "Arabian 1"}, + {5, 7, 6, name = "Arabian 2"}, + {5, 9, 0, name = "South African 1"}, + {5, 12, 10, name = "South African 2"}, + {7, 8, 2, name = "Libyan Taureg"}, + {7, 16, 12, name = "Brazilian 3"}, + {11, 24, 5, name = "Central African 1"}, + -- Non-Euclidean Rhythms + {1, 4, 0, name = "Kick 4 x 4"}, + {5, 8, 0, name = "West African 2"}, + {7, 12, 10, name = "West African 3"}, + {9, 16, 12, name = "Brazilian 4"}, + {13, 24, 16, name = "Central African 2"} + +} -- textual list of the available scale names for the GUI list selector -m.scalelist = {} +m.scalelist = {}; m.euclidlist = {} m.curScaleName = "Chromatic" -- (option - !must be a valid scale name!) - +m.curEuclidName = "Persian 1" -- (option - !must be a valid euclid preset name!) -- various probability tables m.preNoteProbTable = {}; m.noteProbTable = {} m.preSeqProbTable = {}; m.seqProbTable = {} @@ -1096,33 +1128,34 @@ end function InsertNotes() local debug = false if debug or m.debug then ConMsg("InsertNotes()") end - - local t1, t2, t3 = GetNoteBuf(), nil, nil - -- note shifter - if m.seqShiftF then - t2 = SeqShifter(t1) - else - t2 = {}; CopyTable(t1, t2) - end - - -- note repeater - if m.seqRepeatF then - t3 = SeqRepeater(t2) - else - t3 = {}; CopyTable(t2, t3) - end - - DeleteNotes() - for k, v in pairs(t3) do - v[4] = Quantise(v[4]) - if not v[9] then v[4] = v[4] - m.legato end -- handle legatolessness - reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) - end -- for k, v t3 - - reaper.MIDI_Sort(m.activeTake) - reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off + if m.activeTake then + local t1, t2, t3 = GetNoteBuf(), nil, nil + + -- note shifter + if m.seqShiftF then + t2 = SeqShifter(t1) + else + t2 = {}; CopyTable(t1, t2) + end + -- note repeater + if m.seqRepeatF then + t3 = SeqRepeater(t2) + else + t3 = {}; CopyTable(t2, t3) + end + + DeleteNotes() + for k, v in pairs(t3) do + v[4] = Quantise(v[4]) + if not v[9] then v[4] = v[4] - m.legato end -- handle legatolessness + reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) + end -- for k, v t3 + + reaper.MIDI_Sort(m.activeTake) + reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off + end -- active take end -------------------------------------------------------------------------------- -- PrintNotes - arg note_buffer t; print note_buffer to reaper console @@ -1255,16 +1288,20 @@ local noteOptionText = e.Textbox:new({1}, nx+(np*14)+20, 210, (nw*4), 20, e.col_ -- sequence generate button local sequenceBtn = e.Button:new({2}, 25, 205, 100, 25, e.col_yellow, "Generate", m.defFont, m.defFontSz, e.col_grey8) local sx, sy, sw, sh, sp = 140, 50, 30, 150, 40 + -- sequencer grid size radio selector local seqGridRad = e.Rad_Button:new({2,3}, sx, sy + 40, 30, 30, e.col_yellow, "", m.defFont, m.defFontSz, e.col_grey8, 1, {"1/16", "1/8", "1/4"}) local seqGridText = e.Textbox:new({2,3}, sx+5, 210, (sw*2)+5, 20, e.col_grey5, "Grid Size", m.defFont, m.defFontSz, e.col_grey7) + -- sequence grid probability sliders local seqSldr16 = e.Vert_Slider:new({2}, sx+(sp*2)+20, sy, sw, sh, e.col_blue, "1/16", m.defFont, m.defFontSz, e.col_grey8, 0, 0, 0, m.defFontSz, 1) local seqSldr8 = e.Vert_Slider:new({2}, sx+(sp*3)+20, sy, sw, sh, e.col_blue, "1/8", m.defFont, m.defFontSz, e.col_grey8, 0, 0, 0, m.defFontSz, 1) local seqSldr4 = e.Vert_Slider:new({2}, sx+(sp*4)+20, sy, sw, sh, e.col_blue, "1/4", m.defFont, m.defFontSz, e.col_grey8, 0, 0, 0, m.defFontSz, 1) local seqSldrRest = e.Vert_Slider:new({2}, sx+(sp*5)+20, sy, sw, sh, e.col_blue, "Rest", m.defFont, m.defFontSz, e.col_grey8, 0, 0, 0, m.defFontSz, 1) + -- sequence grid probability slider table local t_seqSliders = {seqSldr16, seqSldr8, seqSldr4, seqSldrRest} + -- sequence grid probability sliders label - right click to reset all (per grid size selection) local seqSldrText = e.Textbox:new({2}, sx+(sp * 2)+20, 210, (sw * 5), 20, e.col_grey5, "Size Weight Sliders", m.defFont, m.defFontSz, e.col_grey7) @@ -1297,15 +1334,20 @@ local seqOptionsCb = e.Checkbox:new({2}, sx+(np * 15) + 10, sy + 5, 30, 30, e.co -------------------------------------------------------------------------------- -- euclid generate button local euclidBtn = e.Button:new({3}, 25, 205, 100, 25, e.col_orange, "Generate", m.defFont, m.defFontSz, e.col_grey8) + -- euclidean sliders local ex, ey, ew, eh, ep = 160, 50, 30, 150, 40 local euclidPulsesSldr = e.Vert_Slider:new({3}, ex+(ep*2), ey, ew, eh, e.col_blue, "Puls", m.defFont, m.defFontSz, e.col_grey8, m.eucPulses, 0, 1, 24, 1) local euclidStepsSldr = e.Vert_Slider:new({3}, ex+(ep*3), ey, ew, eh, e.col_blue, "Step", m.defFont, m.defFontSz, e.col_grey8, m.eucSteps, 0, 1, 24, 1) local euclidRotationSldr = e.Vert_Slider:new({3}, ex+(ep*4), ey, ew, eh, e.col_blue, "Rot", m.defFont, m.defFontSz, e.col_grey8, m.eucRot, 0, 0, 24, 1) local t_euclidSliders = {euclidPulsesSldr, euclidStepsSldr, euclidRotationSldr} + -- euclid slider label - right click to reset all local txtEuclidLabel = e.Textbox:new({3}, ex + (ep * 2), 210, (ew * 3) + 20, 20, e.col_grey5, "Euclid Sliders", m.defFont, m.defFontSz, e.col_grey7) --- Sequencer options + +-- euclid presets +local euclidDrop = e.Droplist:new({3}, ex + 415, 70, 100, 20, e.col_blue, "Presets", m.defFont, m.defFontSz, e.col_grey8, 1, m.euclidlist) +-- euclid options local eucOptionsCb = e.Checkbox:new({3}, ex + (ep * 15)- 10, ey + 40, 30, 30, e.col_orange, "", m.defFont, m.defFontSz, e.col_grey8, {0,0,0}, {"Generate", "Accent", "Rnd Notes"}) -------------------------------------------------------------------------------- @@ -1323,7 +1365,7 @@ local msgText = e.Textbox:new({9}, m.win_x + 10, m.win_y + 30, m.win_w - 40, m.w -------------------------------------------------------------------------------- local t_Buttons = {randomBtn, sequenceBtn, seqShiftLBtn, seqShiftRBtn, euclidBtn} local t_Checkboxes = {noteOptionsCb, seqOptionsCb, eucOptionsCb} -local t_Droplists2 = {seqLoopLenDrop, seqLoopNumDrop, seqLoopStartDrop} +local t_Droplists2 = {seqLoopLenDrop, seqLoopNumDrop, seqLoopStartDrop, euclidDrop} local t_RadButtons = {seqGridRad} local t_RSliders = {octProbSldr, seqAccRSldr, seqAccProbSldr, seqLegProbSldr} local t_Textboxes = {probSldrText, octProbText, seqGridText, seqSldrText, seqShiftVal, seqLoopText, seqShiftText, seqAccSldrText, seqLegSldrText, txtEuclidLabel, optText, msgText} @@ -2162,6 +2204,21 @@ function SetDefaultEucOptions() m.eucRndNotesF = pExtState.eucOptionsCb[3] == true and true or false end +-- create a euclid preset name lookup table for the gui (euclidDrop) + for k, v in pairs(m.euclidPresets) do + m.euclidlist[k] = m.euclidPresets[k]["name"] + end + -- if euclid preset name saved in project state, load it + if pExtState.curEuclidName then + m.curEuclidName = pExtState.curEuclidName + end + -- update the euclid dropbox val1 to match the euclid table index + for k, v in pairs(m.euclidPresets) do + if v.name == m.curEuclidName then euclidDrop.val1 = k end + end + +-- SetEuclid(m.curEuclidName, m.euclidPresets) --set chosen preset + -- set euclidean options using defaults, or loaded project state eucOptionsCb.val1[1] = (true and m.eucF) and 1 or 0 -- generate eucOptionsCb.val1[2] = (true and m.eucAccentF) and 1 or 0 -- accents From 9b7a48d46643d351b74b42e47395ff81edefbcc6 Mon Sep 17 00:00:00 2001 From: RobU Date: Thu, 13 Jul 2017 07:14:54 +0100 Subject: [PATCH 29/33] Euclid presets working, pExtState broken... --- .../RobU - MIDI Ex Machina.lua | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index fe0464d..ee1f3f5 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -2309,6 +2309,25 @@ euclidRotationSldr.onMove = function() end end +-- Euclid Presets +euclidDrop.onLClick = function() + local debug = false + if debug or m.debug then ConMsg("\neuclidDrop.onLClick()") end + + local preset = {} + + for i = 1, #m.euclidPresets, 1 do + if euclidDrop.val2[euclidDrop.val1] == m.euclidPresets[i].name then + preset = m.euclidPresets[i] + end + end + + euclidPulsesSldr.val1 = preset[1] + euclidStepsSldr.val1 = preset[2] + euclidRotationSldr.val1 = preset[3] + euclidRotationSldr.max = euclidStepsSldr.val1 +end + -- Main action elements -- Randomiser randomBtn.onLClick = function() @@ -2496,6 +2515,8 @@ euclidBtn.onLClick = function() for k, v in pairs(t_euclidSliders) do pExtState.eucSliders[k] = v.val1 end + pExtState.curEuclidName = euclidDrop.val2[euclidDrop.val1] + end -- m.activeTake end From 76e619f0ca11fc64532013b5a2b70e50fa9304aa Mon Sep 17 00:00:00 2001 From: RobU23 Date: Thu, 13 Jul 2017 21:25:37 +0100 Subject: [PATCH 30/33] _ --- .../MIDI Ex Machina/RobU - MIDI Ex Machina.lua | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index ee1f3f5..136dc09 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -2249,6 +2249,7 @@ function SetDefaultEucSliders() for k, v in pairs(t_euclidSliders) do v.val1 = pExtState.eucSliders[k] end + else euclidPulsesSldr.val1 = m.eucPulses @@ -2314,18 +2315,22 @@ euclidDrop.onLClick = function() local debug = false if debug or m.debug then ConMsg("\neuclidDrop.onLClick()") end - local preset = {} + local p = {} for i = 1, #m.euclidPresets, 1 do if euclidDrop.val2[euclidDrop.val1] == m.euclidPresets[i].name then - preset = m.euclidPresets[i] + p = m.euclidPresets[i] end end - euclidPulsesSldr.val1 = preset[1] - euclidStepsSldr.val1 = preset[2] - euclidRotationSldr.val1 = preset[3] + euclidPulsesSldr.val1 = p[1] + euclidStepsSldr.val1 = p[2] + euclidRotationSldr.val1 = p[3] euclidRotationSldr.max = euclidStepsSldr.val1 + + -- save pExtState + pExtState.eucSliders = {p[1], p[2], p[3]} + pExtState.curEuclidName = euclidDrop.val2[euclidDrop.val1] end -- Main action elements @@ -2515,7 +2520,7 @@ euclidBtn.onLClick = function() for k, v in pairs(t_euclidSliders) do pExtState.eucSliders[k] = v.val1 end - pExtState.curEuclidName = euclidDrop.val2[euclidDrop.val1] + end -- m.activeTake end From cb645db09016501d050586ab6a6d04b7a6999956 Mon Sep 17 00:00:00 2001 From: RobU23 Date: Thu, 26 Oct 2017 23:00:53 +0100 Subject: [PATCH 31/33] minor tweaks, bugfixes --- .../RobU - MIDI Ex Machina.lua | 698 +++++++++--------- 1 file changed, 349 insertions(+), 349 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 136dc09..4acde02 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -3,23 +3,23 @@ @about #### MIDI Ex Machina A scale-oriented, probability based composition tool - + #### Features note randomiser - selectable root note, octave, scale - note probability sliders - randomise all or selected notes - - octave doubler, with probability slider - - force first note to root note option + - octave doubler, with probability slider + - force first note to root note option - permute selected notes - + monophonic random sequence generator - note length probability sliders - grid size control - velocity accent level, and probabilty slider - legato probability slider - various generation options - + euclidean sequence generator - grid size control - set pulses, steps, and rotation @@ -93,7 +93,7 @@ m.oct = 4; m.key = 1; m.root = 0 -- (options, except m.root) -- midi editor, take, grid m.activeEditor, m.activeTake, m.mediaItem = nil, nil, nil m.currTake, m.lastTake = "", "" -m.ppqn = 960; -- default ppqn, no idea how to check if this has been changed.. +m.ppqn = 960; -- default ppqn, no idea how to check if this has been changed.. m.reaGrid = 0 -- note randomiser @@ -108,7 +108,7 @@ m.seqF = true -- generate sequence (option) m.seqFirstNoteF = true -- first note always (option) m.seqAccentF = true -- generate accents (option) m.seqLegatoF = false -- use legato (option) -m.seqRndNotesF = true -- randomise notes (option) +m.seqRndNotesF = true -- randomise notes (option) m.seqRepeatF = false -- repeat sequence by grid length m.seqShiftF = false -- shift sequence by grid length m.legato = 10 -- default legatolessness value @@ -151,7 +151,7 @@ m.scales = { {0, 2, 4, 7, 9, 12,name = "Pentatonic Maj"}, {0, 3, 5, 7, 10, 12,name = "Pentatonic Min"}, {name = "Permute"} -} +} -- a list of scales available to the note randomiser, more can be added manually if required -- each value is the interval step from the root note of the scale (0) including the octave (12) @@ -174,7 +174,7 @@ m.euclidPresets = { {5, 9, 0, name = "South African 1"}, {5, 12, 10, name = "South African 2"}, {7, 8, 2, name = "Libyan Taureg"}, - {7, 16, 12, name = "Brazilian 3"}, + {7, 16, 12, name = "Brazilian 3"}, {11, 24, 5, name = "Central African 1"}, -- Non-Euclidean Rhythms {1, 4, 0, name = "Kick 4 x 4"}, @@ -182,7 +182,7 @@ m.euclidPresets = { {7, 12, 10, name = "West African 3"}, {9, 16, 12, name = "Brazilian 4"}, {13, 24, 16, name = "Central African 2"} - + } -- textual list of the available scale names for the GUI list selector m.scalelist = {}; m.euclidlist = {} @@ -269,15 +269,15 @@ end -------------------------------------------------------------------------------- Pickle = { clone = function (t) local nt = {} - for i, v in pairs(t) do - nt[i] = v + for i, v in pairs(t) do + nt[i] = v end - return nt -end + return nt +end } -------------------------------------------------------------------------------- function Pickle:pickle_(root) - if type(root) ~= "table" then + if type(root) ~= "table" then error("can only pickle tables, not " .. type(root) .. "s") end self._tableToRef = {} @@ -304,12 +304,12 @@ function Pickle:value_(v) elseif vtype == "boolean" then return tostring(v) elseif vtype == "table" then return "{"..self:ref_(v).."}" else error("pickle a " .. type(v) .. " is not supported") - end + end end -------------------------------------------------------------------------------- function Pickle:ref_(t) local ref = self._tableToRef[t] - if not ref then + if not ref then if t == self then error("can't pickle the pickle class") end table.insert(self._refToTable, t) ref = #self._refToTable @@ -353,7 +353,7 @@ end function ClearTable(t) local debug = false if debug or m.debug then ConMsg("ClearTable()") end - + for k, v in pairs(t) do t[k] = nil end @@ -364,12 +364,12 @@ end function CopyTable(t1, t2) local debug = false if debug or m.debug then ConMsg("CopyTable()") end - + ClearTable(t2) local i = 1 while t1[i] do local j = 1 - t2[i] = {} + t2[i] = {} while (t1[i][j] ~= nil) do t2[i][j] = t1[i][j] j = j + 1 @@ -383,7 +383,7 @@ end local function NewNoteBuf() local debug = false if debug or m.debug then ConMsg("NewNoteBuf()") end - + m.notebuf.i = m.notebuf.i + 1 m.notebuf.max = m.notebuf.max + 1 m.notebuf[m.notebuf.i] = {} @@ -400,7 +400,7 @@ end local function GetNoteBuf() local debug = false if debug or m.debug then ConMsg("GetNoteBuf()") end - + if m.notebuf.i >= 1 then if debug or m.debug then str = "retrieved buffer\n" @@ -409,14 +409,14 @@ local function GetNoteBuf() end return m.notebuf[m.notebuf.i] end -end +end -------------------------------------------------------------------------------- -- UndoNoteBuf() - points to previous note buffer -------------------------------------------------------------------------------- local function UndoNoteBuf() local debug = false if debug or m.debug then ConMsg("UndoNoteBuf()") end - + if m.notebuf.i > 1 then m.notebuf.i = m.notebuf.i -1 if debug or m.debug then @@ -442,12 +442,12 @@ local function PurgeNoteBuf() ConMsg("current idx = " .. tostring(m.notebuf.i)) ConMsg("max idx = " .. tostring(m.notebuf.max)) end - + while m.notebuf.max > m.notebuf.i do m.notebuf[m.notebuf.max] = nil if debug or m.debug then ConMsg("purging buffer " .. tostring(m.notebuf.max)) end m.notebuf.max = m.notebuf.max - 1 - end + end end -------------------------------------------------------------------------------- -- GetItemLength(t) - get length of take 't', set various global vars @@ -456,7 +456,7 @@ end function GetItemLength() local debug = false if debug or m.debug then ConMsg("GetItemLength()") end - + mItem = reaper.GetSelectedMediaItem(0, 0) if mItem then if debug or m.debug then ConMsg("mItem = " .. tostring(mItem)) end @@ -484,7 +484,7 @@ end function GetReaperGrid(gridRad) local debug = false if debug or m.debug then ConMsg("GetReaperGrid()") end - + if m.activeTake then m.reaGrid, __, __ = reaper.MIDI_GetGrid(m.activeTake) -- returns quarter notes if debug or m.debug then ConMsg("m.reaGrid = " .. tostring(m.reaGrid)) end @@ -494,7 +494,7 @@ function GetReaperGrid(gridRad) elseif m.reaGrid == 1 then gridRad.val1 = 3 -- 1/4 end -- m.reaGrid end - else + else if debug or m.debug then ConMsg("No Active Take\n") end end -- m.activeTake end @@ -504,7 +504,7 @@ end function GetPermuteScaleFromTake(t) local debug = false if debug or m.debug then ConMsg("GetPermuteScaleFromTake()") end - + local i, j = 1, 0 if m.activeTake then local __, num_notes, num_cc, num_sysex = reaper.MIDI_CountEvts(m.activeTake) @@ -513,14 +513,14 @@ function GetPermuteScaleFromTake(t) for i = 1, num_notes do __, selected, __, __, __, __, pitch, __ = reaper.MIDI_GetNote(m.activeTake, i-1) if selected == true then - j = j + 1 + j = j + 1 t[j] = pitch - m.root end - end -- for i + end -- for i end --if num_notes else if debug or m.debug then ConMsg("No Active Take") end - end -- m.activeTake + end -- m.activeTake end -------------------------------------------------------------------------------- -- Quantise(ppqn) note length quantisation @@ -537,7 +537,7 @@ end function GetNotesFromTake() local debug = false if debug or m.debug then ConMsg("GetNotesFromTake()") end - + local i, t if m.activeTake then local _retval, num_notes, num_cc, num_sysex = reaper.MIDI_CountEvts(m.activeTake) @@ -559,12 +559,12 @@ function GetNotesFromTake() noteLen = div * m.legQ t[i][4] = startppq + noteLen --t[i][4], leg = Quantise(endppq) - t[i][5] = noteLen + t[i][5] = noteLen t[i][6] = channel t[i][7] = pitch t[i][8] = velocity t[i][9] = leg == 0 and true or false - end -- for i + end -- for i end -- num_notes if debug or m.debug then PrintNotes(t) end return t @@ -578,7 +578,7 @@ end function DeleteNotes() local debug = false if debug or m.debug then ConMsg("DeleteNotes()") end - + local i, num_notes = 0, 0 if m.activeTake then __, num_notes, __, __ = reaper.MIDI_CountEvts(m.activeTake) @@ -587,7 +587,7 @@ function DeleteNotes() end --for else if debug or m.debug then ConMsg("No Active Take") end - end --m.activeTake + end --m.activeTake end -------------------------------------------------------------------------------- -- SetRootNote(octave, key) - returns new root midi note @@ -606,7 +606,7 @@ end function GenProbTable(preProbTable, sliderTable, probTable) local debug = false if debug or m.debug then ConMsg("GenProbTable()") end - + local i, j, k, l = 1, 1, 1, 1 local floor = math.floor ClearTable(probTable) @@ -627,7 +627,7 @@ end function GenAccentTable(probTable, velSlider, probSlider) local debug = false if debug or m.debug then ConMsg("GenAccentTable()") end - + local i, j = 1, 1 ClearTable(probTable) -- insert normal velocity @@ -648,7 +648,7 @@ end function GenLegatoTable(probTable, probSlider) local debug = false if debug or m.debug then ConMsg("GenLegatoTable()") end - + local i, j = 1, 1 ClearTable(probTable) -- no legato @@ -669,7 +669,7 @@ end function GenOctaveTable(probTable, probSlider) local debug = false if debug or m.debug then ConMsg("GenOctaveTable()") end - + local i, j = 1, 1 ClearTable(probTable) -- single octave @@ -684,17 +684,17 @@ function GenOctaveTable(probTable, probSlider) end end -------------------------------------------------------------------------------- --- SetScale() +-- SetScale() -- copies a scale from allScales to scale, key = scaleName -------------------------------------------------------------------------------- function SetScale(scaleName, allScales, scale) local debug = false - + ClearTable(scale) for i = 1, #allScales, 1 do if scaleName == allScales[i].name then - if scaleName == "Permute" then - m.rndPermuteF = true + if scaleName == "Permute" then + m.rndPermuteF = true GetPermuteScaleFromTake(scale) else m.rndPermuteF = false @@ -708,7 +708,7 @@ function SetScale(scaleName, allScales, scale) if debug or m.debug then ConMsg("SetScale() - scaleName = " .. tostring(scaleName)) end end -------------------------------------------------------------------------------- --- SetSeqGridSizes() +-- SetSeqGridSizes() -------------------------------------------------------------------------------- function SetSeqGridSizes(sliderTable) local debug = false @@ -728,7 +728,7 @@ end function UpdateSliderLabels(sliderTable, preProbTable) local debug = false if debug or m.debug then ConMsg("UpdateSliderLabels()") end - + for k, v in pairs(sliderTable) do if preProbTable[k] then -- if there's a Scale note -- set the slider to the note name @@ -746,27 +746,27 @@ end function GetUniqueNote(tNotes, noteIdx, noteProbTable, octProbTable) local debug = false if debug and m.debug then ConMsg("GetUniqueNote()") end - - newNote = m.root + noteProbTable[math.random(1, #noteProbTable)] + + newNote = m.root + noteProbTable[math.random(1, #noteProbTable)] if m.rndOctX2F and not m.rndPermuteF then newNote = newNote + octProbTable[math.random(1, #octProbTable)] end - + if #m.dupes == 0 then -- dupe table is empty m.dupes.i = 1; m.dupes[m.dupes.i] = {} -- add note to the dupe table m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] m.dupes[m.dupes.i].midi = newNote return newNote - + elseif tNotes[noteIdx][3] >= m.dupes[m.dupes.i].srtpos and tNotes[noteIdx][3] < m.dupes[m.dupes.i].endpos then -- note overlaps with previous note m.dupes.i = m.dupes.i + 1; m.dupes[m.dupes.i] = {} -- add note to dupe table m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] unique = false - - while not unique do + + while not unique do newNote = m.root + noteProbTable[math.random(1,#noteProbTable)] if m.rndOctX2F and not m.rndPermuteF then newNote = newNote + octProbTable[math.random(1, #octProbTable)] @@ -778,13 +778,13 @@ function GetUniqueNote(tNotes, noteIdx, noteProbTable, octProbTable) end -- not unique m.dupes[m.dupes.i].midi = newNote -- update dupe table return newNote - + else -- note does not overlap with previous note m.dupes = {}; m.dupes.i = 1; m.dupes[m.dupes.i] = {} -- reset dupe table m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] m.dupes[m.dupes.i].midi = newNote - return newNote + return newNote end -- if #m.dupes end -------------------------------------------------------------------------------- @@ -793,14 +793,14 @@ end function RandomiseNotesPoly() local debug = false if debug or m.debug then ConMsg("RandomiseNotesPoly()") end - + m.dupes.i = 1 local i = 1 local t1, t2 = GetNoteBuf(), NewNoteBuf() CopyTable(t1, t2) - - if debug and m.debug then PrintNotes(t1) end - + + if debug and m.debug then PrintNotes(t1) end + while t2[i] do if t2[i][1] == true or m.rndAllNotesF then -- if selected, or all notes flag is true if i == 1 and m.rndFirstNoteF then -- if selected, the first not is always root of scale @@ -811,11 +811,11 @@ function RandomiseNotesPoly() end i = i + 1 end -- while t1[i] - + PurgeNoteBuf() if debug and m.debug then PrintNotes(t2) end InsertNotes() - if m.rndPermuteF and m.activeTake then + if m.rndPermuteF and m.activeTake then __, pHash = reaper.MIDI_GetHash(m.activeTake, false, 0) m.pHash = pHash end @@ -826,7 +826,7 @@ end function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) local debug = false if debug or m.debug then ConMsg("GenSequence()") end - + local t = NewNoteBuf() GetReaperGrid() -- populates m.reaGrid local itemPos = 0 @@ -837,16 +837,16 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) local noteCount = 0; restCount = 0 while itemPos < itemLength do - + if m.seqFirstNoteF and noteCount == 0 then -- handle first note flag newNote = seqProbTable[math.random(1, #seqProbTable)] while newNote == -1 do newNote = seqProbTable[math.random(1, #seqProbTable)] end - else + else newNote = seqProbTable[math.random(1, #seqProbTable)] end -- m.seqFirstNoteF - + if newNote == -1 then itemPos = itemPos + gridSize restCount = restCount + 1 @@ -855,13 +855,13 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) noteLen = newNote * m.ppqn -- check if noteLen exceeds the item length if noteStart + noteLen > itemLength then noteLen = itemLength - noteStart end - noteEnd = noteStart + noteLen + noteEnd = noteStart + noteLen itemPos = itemPos + noteLen if m.seqLegatoF then -- handle legato flag noteLeg = legProbTable[math.random(1, #legProbTable)] else noteLeg = false - end + end if m.seqAccentF then -- handle accent flag noteVel = accProbTable[math.random(1, #accProbTable)] else @@ -878,9 +878,9 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) t[noteCount][7] = m.root -- note number t[noteCount][8] = noteVel -- velocity t[noteCount][9] = noteLeg -- legato - + end -- newNote - + end -- itemPos < itemLength if debug and m.debug then PrintNotes(t) end PurgeNoteBuf() @@ -893,7 +893,7 @@ end function GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) local debug = false if debug or m.debug then ConMsg("GenBjorklund()") end - + local floor = math.floor local t = NewNoteBuf() GetReaperGrid() -- populates m.reaGrid @@ -909,19 +909,19 @@ function GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) local pattern = b.generate(pulse, step) local rot = floor(rotation.val1 + 0.5) local idx = (-rot) + 1; idx = Wrap(idx, step) - + while itemPos < itemLength do if pattern[idx] then noteStart = itemPos noteLen = gridSize noteEnd = noteStart + noteLen itemPos = itemPos + noteLen - + if m.eucAccentF then -- handle accent flag noteVel = accProbTable[math.random(1, #accProbTable)] else noteVel = floor(accSlider.val1) - end -- m.seqAccentF + end -- m.seqAccentF --noteVel = accProbTable[math.random(1, #accProbTable)] noteCount = noteCount + 1 t[noteCount] = {} @@ -938,11 +938,11 @@ function GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) itemPos = itemPos + gridSize restCount = restCount + 1 end - + idx = idx + 1 idx = Wrap(idx, step) end - + PurgeNoteBuf() --if not m.eucRndNotesF then InsertNotes() end InsertNotes() @@ -953,7 +953,7 @@ end function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) local debug = false if debug or m.debug then ConMsg("GenNoteAttributes()") end - + if not accF and not legF then return end local t1, t2 = GetNoteBuf(), NewNoteBuf() local gridSize = GetReaperGrid() @@ -961,20 +961,20 @@ function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) local div, rem, noteLen CopyTable(t1, t2) if debug and m.debug then PrintNotes(t2) end - + for k, v in pairs(t2) do if v[1] then -- selected if accF then -- handle accent flag (8 = velocity) v[8] = accProbTable[math.random(1, #accProbTable)] end -- end accF if legF ~= 1 then -- no legato when called by euclid - if legF then -- handle legato flag + if legF then -- handle legato flag v[9] = legProbTable[math.random(1, #legProbTable)] - end -- legF + end -- legF end -- legF ~= 1 - end -- selected + end -- selected end -- for k, v t2 - + if debug and m.debug then PrintNotes(t2) end PurgeNoteBuf() InsertNotes() @@ -986,23 +986,23 @@ end function SeqShifter(t1) local debug = false if debug or m.debug then ConMsg("SeqShifter()") end - + local gridSize = math.floor(m.reaGrid * m.ppqn) - local itemLenP = GetItemLength() + local itemLenP = GetItemLength() local noteShift = math.floor(m.seqShift * gridSize) local t2 = nil - + -- note shifter if m.shiftGlueF then - if debug or m.debug then ConMsg("Shifter glued ...") end + if debug or m.debug then ConMsg("Shifter glued ...") end t2 = NewNoteBuf() -- new note buffer for glueing m.shiftGlueF = false else - if debug or m.debug then ConMsg("Shifter not glued ...") end + if debug or m.debug then ConMsg("Shifter not glued ...") end t2 = {} -- temp table for note shifter (no undo) end - CopyTable(t1, t2) + CopyTable(t1, t2) for k, v in pairs(t2) do v[3] = v[3] + noteShift v[4] = v[4] + noteShift @@ -1015,7 +1015,7 @@ function SeqShifter(t1) v[4] = v[4] - itemLenP end end -- for k, v t2 - + return t2 end -------------------------------------------------------------------------------- @@ -1024,9 +1024,9 @@ end function SeqRepeater(t1) local debug = false if debug or m.debug then ConMsg("SeqRepeater()") end - + local gridSize = math.floor(m.reaGrid * m.ppqn) - local itemLenP = GetItemLength() + local itemLenP = GetItemLength() local t2 = nil -- note repeater @@ -1038,7 +1038,7 @@ function SeqRepeater(t1) if debug or m.debug then ConMsg("Repeater not glued...") end t2 = {} -- temp table for repeating end - + local loopStartP = (m.loopStartG -1) * gridSize local loopLenP = m.loopLenG * gridSize local loopEndP = loopStartP + loopLenP @@ -1049,12 +1049,12 @@ function SeqRepeater(t1) -- pre-repeat if debug or m.debug then ConMsg("pre repeat ...") end - for k, v in pairs(t1) do + for k, v in pairs(t1) do if v[3] >= 0 and v[3] < loopStartP then t2[i] = {} t2[i][1] = v[1] -- selected t2[i][2] = v[2] -- muted - t2[i][3] = v[3] -- startppqn + t2[i][3] = v[3] -- startppqn t2[i][4] = v[4] -- endppqn --if not t2[i][9] then t2[i][4] = t2[i][4] - m.legato end -- handle legatolessness t2[i][5] = v[5] -- length @@ -1067,14 +1067,14 @@ function SeqRepeater(t1) end end -- k, v in pairs(t1) - pre-repeat writeOffP = writeOffP + loopStartP - + -- repeat if debug or m.debug then ConMsg("repeat ...") end while loopNum > 0 do for k, v in pairs(t1) do if v[3] >= loopStartP and v[3] < loopEndP then t2[i] = {} - t2[i][1] = v[1] -- selected + t2[i][1] = v[1] -- selected t2[i][2] = v[2] -- muted t2[i][3] = v[3] + writeOffP -- startppqn if v[4] > loopEndP then t2[i][4] = loopEndP + writeOffP else t2[i][4] = v[4] + writeOffP end -- endppqn @@ -1087,7 +1087,7 @@ function SeqRepeater(t1) reaper.MIDI_InsertNote(m.activeTake, t2[i][1], t2[i][2], t2[i][3], t2[i][4], t2[i][6], t2[i][7], t2[i][8], false) i = i + 1 end -- if v[3] - + end -- for k, v t1 - repeat loopNum = loopNum - 1 writeOffP = writeOffP + loopLenP @@ -1095,16 +1095,16 @@ function SeqRepeater(t1) -- post-repeat if debug or m.debug then ConMsg("post repeat ...") end - local written = loopStartP + (loopLenP * m.loopNum) - local remLenP = itemLenP - written + local written = loopStartP + (loopLenP * m.loopNum) + local remLenP = itemLenP - written local readStartP = loopStartP + loopLenP local readEndP = readStartP + remLenP local writeOffP = written - readStartP - + for k, v in pairs(t1) do if v[3] >= readStartP and v[3] < readEndP then t2[i] = {} - t2[i][1] = v[1] -- selected + t2[i][1] = v[1] -- selected t2[i][2] = v[2] -- muted t2[i][3] = v[3] + writeOffP -- startppqn if v[4] > itemLenP then t2[i][4] = itemLenP else t2[i][4] = v[4] + writeOffP end -- endppqn @@ -1116,11 +1116,11 @@ function SeqRepeater(t1) t2[i][9] = v[9] -- legato reaper.MIDI_InsertNote(m.activeTake, t2[i][1], t2[i][2], t2[i][3], t2[i][4], t2[i][6], t2[i][7], t2[i][8], false) i = i + 1 - end + end end -- k, v in pairs(t1) - post-repeat - + return t2 - + end -------------------------------------------------------------------------------- -- InsertNotes() - insert current note buffer in the active take @@ -1131,28 +1131,28 @@ function InsertNotes() if m.activeTake then local t1, t2, t3 = GetNoteBuf(), nil, nil - + -- note shifter if m.seqShiftF then t2 = SeqShifter(t1) else t2 = {}; CopyTable(t1, t2) end - + -- note repeater - if m.seqRepeatF then + if m.seqRepeatF then t3 = SeqRepeater(t2) else t3 = {}; CopyTable(t2, t3) end - + DeleteNotes() for k, v in pairs(t3) do v[4] = Quantise(v[4]) if not v[9] then v[4] = v[4] - m.legato end -- handle legatolessness - reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) + reaper.MIDI_InsertNote(m.activeTake, v[1], v[2], v[3], v[4], v[6], v[7], v[8], false) end -- for k, v t3 - + reaper.MIDI_Sort(m.activeTake) reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off end -- active take @@ -1163,21 +1163,21 @@ end function PrintNotes(t) -- debug code local debug = false if debug or m.debug then ConMsg("PrintNotes()") end - + if not t then return end local i = 1 local str = "sel \t mut \t s_ppq \t e_ppq \t leng \t chan \t pitch \t vel \t leg \n" - + while t[i] do j = 1 - while (t[i][j] ~= nil) do + while (t[i][j] ~= nil) do str = str .. tostring(t[i][j]) .. "\t" j = j + 1 - end + end str = str .. "\n" i = i + 1 end -- while t[i] - + str = str .. "\n" if debug or m.debug then ConMsg(str) end end @@ -1187,14 +1187,14 @@ end function PrintTable(t) -- debug code local debug = false if debug or m.debug then ConMsg("PrintTable()") end - + if not t then return end local str = "" - + for k, v in pairs(t) do str = str .. tostring(v) .. "\t" - end - + end + str = str .. "\n" if debug or m.debug then ConMsg(str) end end @@ -1204,13 +1204,13 @@ end function ShowMessage(tb, msgNum) local debug = false if debug and m.debug then ConMsg("ShowMessage() ") end - + if msgNum == 0 then - tb.tab = (1 << 9) + tb.tab = (1 << 9) tb.label = "" - elseif msgNum == 1 then + elseif msgNum == 1 then tb.tab = 0 - tb.label = "No Active Take" + tb.label = "No Active Take" end e.gScaleState = true end @@ -1248,7 +1248,7 @@ dx, dy, dw, dh = 25, 70, 100, 20 local keyDrop = e.Droplist:new({1, 2, 3}, dx, dy, dw, dh, e.col_blue, "Root Note", m.defFont, m.defFontSz, e.col_grey8, m.key, m.notes) local octDrop = e.Droplist:new({1, 2, 3}, dx, dy + 45, dw, dh, e.col_blue, "Octave ", m.defFont, m.defFontSz, e.col_grey8, m.oct,{0, 1, 2, 3, 4, 5, 6, 7}) local scaleDrop = e.Droplist:new({1, 2, 3}, dx, dy + 90, dw, dh, e.col_blue, "Scale", m.defFont, m.defFontSz, e.col_grey8, 1, m.scalelist) -local t_Droplists = {keyDrop, octDrop, scaleDrop} +local t_Droplists = {keyDrop, octDrop, scaleDrop} -------------------------------------------------------------------------------- -- Randomiser Layer @@ -1277,7 +1277,7 @@ local t_noteSliders = {noteSldr01, noteSldr02, noteSldr03, noteSldr04, noteSldr0 local probSldrText = e.Textbox:new({1}, nx, 210, 510, 20, e.col_grey5, "Note Weight Sliders", m.defFont, m.defFontSz, e.col_grey7) -- Note octave doubler probability slider local octProbSldr = e.Vert_Slider:new({1}, nx+(np*13) + 10, ny, nw, nh, e.col_blue, "%", m.defFont, m.defFontSz, e.col_grey8, m.rndOctProb, 0, 0, 10, 1) -local octProbText = e.Textbox:new({1}, nx+(np*13) + 10, 210, (nw), 20, e.col_grey5, "Oct", m.defFont, m.defFontSz, e.col_grey7) +local octProbText = e.Textbox:new({1}, nx+(np*13) + 10, 210, (nw), 20, e.col_grey5, "Oct", m.defFont, m.defFontSz, e.col_grey7) -- Note randomiser options local noteOptionsCb = e.Checkbox:new({1}, nx+(np*15)-10, ny+30, 30, 30, e.col_orange, "", m.defFont, m.defFontSz, e.col_grey8, {0,0,0}, {"All / Sel Notes", "1st Note = Root", "Octave X2"}) local noteOptionText = e.Textbox:new({1}, nx+(np*14)+20, 210, (nw*4), 20, e.col_grey5, "Options", m.defFont, m.defFontSz, e.col_grey7) @@ -1373,7 +1373,7 @@ local t_Textboxes = {probSldrText, octProbText, seqGridText, seqSldrText, seqShi -------------------------------------------------------------------------------- -- GUI Functions START --------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -- Main window -------------------------------------------------------------------------------- @@ -1381,11 +1381,11 @@ local t_Textboxes = {probSldrText, octProbText, seqGridText, seqSldrText, seqShi zoomDrop.onLClick = function() -- window scaling local debug = false if debug or m.debug then ConMsg("\nzoomDrop.onLClick()") end - + if zoomDrop.val1 == 1 then e.gScale = 0.7 elseif zoomDrop.val1 == 2 then e.gScale = 0.8 elseif zoomDrop.val1 == 3 then e.gScale = 0.9 - elseif zoomDrop.val1 == 4 then e.gScale = 1 + elseif zoomDrop.val1 == 4 then e.gScale = 1 elseif zoomDrop.val1 == 5 then e.gScale = 1.1 elseif zoomDrop.val1 == 6 then e.gScale = 1.2 elseif zoomDrop.val1 == 7 then e.gScale = 1.4 @@ -1394,16 +1394,16 @@ zoomDrop.onLClick = function() -- window scaling elseif zoomDrop.val1 == 10 then e.gScale = 2.0 end pExtState.zoomDrop = zoomDrop.val1 - + if debug or m.debug then ConMsg("zoom = " .. tostring(e.gScale)) end - - -- set soom + + -- set soom if pExtState.win_x ~= m.win_x then __, m.win_x, m.win_y, __, __ = gfx.dock(-1,0,0,0,0) pExtState.win_x = m.win_x pExtState.win_y = m.win_y end - + m.zoomF = true end -- Layer 1 button @@ -1421,13 +1421,13 @@ layerBtn01.onLClick = function() -- randomiser v:getSetLabelColour(e.gol_grey7) end -- set current layer to highlight colour - layerBtn01:getSetColour(e.col_green) + layerBtn01:getSetColour(e.col_green) layerBtn01:getSetLabelColour(e.col_grey8) -- set zoom state flag e.gScaleState = true -- set project ext state pExtState.activeLayer = e.gActiveLayer - + end -- Layer 2 button layerBtn02.onLClick = function() -- sequencer @@ -1444,12 +1444,12 @@ layerBtn02.onLClick = function() -- sequencer v:getSetLabelColour(e.gol_grey7) end -- set current layer to highlight colour - layerBtn02:getSetColour(e.col_yellow) + layerBtn02:getSetColour(e.col_yellow) layerBtn02:getSetLabelColour(e.col_grey8) -- set zoom state flag e.gScaleState = true -- set project ext state - pExtState.activeLayer = e.gActiveLayer + pExtState.activeLayer = e.gActiveLayer end -- Layer 3 button layerBtn03.onLClick = function() -- euclidean @@ -1466,12 +1466,12 @@ layerBtn03.onLClick = function() -- euclidean v:getSetLabelColour(e.gol_grey7) end -- set current layer to highlight colour - layerBtn03:getSetColour(e.col_orange) + layerBtn03:getSetColour(e.col_orange) layerBtn03:getSetLabelColour(e.col_grey8) - -- set zoom state flag + -- set zoom state flag e.gScaleState = true -- set project ext state - pExtState.activeLayer = e.gActiveLayer + pExtState.activeLayer = e.gActiveLayer end -- Layer 4 button layerBtn04.onLClick = function() -- options @@ -1488,18 +1488,18 @@ layerBtn04.onLClick = function() -- options v:getSetLabelColour(e.gol_grey7) end -- set current layer to highlight colour - layerBtn04:getSetColour(e.col_grey6) + layerBtn04:getSetColour(e.col_grey6) layerBtn04:getSetLabelColour(e.col_grey8) -- set zoom state flag e.gScaleState = true -- set project ext state - pExtState.activeLayer = e.gActiveLayer + pExtState.activeLayer = e.gActiveLayer end -- Undo button undoBtn.onLClick = function() -- undo local debug = false if debug or m.debug then ConMsg("\nundoBtn.onLClick()") end - + -- check for repeat flag, turn off if it's on... (kludge 101) UndoNoteBuf() InsertNotes() PrintNotes(m.notebuf[m.notebuf.i]) @@ -1508,38 +1508,38 @@ end redoBtn.onLClick = function() -- redo local debug = false if debug or m.debug then ConMsg("\nredoBtn.onLClick()") end - + if m.notebuf[m.notebuf.i + 1] ~= nil then --PrintNotes(m.notebuf[m.notebuf.i + 1]) m.notebuf.i = m.notebuf.i + 1 InsertNotes() --PrintNotes(m.notebuf[m.notebuf.i]) else - if debug or m.debug then ConMsg("nothing to redo...") end + if debug or m.debug then ConMsg("nothing to redo...") end end end -- Set default window options function SetDefaultWindowOpts() local debug = false if debug or m.debug then ConMsg("SetDefaultWinOpts()") end - + if pExtState.zoomDrop then zoomDrop.val1 = pExtState.zoomDrop end - + if pExtState.win_x then -- set the windown position m.win_x = pExtState.win_x m.win_y = pExtState.win_y end - + zoomDrop.onLClick() end -- Set default layer function SetDefaultLayer() local debug = false if debug or m.debug then ConMsg("SetDefaultLayer()") end - - if pExtState.activeLayer then + + if pExtState.activeLayer then if pExtState.activeLayer == 1 then layerBtn01.onLClick() elseif pExtState.activeLayer == 2 then layerBtn02.onLClick() elseif pExtState.activeLayer == 3 then layerBtn03.onLClick() @@ -1555,10 +1555,10 @@ end function SetDefaultRndOptions() local debug = false if debug or m.debug then ConMsg("SetDefaultRndOptions()") end - + -- if randomiser options were saved to project state, load them if pExtState.noteOptionsCb then - m.rndAllNotesF = pExtState.noteOptionsCb[1] == true and true or false + m.rndAllNotesF = pExtState.noteOptionsCb[1] == true and true or false m.rndFirstNoteF = pExtState.noteOptionsCb[2] == true and true or false m.rndOctX2F = pExtState.noteOptionsCb[3] == true and true or false end @@ -1572,11 +1572,11 @@ end noteOptionsCb.onLClick = function() local debug = false if debug or m.debug then ConMsg("noteOptionsCb.onLClick()") end - + m.rndAllNotesF = noteOptionsCb.val1[1] == 1 and true or false -- All / Sel Notes m.rndFirstNoteF = noteOptionsCb.val1[2] == 1 and true or false -- 1st Note Root m.rndOctX2F = noteOptionsCb.val1[3] == 1 and true or false -- Octave X2 - + pExtState.noteOptionsCb = {m.rndAllNotesF, m.rndFirstNoteF, m.rndOctX2F} if debug or m.debug then PrintTable(noteOptionsCb.val1) end @@ -1586,11 +1586,11 @@ end keyDrop.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nkeyDrop.onLClick()") end - + m.key = keyDrop.val1 - m.root = SetRootNote(m.oct, m.key) + m.root = SetRootNote(m.oct, m.key) UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) - + -- set project ext state pExtState.key = m.key pExtState.root = m.root @@ -1599,11 +1599,11 @@ end octDrop.onLClick = function() local debug = false if debug or m.debug then ConMsg("\noctDrop.onLClick()") end - + m.oct = octDrop.val1 m.root = SetRootNote(m.oct, m.key) - - -- set project ext state + + -- set project ext state pExtState.oct = m.oct pExtState.root = m.root end @@ -1612,33 +1612,33 @@ scaleDrop.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nscaleDrop.onLClick()") end SetScale(scaleDrop.val2[scaleDrop.val1], m.scales, m.preNoteProbTable) - if m.rndPermuteF then + if m.rndPermuteF then noteOptionsCb.val1[1] = 0 m.rndAllNotesF = false end UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) - -- set project ext state + -- set project ext state pExtState.curScaleName = scaleDrop.val2[scaleDrop.val1] -end +end -- Set default scale options function SetDefaultScaleOpts() local debug = false if debug or m.debug then ConMsg("SetDefaultScaleOpts()") end - + -- if key saved in project state, load it - if pExtState.key then + if pExtState.key then m.key = math.floor(tonumber(pExtState.key)) keyDrop.val1 = m.key end -- if octave saved in project state, load it - if pExtState.oct then + if pExtState.oct then m.oct = math.floor(tonumber(pExtState.oct)) octDrop.val1 = m.oct end -- set the midi note number for scale root - m.root = SetRootNote(m.oct, m.key) + m.root = SetRootNote(m.oct, m.key) -- create a scale name lookup table for the gui (scaleDrop) for k, v in pairs(m.scales) do m.scalelist[k] = m.scales[k]["name"] @@ -1648,9 +1648,9 @@ function SetDefaultScaleOpts() m.curScaleName = pExtState.curScaleName end -- update the scale dropbox val1 to match the scale table index - for k, v in pairs(m.scales) do + for k, v in pairs(m.scales) do if v.name == m.curScaleName then scaleDrop.val1 = k end - end + end SetScale(m.curScaleName, m.scales, m.preNoteProbTable) --set chosen scale UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) -- set sliders labels to current scale notes @@ -1660,7 +1660,7 @@ end function SetDefaultRndSliders() local debug = false if debug or m.debug then ConMsg("SetDefaultRndSliders()") end - + -- if randomiser sliders were saved to project state, load them if pExtState.noteSliders then for k, v in pairs(t_noteSliders) do @@ -1681,15 +1681,15 @@ end probSldrText.onRClick = function() local debug = false if debug or m.debug then ConMsg("\nprobSldrText.onRClick()") end - + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Note Sliders") - - if result == 1 then + + if result == 1 then for k, v in pairs(t_noteSliders) do -- reset the sliders if v.label ~= "" then v.val1 = 1 end end -- in pairs(t_noteSliders) - + if pExtState.noteSliders then -- write the new proj ext state for k, v in pairs(t_noteSliders) do if v.label ~= "" then pExtState.noteSliders[k] = v.val1 end @@ -1702,11 +1702,11 @@ end octProbText.onRClick = function() local debug = false if debug or m.debug then ConMsg("\noctProbText.onRClick()") end - + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Octave Slider") - - if result == 1 then + + if result == 1 then octProbSldr.val1 = m.rndOctProb if pExtState.rndOctProb then -- write the new proj ext state pExtState.rndOctProb = nil @@ -1721,9 +1721,9 @@ end function SetDefaultSeqOptions() local debug = false if debug or m.debug then ConMsg("SetDefaultSeqOptions()") end - + -- if sequencer options were saved to project state, load them - if pExtState.seqOptionsCb then + if pExtState.seqOptionsCb then m.seqF = pExtState.seqOptionsCb[1] == true and true or false m.seqFirstNoteF = pExtState.seqOptionsCb[2] == true and true or false m.seqAccentF = pExtState.seqOptionsCb[3] == true and true or false @@ -1731,7 +1731,7 @@ function SetDefaultSeqOptions() m.seqRndNotesF = pExtState.seqOptionsCb[5] == true and true or false m.seqRepeatF = pExtState.seqOptionsCb[6] == true and true or false end - + -- set sequencer options using defaults, or loaded project state seqOptionsCb.val1[1] = (true and m.seqF) and 1 or 0 -- generate seqOptionsCb.val1[2] = (true and m.seqFirstNoteF) and 1 or 0 -- 1st Note Always @@ -1739,28 +1739,28 @@ function SetDefaultSeqOptions() seqOptionsCb.val1[4] = (true and m.seqLegatoF) and 1 or 0 -- legato seqOptionsCb.val1[5] = (true and m.seqRndNotesF) and 1 or 0 -- random notes seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 -- repeat - + -- store the project state pExtState.seqOptionsCb = {m.seqF, m.seqFirstNoteF, m.seqAccentF, m.seqLegatoF, m.seqRndNotesF, m.seqRepeatF} end --- Sequencer options toggle logic +-- Sequencer options toggle logic seqOptionsCb.onLClick = function() local debug = false if debug or m.debug then ConMsg("seqOptionsCb.onLClick()") end - + m.seqF = seqOptionsCb.val1[1] == 1 and true or false -- Generate m.seqFirstNoteF = seqOptionsCb.val1[2] == 1 and true or false -- 1st Note Always m.seqAccentF = seqOptionsCb.val1[3] == 1 and true or false -- Accent m.seqLegatoF = seqOptionsCb.val1[4] == 1 and true or false -- Legato m.seqRndNotesF = seqOptionsCb.val1[5] == 1 and true or false -- Randomise Notes m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Repeat - + if pExtState.seqOptionsCb then if pExtState.seqOptionsCb[6] ~= m.seqRepeatF then InsertNotes() end else if m.seqRepeatF then InsertNotes() end end - + pExtState.seqOptionsCb = {m.seqF, m.seqFirstNoteF, m.seqAccentF, m.seqLegatoF, m.seqRndNotesF, m.seqRepeatF} if debug or m.debug then PrintTable(seqOptionsCb.val1) end @@ -1772,7 +1772,7 @@ function SetDefaultSeqGridSliders() if debug or m.debug then ConMsg("SetDefaultSeqGridSliders()") end GetReaperGrid(seqGridRad) - SetSeqGridSizes(t_seqSliders) + SetSeqGridSizes(t_seqSliders) if seqGridRad.val1 == 1 then if pExtState.seqGrid16 then -- 1/16 grid @@ -1785,7 +1785,7 @@ function SetDefaultSeqGridSliders() end end -- pExtState.seqGrid16 - elseif seqGridRad.val1 == 2 then + elseif seqGridRad.val1 == 2 then if pExtState.seqGrid8 then -- 1/8 grid for k, v in pairs(t_seqSliders) do v.val1 = pExtState.seqGrid8[k] @@ -1796,7 +1796,7 @@ function SetDefaultSeqGridSliders() end end -- pExtState.seqGrid8 - elseif seqGridRad.val1 == 3 then + elseif seqGridRad.val1 == 3 then if pExtState.seqGrid4 then -- 1/4 grid for k, v in pairs(t_seqSliders) do v.val1 = pExtState.seqGrid4[k] @@ -1805,21 +1805,21 @@ function SetDefaultSeqGridSliders() for k, v in pairs(t_seqSliders) do v.val1 = m.seqGrid4[k] end - end + end end -- pExtState.seqGrid4 - - if debug or m.debug then + + if debug or m.debug then for k, v in pairs(t_seqSliders) do ConMsg("t_seqSliders.val1 (4) = " .. tostring(v.val1)) end end - + end -- Reset sequencer grid sliders seqSldrText.onRClick = function() local debug = false if debug or m.debug then ConMsg("\nseqSldrText.onLClick()") end - + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Sequence Sliders") if result == 1 then @@ -1828,19 +1828,19 @@ seqSldrText.onRClick = function() v.val1 = m.seqGrid16[k] end -- in pairs(t_seqSliders) pExtState.seqGrid16 = nil - + elseif seqGridRad.val1 == 2 then -- 1/8ths for k, v in pairs(t_seqSliders) do -- reset the sliders v.val1 = m.seqGrid8[k] end -- in pairs(t_seqSliders) pExtState.seqGrid8 = nil - + elseif seqGridRad.val1 == 3 then -- 1/4ths for k, v in pairs(t_seqSliders) do -- reset the sliders v.val1 = m.seqGrid4[k] end -- in pairs(t_seqSliders) pExtState.seqGrid4 = nil - + end -- seqGridRad end -- result end @@ -1849,24 +1849,24 @@ end function SetDefaultAccLegSliders() local debug = false if debug or m.debug then ConMsg("SetDefaultAccLegSliders()") end - + -- if seq accent & legato sliders were saved to project state, load them - if pExtState.seqAccRSldrLo then + if pExtState.seqAccRSldrLo then seqAccRSldr.val1 = pExtState.seqAccRSldrLo else seqAccRSldr.val1 = m.accentLow end - if pExtState.seqAccRSldrHi then + if pExtState.seqAccRSldrHi then seqAccRSldr.val2 = pExtState.seqAccRSldrHi else seqAccRSldr.val2 = m.accentHigh end - if pExtState.seqAccProb then + if pExtState.seqAccProb then seqAccProbSldr.val1 = pExtState.seqAccProb else seqAccProbSldr.val1 = m.accentProb end - if pExtState.seqLegProb then + if pExtState.seqLegProb then seqLegProbSldr.val1 = pExtState.seqLegProb else seqLegProbSldr.val1 = m.legatoProb @@ -1876,13 +1876,13 @@ end -- function seqAccSldrText.onRClick = function() local debug = false if debug or m.debug then ConMsg("\nseqAccSldrText.onRClick()") end - + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Accent Sliders") - - if result == 1 then + + if result == 1 then seqAccRSldr.val1 = m.accentLow - if pExtState.seqAccRSldrLo then pExtState.seqAccRSldrLo = nil end + if pExtState.seqAccRSldrLo then pExtState.seqAccRSldrLo = nil end seqAccRSldr.val2 = m.accentHigh if pExtState.seqAccRSldrHi then pExtState.seqAccRSldrHi = nil end seqAccProbSldr.val1 = m.accentProb @@ -1893,11 +1893,11 @@ end seqLegSldrText.onRClick = function() local debug = false if debug or m.debug then ConMsg("\nseqLegSldrText.onLClick()") end - + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Legato Slider") - - if result == 1 then + + if result == 1 then seqLegProbSldr.val1 = m.legatoProb if pExtState.seqLegProb then pExtState.seqLegProb = nil end end -- result @@ -1907,7 +1907,7 @@ end function SetDefaultSeqShift() local debug = false if debug or m.debug then ConMsg("SetDefaultSeqShift()") end - + m.seqShift = 0 m.seqShiftMin = 0 m.seqShiftMax = 0 @@ -1917,8 +1917,8 @@ end function ResetSeqShifter() local debug = false if debug or m.debug then ConMsg("ResetSeqShifter()") end - - m.seqShiftF = false + + m.seqShiftF = false m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) end @@ -1939,7 +1939,7 @@ end seqShiftText.onRClick = function() local debug = false if debug or m.debug then ConMsg("\nseqShiftText.onRClick") end - + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Note Shift|Glue Shift") @@ -1949,16 +1949,16 @@ seqShiftText.onRClick = function() elseif result == 2 then GlueSeqShifter() end -- result -end +end -- Sequence shifter left seqShiftLBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nseqShiftLBtn()") end - + local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() m.seqShiftMin = -(math.floor(itemLength / gridSize)-1) - + if m.seqShift <= m.seqShiftMin then m.seqShift = 0 m.seqShiftF = false @@ -1966,7 +1966,7 @@ seqShiftLBtn.onLClick = function() m.seqShift = m.seqShift - 1 m.seqShiftF = true end - + seqShiftVal.label = tostring(m.seqShift) InsertNotes() end @@ -1974,18 +1974,18 @@ end seqShiftRBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nseqShiftRBtn()") end - + local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() m.seqShiftMax = math.floor(itemLength / gridSize) - 1 - if m.seqShift >= m.seqShiftMax then + if m.seqShift >= m.seqShiftMax then m.seqShift = 0 m.seqShiftF = false else m.seqShift = m.seqShift + 1 m.seqShiftF = true - end + end seqShiftVal.label = tostring(m.seqShift) InsertNotes() @@ -1995,25 +1995,25 @@ end function SetDefaultSeqRepeat() local debug = false if debug or m.debug then ConMsg("SetDefaultSeqRepeat()") end - + GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() - + -- start m.loopStartG = 1 seqLoopStartDrop.val1 = m.loopStartG - + -- length m.loopLenG = 1 - seqLoopLenDrop.val1 = m.loopLenG - + seqLoopLenDrop.val1 = m.loopLenG + -- amount m.loopNum = 1 seqLoopNumDrop.val1 = m.loopNum m.loopMaxRep = math.floor(itemLength / gridSize) - + for i = 1, m.loopMaxRep do seqLoopStartDrop.val2[i] = i seqLoopNumDrop.val2[i] = i @@ -2025,7 +2025,7 @@ function ResetSeqRepeater() local debug = false if debug or m.debug then ConMsg("ResetSeqRepeater()") end -- reset the GUI and repeat flag - m.seqRepeatF = false + m.seqRepeatF = false seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 -- reset the drop down lists seqLoopStartDrop.val1 = 1; m.loopStartG = 1 @@ -2038,15 +2038,15 @@ end function GlueSeqRepeater() local debug = false if debug or m.debug then ConMsg("GlueSeqRepeater()") end - m.loopGlueF = true + m.loopGlueF = true InsertNotes() - + -- reset the shifter (implicit when glueing the loop) ResetSeqShifter() - + -- reset the GUI and repeat flag ResetSeqRepeater() - + -- reset the drop down lists and pExtState seqLoopStartDrop.val1 = 1; m.loopStartG = 1 seqLoopLenDrop.val1 = 1; m.loopLenG = 1 @@ -2056,48 +2056,48 @@ end seqLoopText.onRClick = function() local debug = false if debug or m.debug then ConMsg("\nseqLoopText.onRClick") end - + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Repeat|Glue Repeat") - if result == 1 then + if result == 1 then ResetSeqRepeater() InsertNotes() elseif result == 2 then GlueSeqRepeater() end -- result - + end -- onRClick -- Sequencer repeater functions seqLoopStartDrop.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nseqLoopStartDrop.onLClick()") end - + GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) local gridSizeP = m.reaGrid * m.ppqn - if debug or m.debug then ConMsg("gridSizeP = " .. tostring(gridSizeP)) end + if debug or m.debug then ConMsg("gridSizeP = " .. tostring(gridSizeP)) end local itemLenP = GetItemLength() - if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end + if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end local itemLenG = math.floor(itemLenP / gridSizeP) - if debug or m.debug then ConMsg("itemLenG = " .. tostring(itemLenG)) end + if debug or m.debug then ConMsg("itemLenG = " .. tostring(itemLenG)) end local remLenG = itemLenG - (seqLoopStartDrop.val1 -1) - if debug or m.debug then ConMsg("remLenG = " .. tostring(remLenG)) end - + if debug or m.debug then ConMsg("remLenG = " .. tostring(remLenG)) end + -- set the start point lookup table for i = 1, itemLenG do seqLoopStartDrop.val2[i] = i m.t_loopStart[i] = i end m.loopStartG = seqLoopStartDrop.val1 - + -- check the loop length doesn't exceed the remaining item length if seqLoopLenDrop.val1 > remLenG then seqLoopLenDrop.val1 = remLenG end seqLoopLenDrop.val2 = {} for i = 1, remLenG do seqLoopLenDrop.val2[i] = i - end + end m.loopLenG = seqLoopLenDrop.val1 - + -- check the loop amount doesn't exceed the remaining item length while seqLoopNumDrop.val1 * m.loopLenG > remLenG do seqLoopNumDrop.val1 = seqLoopNumDrop.val1 - 1 @@ -2106,39 +2106,39 @@ seqLoopStartDrop.onLClick = function() local maxLoops = math.floor(remLenG / m.loopLenG) for i = 1, maxLoops do seqLoopNumDrop.val2[i] = i - end + end m.loopNum = seqLoopNumDrop.val1 - + if m.seqRepeatF then InsertNotes() end if debug or m.debug then ConMsg("m.loopStartG = " .. tostring(m.loopStartG)) end if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end - if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end + if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end end -- Sequencer repeat length seqLoopLenDrop.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nseqLoopLenDrop.onLClick()") end - + GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) local gridSizeP = m.reaGrid * m.ppqn - if debug or m.debug then ConMsg("gridSizeP = " .. tostring(gridSizeP)) end + if debug or m.debug then ConMsg("gridSizeP = " .. tostring(gridSizeP)) end local itemLenP = GetItemLength() - if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end + if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end local itemLenG = math.floor(itemLenP / gridSizeP) - if debug or m.debug then ConMsg("itemLenG = " .. tostring(itemLenG)) end + if debug or m.debug then ConMsg("itemLenG = " .. tostring(itemLenG)) end local remLenG = itemLenG - (seqLoopStartDrop.val1 -1) - if debug or m.debug then ConMsg("remLenG = " .. tostring(remLenG)) end - + if debug or m.debug then ConMsg("remLenG = " .. tostring(remLenG)) end + -- check the loop length doesn't exceed the remaining item length if seqLoopLenDrop.val1 > remLenG then seqLoopLenDrop.val1 = remLenG end seqLoopLenDrop.val2 = {} for i = 1, remLenG do seqLoopLenDrop.val2[i] = i - end + end m.loopLenG = seqLoopLenDrop.val1 - + -- check the loop amount doesn't exceed the remaining item length while seqLoopNumDrop.val1 * m.loopLenG > remLenG do seqLoopNumDrop.val1 = seqLoopNumDrop.val1 - 1 @@ -2147,30 +2147,30 @@ seqLoopLenDrop.onLClick = function() local maxLoops = math.floor(remLenG / m.loopLenG) for i = 1, maxLoops do seqLoopNumDrop.val2[i] = i - end + end m.loopNum = seqLoopNumDrop.val1 - + if m.seqRepeatF then InsertNotes() end if debug or m.debug then ConMsg("m.loopStartG = " .. tostring(m.t_loopStart[m.loopStartG])) end if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end - if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end + if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end end -- Sequencer repeat amount seqLoopNumDrop.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nseqLoopNumDrop.onLClick()") end - + GetReaperGrid() -- sets m.reaGrid (.25 / 0.5 / 0.1) local gridSizeP = m.reaGrid * m.ppqn - if debug or m.debug then ConMsg("gridSizeP = " .. tostring(gridSizeP)) end + if debug or m.debug then ConMsg("gridSizeP = " .. tostring(gridSizeP)) end local itemLenP = GetItemLength() - if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end + if debug or m.debug then ConMsg("itemLenP = " .. tostring(itemLenP)) end local itemLenG = math.floor(itemLenP / gridSizeP) - if debug or m.debug then ConMsg("itemLenG = " .. tostring(itemLenG)) end + if debug or m.debug then ConMsg("itemLenG = " .. tostring(itemLenG)) end local remLenG = itemLenG - (seqLoopStartDrop.val1 -1) - if debug or m.debug then ConMsg("remLenG = " .. tostring(remLenG)) end - + if debug or m.debug then ConMsg("remLenG = " .. tostring(remLenG)) end + -- check the loop amount doesn't exceed the remaining item length while seqLoopNumDrop.val1 * m.loopLenG > remLenG do seqLoopNumDrop.val1 = seqLoopNumDrop.val1 - 1 @@ -2179,14 +2179,14 @@ seqLoopNumDrop.onLClick = function() local maxLoops = math.floor(remLenG / m.loopLenG) for i = 1, maxLoops do seqLoopNumDrop.val2[i] = i - end + end m.loopNum = seqLoopNumDrop.val1 - + if m.seqRepeatF then InsertNotes() end if debug or m.debug then ConMsg("m.loopStartG = " .. tostring(m.t_loopStart[m.loopStartG])) end if debug or m.debug then ConMsg("m.loopLenG = " .. tostring(m.loopLenG)) end - if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end + if debug or m.debug then ConMsg("m.loopNum = " .. tostring(m.loopNum)) end end -------------------------------------------------------------------------------- @@ -2196,14 +2196,14 @@ end function SetDefaultEucOptions() local debug = false if debug or m.debug then ConMsg("SetDefaultEucOptions()") end - + -- if euclidean options were saved to project state, load them - if pExtState.eucOptionsCb then + if pExtState.eucOptionsCb then m.eucF = pExtState.eucOptionsCb[1] == true and true or false m.eucAccentF = pExtState.eucOptionsCb[2] == true and true or false m.eucRndNotesF = pExtState.eucOptionsCb[3] == true and true or false end - + -- create a euclid preset name lookup table for the gui (euclidDrop) for k, v in pairs(m.euclidPresets) do m.euclidlist[k] = m.euclidPresets[k]["name"] @@ -2213,12 +2213,12 @@ function SetDefaultEucOptions() m.curEuclidName = pExtState.curEuclidName end -- update the euclid dropbox val1 to match the euclid table index - for k, v in pairs(m.euclidPresets) do + for k, v in pairs(m.euclidPresets) do if v.name == m.curEuclidName then euclidDrop.val1 = k end - end + end -- SetEuclid(m.curEuclidName, m.euclidPresets) --set chosen preset - + -- set euclidean options using defaults, or loaded project state eucOptionsCb.val1[1] = (true and m.eucF) and 1 or 0 -- generate eucOptionsCb.val1[2] = (true and m.eucAccentF) and 1 or 0 -- accents @@ -2229,11 +2229,11 @@ end eucOptionsCb.onLClick = function() local debug = false if debug or m.debug then ConMsg("eucOptionsCb.onLClick()") end - + m.eucF = eucOptionsCb.val1[1] == 1 and true or false -- Generate m.eucAccentF = eucOptionsCb.val1[2] == 1 and true or false -- Accent m.eucRndNotesF = eucOptionsCb.val1[3] == 1 and true or false -- Randomise notes - + pExtState.eucOptionsCb = {m.eucF, m.eucAccentF, m.eucRndNotesF} if debug or m.debug then PrintTable(eucOptionsCb.val1) end @@ -2243,15 +2243,15 @@ end function SetDefaultEucSliders() local debug = false if debug or m.debug then ConMsg("SetDefaultEucSliders()") end - + -- if euclidean sliders were saved to project state, load them if pExtState.eucSliders then for k, v in pairs(t_euclidSliders) do v.val1 = pExtState.eucSliders[k] end - + else - + euclidPulsesSldr.val1 = m.eucPulses euclidStepsSldr.val1 = m.eucSteps euclidRotationSldr.val1 = m.eucRot @@ -2261,11 +2261,11 @@ end txtEuclidLabel.onRClick = function() local debug = false if debug or m.debug then ConMsg("\ntxtEuclidLabel.onLClick()") end - + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y local result = gfx.showmenu("Reset Euclid Sliders") - - if result == 1 then + + if result == 1 then euclidPulsesSldr.val1 = m.eucPulses euclidStepsSldr.val1 = m.eucSteps euclidRotationSldr.val1 = m.eucRot @@ -2273,11 +2273,11 @@ txtEuclidLabel.onRClick = function() end -- result end --- Euclid pulses slider +-- Euclid pulses slider euclidPulsesSldr.onMove = function() local debug = false if debug or m.debug then ConMsg("euclidPlusesSldr.onMove()") end - + if euclidPulsesSldr.val1 > euclidStepsSldr.val1 then -- pulses > steps euclidStepsSldr.val1 = euclidPulsesSldr.val1 euclidRotationSldr.max = euclidStepsSldr.val1 @@ -2302,7 +2302,7 @@ end euclidRotationSldr.onMove = function() local debug = false if debug or m.debug then ConMsg("euclidRotationSldr.onMove()") end - + euclidRotationSldr.max = euclidStepsSldr.val1 if euclidRotationSldr.val1 > euclidStepsSldr.val1 then euclidRotationSldr.val1 = euclidStepsSldr.val1 @@ -2314,24 +2314,24 @@ end euclidDrop.onLClick = function() local debug = false if debug or m.debug then ConMsg("\neuclidDrop.onLClick()") end - - local p = {} - + + local p = {} + for i = 1, #m.euclidPresets, 1 do if euclidDrop.val2[euclidDrop.val1] == m.euclidPresets[i].name then p = m.euclidPresets[i] end end - + euclidPulsesSldr.val1 = p[1] euclidStepsSldr.val1 = p[2] euclidRotationSldr.val1 = p[3] euclidRotationSldr.max = euclidStepsSldr.val1 - -- save pExtState + -- save pExtState pExtState.eucSliders = {p[1], p[2], p[3]} pExtState.curEuclidName = euclidDrop.val2[euclidDrop.val1] -end +end -- Main action elements -- Randomiser @@ -2350,37 +2350,37 @@ randomBtn.onLClick = function() GenOctaveTable(m.octProbTable, octProbSldr) GetNotesFromTake() -- grab the current take data RandomiseNotesPoly() - - -- set project ext state + + -- set project ext state pExtState.noteSliders = {} for k, v in pairs(t_noteSliders) do pExtState.noteSliders[k] = v.val1 end pExtState.rndOctProb = octProbSldr.val1 -end +end -- Sequencer sequenceBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nsequenceBtn.onLClick()") end if not m.activeTake then return end - + -- turn off and reset shift local t_shift = table.pack(m.seqShift, m.seqShiftMin, m.seqShiftMax) -- required? ResetSeqShifter() - + -- backup repeat - local t_repeat = table.pack(m.loopStartG, m.loopLenG, m.loopNum, m.seqRepeatF) - + local t_repeat = table.pack(m.loopStartG, m.loopLenG, m.loopNum, m.seqRepeatF) + if m.seqF then if m.seqRepeatF then -- temporarily turn off repeat, if it was on m.seqRepeatF = false -- remember it was on... - m.seqRepeatState = true + repeatState = true seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 seqLoopStartDrop.val1 = 1; m.loopStartG = 1 seqLoopLenDrop.val1 = 1; m.loopLenG = 1 seqLoopNumDrop.val1 = 1; m.loopNum = 1 InsertNotes() - end + end SetSeqGridSizes(t_seqSliders) GenProbTable(m.preSeqProbTable, t_seqSliders, m.seqProbTable) GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) @@ -2389,27 +2389,27 @@ sequenceBtn.onLClick = function() GenSequence(m.seqProbTable, m.accProbTable, seqAccRSldr, m.legProbTable) if m.seqRndNotesF then randomBtn.onLClick() end -- restore and turn on repeat, if it was previously on... - if m.seqRepeatState then + if repeatState then m.loopStartG, m.loopLenG, m.loopNum, m.seqRepeatF = table.unpack(t_repeat) - seqLoopNumDrop.val1 = m.loopNum + seqLoopNumDrop.val1 = m.loopNum seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 seqLoopStartDrop.val1 = m.loopStartG seqLoopLenDrop.val1 = m.loopLenG seqLoopNumDrop.val1 = m.loopNum InsertNotes() - m.seqRepeatState = false + repeatState = false end - -- if m.seqRepeatF then InsertNotes() end - + -- if m.seqRepeatF then InsertNotes() end + else -- not m.seqF GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) GenLegatoTable(m.legProbTable, seqLegProbSldr) - GetNotesFromTake() + GetNotesFromTake() GenNoteAttributes(m.seqAccentF, m.accProbTable, seqAccRSldr, m.seqLegatoF, m.legProbTable) - - if m.seqRndNotesF then randomBtn.onLClick() end + + if m.seqRndNotesF then randomBtn.onLClick() end end -- m.seqF - + -- set project ext state if seqGridRad.val1 == 1 then -- 1/16 grid pExtState.seqGrid16 = {} @@ -2428,7 +2428,7 @@ sequenceBtn.onLClick = function() for k, v in pairs (t_seqSliders) do pExtState.seqGrid4[k] = v.val1 end - end + end pExtState.seqOptionsCb = {m.seqF, m.seqFirstNoteF, m.seqAccentF, m.seqLegatoF, m.seqRndNotesF, m.seqRepeatF} pExtState.seqAccRSldrLo = seqAccRSldr.val1 pExtState.seqAccRSldrHi = seqAccRSldr.val2 @@ -2439,9 +2439,9 @@ end seqGridRad.onLClick = function() -- change grid size local debug = false if debug or m.debug then ConMsg("\nseqGridRad.onLClick()") end - + if m.activeTake then - + if seqGridRad.val1 == 1 then -- 1/16 grid reaper.MIDIEditor_OnCommand(m.activeEditor, 40192) -- set grid if pExtState.seqGrid16 then @@ -2489,7 +2489,7 @@ end euclidBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\neuclidBtn.onLClick()") end - + -- turn off and reset shifter and repeater ResetSeqShifter() ResetSeqRepeater() @@ -2500,28 +2500,28 @@ euclidBtn.onLClick = function() GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) GetNotesFromTake() GenBjorklund(euclidPulsesSldr, euclidStepsSldr, euclidRotationSldr, m.accProbTable, seqAccRSldr) - if m.eucRndNotesF then + if m.eucRndNotesF then randomBtn.onLClick() -- call RandomiseNotes end - + else -- not m.eucF if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) GetNotesFromTake() GenNoteAttributes(m.eucAccentF, m.accProbTable, seqAccRSldr, false, m.legProbTable) - if m.eucRndNotesF then + if m.eucRndNotesF then if debug or m.debug then ConMsg("m.eucRndNotesF = " .. tostring(m.eucRndNotesF)) end randomBtn.onLClick() -- call RandomiseNotes - end + end end -- m.eucF - - -- set project ext state + + -- set project ext state pExtState.eucSliders = {} for k, v in pairs(t_euclidSliders) do pExtState.eucSliders[k] = v.val1 end - - + + end -- m.activeTake end @@ -2531,12 +2531,12 @@ end function DrawGUI() for key, winElms in pairs(t_winElements) do winElms:draw() end for key, winLays in pairs(t_winLayers) do winLays:draw() end - --for key, frame in pairs(t_Frames) do frame:draw() end + --for key, frame in pairs(t_Frames) do frame:draw() end for key, check in pairs(t_Checkboxes) do check:draw() end - for key, radio in pairs(t_RadButtons) do radio:draw() end + for key, radio in pairs(t_RadButtons) do radio:draw() end for key, btn in pairs(t_Buttons) do btn:draw() end for key, dlist in pairs(t_Droplists) do dlist:draw() end - for key, dlist2 in pairs(t_Droplists2) do dlist2:draw() end + for key, dlist2 in pairs(t_Droplists2) do dlist2:draw() end --for key, knb in pairs(t_Knobs) do knb:draw() end for key, rsliders in pairs(t_RSliders) do rsliders:draw() end for key, nsldrs in pairs(t_noteSliders) do nsldrs:draw() end @@ -2561,9 +2561,9 @@ function InitMidiExMachina() math.randomseed(os.time()) for i = 1, 15 do math.random() end -- lua quirk, first random call always returns the same value... reaper.ClearConsole() - local debug = false - if debug or m.debug then ConMsg("InitMidiExMachina()") end - + local debug = false + if debug or m.debug then ConMsg("InitMidiExMachina()") end + -- grab the midi editor, and active take m.activeEditor = reaper.MIDIEditor_GetActive() if m.activeEditor then @@ -2583,15 +2583,15 @@ function InitMidiExMachina() end if not m.activeTake then ConMsg("InitMidiExMachina() - No Active Take") end end -- m.activeEditor - + -- Load ProjectExtState __, pExtStateStr = reaper.GetProjExtState(0, "MEM", "pExtState") - if pExtStateStr ~= "" then + if pExtStateStr ~= "" then pExtState = unpickle(pExtStateStr) end -- pExtStateStr - + -- set GUI defaults or restore from project state - SetDefaultWindowOpts(); SetDefaultLayer() + SetDefaultWindowOpts(); SetDefaultLayer() SetDefaultScaleOpts() SetDefaultRndOptions(); SetDefaultRndSliders() SetDefaultSeqOptions(); SetDefaultSeqShift(); SetDefaultSeqRepeat() @@ -2608,9 +2608,9 @@ end function InitGFX() local debug = false if debug or m.debug then ConMsg("\nInitGFX()") end - + -- Init window ------ - gfx.clear = RGB2Packed(table.unpack(m.win_bg)) + gfx.clear = RGB2Packed(table.unpack(m.win_bg)) gfx.init(m.win_title, m.win_w * e.gScale, m.win_h * e.gScale, m.win_dockstate, m.win_x, m.win_y) -- Last mouse position and state gLastMouseCap, gLastMouseX, gLastMouseY = 0, 0, 0 @@ -2625,13 +2625,13 @@ function MainLoop() if gfx.mouse_cap & 1 == 1 and gLastMouseCap & 1 == 0 or -- L mouse gfx.mouse_cap & 2 == 2 and gLastMouseCap & 2 == 0 or -- R mouse gfx.mouse_cap & 64 == 64 and gLastMouseCap & 64 == 0 then -- M mouse - gMouseOX, gMouseOY = gfx.mouse_x, gfx.mouse_y + gMouseOX, gMouseOY = gfx.mouse_x, gfx.mouse_y end -- Set modifier keys Ctrl = gfx.mouse_cap & 4 == 4 Shift = gfx.mouse_cap & 8 == 8 Alt = gfx.mouse_cap & 16 == 16 - + -- if resized, set scale flag and reset gfx if m.zoomF == true then if debug or m.debug then ConMsg("m.zoomF == true") end @@ -2639,40 +2639,40 @@ function MainLoop() gfx.quit() InitGFX() m.zoomF = false - end - + end + DrawGUI() e.gScaleState = false -- prevent zoom code from running every loop - + -- Save or reset last mouse state since GUI was refreshed gLastMouseCap = gfx.mouse_cap gLastMouseX, gLastMouseY = gfx.mouse_x, gfx.mouse_y gfx.mouse_wheel = 0 -- reset gfx.mouse_wheel - + -- Get passthrough key for play/stop (spacebar) char = gfx.getchar() if char == 32 then reaper.Main_OnCommand(40044, 0) end - + -- Defer 'MainLoop' if not explicitly quiting (esc) - if char ~= -1 and char ~= 27 then - reaper.defer(MainLoop) + if char ~= -1 and char ~= 27 then + reaper.defer(MainLoop) else if debug or m.debug then ConMsg("quitting.....") end InsertNotes() -- capture any shifted or repeated notes - + -- Check and save window position __, pExtState.win_x, pExtState.win_y, __, __ = gfx.dock(-1,0,0,0,0) - - -- Pickle + + -- Pickle pExtStateStr = pickle(pExtState) reaper.SetProjExtState(0, "MEM", "pExtState", pExtStateStr ) end - + -- Update Reaper GFX gfx.update() - + -- check for midi editor, take, and media item m.activeEditor = reaper.MIDIEditor_GetActive() if m.activeEditor then @@ -2693,7 +2693,7 @@ function MainLoop() end ShowMessage(msgText, 0) -- clear old messages -- check for changes in the active take if the "Permute" scale is selected - if scaleDrop.val2[scaleDrop.val1] == "Permute" then + if scaleDrop.val2[scaleDrop.val1] == "Permute" then __, pHash = reaper.MIDI_GetHash(m.activeTake, false, 0) if m.pHash ~= pHash then SetScale("Permute", m.scales, m.preNoteProbTable) @@ -2702,17 +2702,17 @@ function MainLoop() end -- m.pHash -- don't allow any note options that might upset permute... noteOptionsCb.val1[2] = 0; m.rndFirstNoteF = false - noteOptionsCb.val1[3] = 0; m.rndOctX2F = false - end -- scaleDrop + noteOptionsCb.val1[3] = 0; m.rndOctX2F = false + end -- scaleDrop -- check for grid changes local grid = m.reaGrid m.reaGrid, __, __ = reaper.MIDI_GetGrid(m.activeTake) - if grid ~= m.reaGrid then + if grid ~= m.reaGrid then GetReaperGrid(seqGridRad) seqGridRad.onLClick() -- update the sequence grid sizes end -- grid else -- handle m.activeTake error - ShowMessage(msgText, 1) + ShowMessage(msgText, 1) m.activeTake = nil end -- m.activeTake else -- handle m.activeEditor error @@ -2729,4 +2729,4 @@ end InitMidiExMachina() InitGFX() MainLoop() --------------------------------------------------------------------------------- \ No newline at end of file +-------------------------------------------------------------------------------- From 2bd06e73c70cf43f13d635afe605967f5ef5ed89 Mon Sep 17 00:00:00 2001 From: RobU23 Date: Wed, 29 Nov 2017 21:37:25 +0000 Subject: [PATCH 32/33] resize window position bugfix --- MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 4acde02..6fc8672 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -76,7 +76,7 @@ local p = require 'persistence' -- currently unused, i.e. no preset save, load, -------------------------------------------------------------------------------- m = {} -- all ex machina data -- user changeable defaults are marked with "(option)" -m.debug = false +m.debug = true -- window m.win_title = "RobU : MIDI Ex Machina - v1.37"; m.win_dockstate = 0 m.win_x = 10; m.win_y = 10; m.win_w = 900; m.win_h = 280 -- window dimensions @@ -1400,6 +1400,7 @@ zoomDrop.onLClick = function() -- window scaling -- set soom if pExtState.win_x ~= m.win_x then __, m.win_x, m.win_y, __, __ = gfx.dock(-1,0,0,0,0) + ConMsg(m.win_x, m.win_y) pExtState.win_x = m.win_x pExtState.win_y = m.win_y end @@ -2648,7 +2649,7 @@ function MainLoop() gLastMouseCap = gfx.mouse_cap gLastMouseX, gLastMouseY = gfx.mouse_x, gfx.mouse_y gfx.mouse_wheel = 0 -- reset gfx.mouse_wheel - + __, pExtState.win_x, pExtState.win_y, __, __ = gfx.dock(-1,0,0,0,0) -- Get passthrough key for play/stop (spacebar) char = gfx.getchar() if char == 32 then reaper.Main_OnCommand(40044, 0) end From 105d01cbfb96be50f5430154577697237c2e83a3 Mon Sep 17 00:00:00 2001 From: RobU23 Date: Fri, 1 Dec 2017 21:47:54 +0000 Subject: [PATCH 33/33] small update to resizing --- MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 6fc8672..c7b46f3 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -1397,10 +1397,11 @@ zoomDrop.onLClick = function() -- window scaling if debug or m.debug then ConMsg("zoom = " .. tostring(e.gScale)) end + __, pExtState.win_x, pExtState.win_y, __, __ = gfx.dock(-1,0,0,0,0) -- set soom if pExtState.win_x ~= m.win_x then __, m.win_x, m.win_y, __, __ = gfx.dock(-1,0,0,0,0) - ConMsg(m.win_x, m.win_y) + ConMsg("m.win_x = " .. tostring(m.win_x) .. "m.win_y = " .. tostring(m.win_y)) pExtState.win_x = m.win_x pExtState.win_y = m.win_y end @@ -2649,7 +2650,7 @@ function MainLoop() gLastMouseCap = gfx.mouse_cap gLastMouseX, gLastMouseY = gfx.mouse_x, gfx.mouse_y gfx.mouse_wheel = 0 -- reset gfx.mouse_wheel - __, pExtState.win_x, pExtState.win_y, __, __ = gfx.dock(-1,0,0,0,0) + -- Get passthrough key for play/stop (spacebar) char = gfx.getchar() if char == 32 then reaper.Main_OnCommand(40044, 0) end