|
|
|
09-15-2019, 03:35 AM
|
#1
|
Human being with feelings
Join Date: Oct 2018
Posts: 17
|
cakewalk function: Scale Velocity (lua - help)
Hello everyone, I am learning to write a script. Implement a feature of cakewalk: Scale Velocity.
See the picture
127 -> 1
The input Begin and end with Velocity, and the script will calculate the results at the beginning and end.
I have a problem and don't know how to get the total number of selected notes. So my calculations have problems and the scripts are not working properly.
Last edited by wwcdgm; 09-18-2019 at 10:56 AM.
|
|
|
09-15-2019, 06:35 AM
|
#2
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 9,875
|
TO get total of selected notes,
Loop first in all notes and increment a variable +1 each time you have sel == true,
then you can do your second loop with this number.
|
|
|
09-15-2019, 01:38 PM
|
#3
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
Or you can use reaper.MIDI_EnumSelNotes( take, noteidx ) in a loop until it returns -1; might be faster for large numbers of notes.
|
|
|
09-16-2019, 12:04 PM
|
#4
|
Human being with feelings
Join Date: Oct 2018
Posts: 17
|
Quote:
Originally Posted by X-Raym
TO get total of selected notes,
Loop first in all notes and increment a variable +1 each time you have sel == true,
then you can do your second loop with this number.
|
Thank you, X-Raym. I used your method to get the total number of notes selected. I can finally continue to write the next step.
Now, the script can be quite satisfactory. However, I have encountered new problems. It works fine with a single melody, but if there are many notes in the same position (such as chords), the calculations will exceed expectations. Obviously an error occurred and some notes were eliminated because of errors.
The reason is that notes at the same time are constantly matched to new values, and many values exceed 127 (I think there are some problems with my calculation formula? -_-!!). In addition, notes of the same time should only use one value, and now it seems that each note has a superimposed assignment.
So, what should you do if the notes at the same time can only match one value?
Please see my code
Code:
function Msg(param)
reaper.ShowConsoleMsg(tostring(param) .. "\n")
end
function Warn(msg)
reaper.ShowMessageBox(tostring(msg), "warning", 0)
end
reaper.ShowConsoleMsg("")
local take=reaper.MIDIEditor_GetTake(reaper.MIDIEditor_GetActive())
retval, notes, ccs, sysex = reaper.MIDI_CountEvts(take)
userOK, userInputsCSV = reaper.GetUserInputs("Scale Velocity",
2,
"Begin,End",
"10,100")
if not userOK then return reaper.SN_FocusMIDIEditor() end
vel_begin, vel_end = userInputsCSV:match("(.*),(.*)")
vel_begin, vel_end = tonumber(vel_begin),tonumber(vel_end)
if vel_begin > 127 or vel_end > 127 or vel_begin < 1 or vel_end < 1 then return end
noteidx = 0
note_count = 0
for noteidx=0, notes-1 do
retval, sel, muted, startppq, endppq, chan, pitch, vel = reaper.MIDI_GetNote(take, noteidx)
if sel == true then
note_count = note_count + 1
end
noteidx=noteidx+1
end
Msg("Note count = "..note_count) -- Get the total number of selected notes
local k = note_count-1
local j = math.abs(math.floor( (vel_begin-vel_end)/k) )
Msg("print K = "..k)
Msg("Value added each time = "..j)
if vel_begin > vel_end then
for i = 0, notes-1 do
retval, sel, muted, ppq_start, ppq_end, chan, pitch, vel = reaper.MIDI_GetNote( take, i )
if sel == true then
vel_begin = vel_begin-j
reaper.MIDI_SetNote( take, i, sel, muted, ppq_start, ppq_end, chan, pitch, vel_begin+j, true )
Msg(vel_begin+j) -- Increase from the input begin value
end
end
else
for i = 0, notes-1 do
retval, sel, muted, ppq_start, ppq_end, chan, pitch, vel = reaper.MIDI_GetNote( take, i )
if sel == true then
vel_begin = vel_begin+j
reaper.MIDI_SetNote( take, i, sel, muted, ppq_start, ppq_end, chan, pitch, vel_begin-j, true )
Msg(vel_begin-j) -- Increase from the input begin value
end
end
end
reaper.UpdateArrange()
reaper.SN_FocusMIDIEditor()
Last edited by wwcdgm; 09-18-2019 at 10:55 AM.
|
|
|
09-16-2019, 12:19 PM
|
#5
|
Human being with feelings
Join Date: Oct 2018
Posts: 17
|
Quote:
Originally Posted by Lokasenna
Or you can use reaper.MIDI_EnumSelNotes( take, noteidx ) in a loop until it returns -1; might be faster for large numbers of notes.
|
Thank you very much Lokasenna. I used your method to successfully loop notes, but I haven't figured out how to get the total number of all selected notes, only the continuous value of 012345.... It seems that MIDI_EnumSelNotes is faster, is it convenient to provide a solution?
|
|
|
09-16-2019, 12:47 PM
|
#6
|
Human being with feelings
Join Date: Sep 2008
Location: Calgary, AB, Canada
Posts: 6,551
|
EnumSelNotes will give you the index (within all of the notes) of the next selected note after whatever index you pass in. After the last selected note, the next index it returns will be -1 - if you have a counter going, at that point you should have the total number of selected notes.
|
|
|
09-16-2019, 03:19 PM
|
#7
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,913
|
Quote:
Originally Posted by wwcdgm
Hello everyone, I am learning to write a script. Implement a feature of cakewalk: Scale Velocity.
|
Cool, I'm just trying to get back into MIDI and wanting to do the same thing, So using whats posted I came up with this so far,...
Code:
local take=reaper.MIDIEditor_GetTake(reaper.MIDIEditor_GetActive())
if take == nil then return end
local cnt, index = 0, {}
local val = reaper.MIDI_EnumSelNotes(take, -1)
while val ~= - 1 do
cnt = cnt + 1
index[cnt] = val
val = reaper.MIDI_EnumSelNotes(take, val)
end
if #index > 0 then
local retval, userInputsCSV = reaper.GetUserInputs("Scale Velocity", 2, "Begin,End", "17,127")
if not retval then return end
local vel_first, vel_end = userInputsCSV:match("(.*),(.*)")
local offset = (vel_end - vel_first) / cnt -- Lua provides automatic conversion between string and number values at run time.
for i = 1, #index do
local retval, sel, muted, ppq_start, ppq_end, chan, pitch, _ = reaper.MIDI_GetNote(take, index[i])
reaper.MIDI_SetNote(take, index[i], sel, muted, ppq_start, ppq_end, chan, pitch, math.floor(vel_first), true)
vel_first = vel_first + offset
end
reaper.UpdateArrange()
else
reaper.MB("No notes selected","ERROR",0)
end
reaper.SN_FocusMIDIEditor()
reaper.defer(function () end)
Better, Worse?
Last edited by Edgemeal; 09-17-2019 at 09:31 AM.
|
|
|
09-17-2019, 02:26 PM
|
#8
|
Human being with feelings
Join Date: Oct 2018
Posts: 17
|
Quote:
Originally Posted by Edgemeal
Cool, I'm just trying to get back into MIDI and wanting to do the same thing, So using whats posted I came up with this so far,...
Code:
local take=reaper.MIDIEditor_GetTake(reaper.MIDIEditor_GetActive())
if take == nil then return end
local cnt, index = 0, {}
local val = reaper.MIDI_EnumSelNotes(take, -1)
while val ~= - 1 do
cnt = cnt + 1
index[cnt] = val
val = reaper.MIDI_EnumSelNotes(take, val)
end
if #index > 0 then
local retval, userInputsCSV = reaper.GetUserInputs("Scale Velocity", 2, "Begin,End", "17,127")
if not retval then return end
local vel_first, vel_end = userInputsCSV:match("(.*),(.*)")
local offset = (vel_end - vel_first) / cnt -- Lua provides automatic conversion between string and number values at run time.
for i = 1, #index do
local retval, sel, muted, ppq_start, ppq_end, chan, pitch, _ = reaper.MIDI_GetNote(take, index[i])
reaper.MIDI_SetNote(take, index[i], sel, muted, ppq_start, ppq_end, chan, pitch, math.floor(vel_first), true)
vel_first = vel_first + offset
end
reaper.UpdateArrange()
else
reaper.MB("No notes selected","ERROR",0)
end
reaper.SN_FocusMIDIEditor()
reaper.defer(function () end)
Better, Worse?
|
Wow, that's great.You have finished it.thank you very much.
There is no problem with the code running, I really admire you.
|
|
|
09-17-2019, 02:54 PM
|
#9
|
Human being with feelings
Join Date: Oct 2018
Posts: 17
|
Quote:
Originally Posted by Lokasenna
EnumSelNotes will give you the index (within all of the notes) of the next selected note after whatever index you pass in. After the last selected note, the next index it returns will be -1 - if you have a counter going, at that point you should have the total number of selected notes.
|
Ok,thank you.Your help was greatly appreciated.
Last edited by wwcdgm; 09-17-2019 at 03:00 PM.
|
|
|
09-17-2019, 03:05 PM
|
#10
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,913
|
Ya thanks!
|
|
|
09-22-2019, 11:29 AM
|
#11
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 3,913
|
Quote:
Originally Posted by wwcdgm
Wow, that's great.You have finished it.thank you very much.
There is no problem with the code running, I really admire you.
|
FWIW, I tweaked it so the first and last selected note values are used for the input defaults, it makes fine tuning a little quicker for me.
Code:
local take=reaper.MIDIEditor_GetTake(reaper.MIDIEditor_GetActive())
if take == nil then return end
local cnt, index = 0, {}
local val = reaper.MIDI_EnumSelNotes(take, -1)
while val ~= - 1 do
cnt = cnt + 1
index[cnt] = val
val = reaper.MIDI_EnumSelNotes(take, val)
end
if #index > 1 then
local _, _, _, _, _, _, _, begin_vel = reaper.MIDI_GetNote(take, index[1])
local _, _, _, _, _, _, _, end_vel = reaper.MIDI_GetNote(take, index[#index])
local cur_range = tostring(begin_vel)..','..tostring(end_vel)
local retval, userInputsCSV = reaper.GetUserInputs("Scale Velocity", 2, "Begin,End", cur_range)
if not retval then return end
local vel_first, vel_end = userInputsCSV:match("(.*),(.*)")
local offset = (vel_end - vel_first) / cnt -- Lua provides automatic conversion between string and number values at run time.
for i = 1, #index do
local retval, sel, muted, ppq_start, ppq_end, chan, pitch, _ = reaper.MIDI_GetNote(take, index[i])
reaper.MIDI_SetNote(take, index[i], sel, muted, ppq_start, ppq_end, chan, pitch, math.floor(vel_first), true)
vel_first = vel_first + offset
end
reaper.UpdateArrange()
else
reaper.MB("Please select two or more notes","Scale Velocity", 0)
end
reaper.SN_FocusMIDIEditor()
reaper.defer(function () end)
Last edited by Edgemeal; 10-02-2019 at 06:53 PM.
Reason: FIX: Bug in reaper.MB call, was missing title text
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 01:14 AM.
|