|
|
|
06-16-2017, 03:46 PM
|
#1
|
Human being with feelings
Join Date: Jan 2007
Location: Canada
Posts: 120
|
Copy/Paste Velocity Data
I can't find a way to copy velocity data (example, a pattern of velocities) and paste it later in the same midi editor track. Is this possible in Reaper?
Apologies if I missed something obvious.
|
|
|
06-16-2017, 04:16 PM
|
#2
|
Human being with feelings
Join Date: Jan 2009
Location: New Zealand
Posts: 2,905
|
Hi I have not done this for a while but when I did I think I did this
Highlight all the automation dots on the screen view you want / rt click on active file and select "copy" Afterwards click a point in the file where you wish the new automation to be then paste, you will find this at the top left hand side of the page under edit, PASTE .
Hope that makes sense .
Hope I have got it right.
Grinder
|
|
|
06-16-2017, 04:37 PM
|
#3
|
Human being with feelings
Join Date: Jan 2007
Location: Canada
Posts: 120
|
Thanks for the quick reply! Unfortunately, my copy/paste includes all data including notes. I'm looking specifically at copying note velocity from source to destination locations.
|
|
|
06-16-2017, 06:07 PM
|
#4
|
Human being with feelings
Join Date: Dec 2015
Posts: 476
|
Hi.
Velocity isn't exactly automation, is it?
I can think of some kind of (groove? advanced?) quantization that lets you untick all the checkboxes except Velocity and use your pattern as the groove...
Ah,
SWS/FNG: Show groove tool
!
Strength
Position: 0%.
Velocity: 100%.
That's the idea.
|
|
|
06-16-2017, 10:30 PM
|
#5
|
Human being with feelings
Join Date: Jan 2007
Location: Canada
Posts: 120
|
Thanks for the workaround but I was hoping for something inside the midi editor. It looks like the functionality is available for cc data but not fpr velocity data. Too bad, I would use it a lot when building ostinato rhythms.
|
|
|
06-17-2017, 10:26 AM
|
#6
|
Human being with feelings
Join Date: May 2006
Location: Surrey, UK
Posts: 19,677
|
'Fraid not; there is no such thing as 'velocity data'.
Velocity is a property of each MIDI note (as are its note number and channel). So you cannot copy the velocities, you can only copy the notes.
__________________
DarkStar ... interesting, if true. . . . Inspired by ...
|
|
|
06-17-2017, 10:38 PM
|
#8
|
Human being with feelings
Join Date: Aug 2007
Location: Near Cambridge UK and Near Questembert, France
Posts: 22,754
|
OK I think the problem lies with how you described what you want. That script isnt copying the velocities really.
What it IS doing (which is rather cool) is applying the *note* velocities from the first section to the *notes* of the later sections. There is a subtle but crucial difference. What the script is really doing is modifying the later velocities to conform to what the earlier section has. In other words it is CHANGING velocities, not pasting them.
__________________
Ici on parles Franglais
|
|
|
06-18-2017, 12:05 AM
|
#9
|
Human being with feelings
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 3,960
|
Code:
function CopySelectedNotesVelocities()
local midieditor = reaper.MIDIEditor_GetActive()
if not midieditor then return end
local take = reaper.MIDIEditor_GetTake( midieditor )
if not take or not reaper.TakeIsMIDI(take) then return end
local _, notecnt = reaper.MIDI_CountEvts( take )
local t = {}
local str = ""
for i = 1, notecnt do
_, selectedOut, _, _, _, _, _, vel = reaper.MIDI_GetNote( take, i-1 )
if selectedOut == true then str = str..vel..',' end
end
reaper.SetExtState('mplCopyVel', 'buf', str, false)
end
CopySelectedNotesVelocities()
Code:
function PasteVelocitiesToSelectedNotes()
local midieditor = reaper.MIDIEditor_GetActive()
if not midieditor then return end
local take = reaper.MIDIEditor_GetTake( midieditor )
if not take or not reaper.TakeIsMIDI(take) then return end
local _, notecnt = reaper.MIDI_CountEvts( take )
str = reaper.GetExtState('mplCopyVel', 'buf')
t = {}
for num in str:gmatch('[%d]+') do t[#t+1] = tonumber(num) end
for i = 1, notecnt do
retval, sel, m, s, e, c, p, v = reaper.MIDI_GetNote( take, i-1 )
if sel == true then reaper.MIDI_SetNote( take, i-1, true, m, s, e, c, p, t[i%#t], true ) end
end
reaper.MIDI_Sort(take)
end
PasteVelocitiesToSelectedNotes()
Last edited by mpl; 06-18-2017 at 12:51 AM.
|
|
|
06-18-2017, 02:11 AM
|
#10
|
Human being with feelings
Join Date: Aug 2007
Location: Near Cambridge UK and Near Questembert, France
Posts: 22,754
|
Damn you scripters are smart!
I will probably never have a use for this, but it is still pretty cool that one can write something like this in Lua or similar and just insert it in Reaper.
Wish I had the right sort of brain to do this....
__________________
Ici on parles Franglais
|
|
|
06-18-2017, 06:07 AM
|
#11
|
Human being with feelings
Join Date: Nov 2015
Location: Germany
Posts: 1,015
|
Quote:
Originally Posted by ivansc
Damn you scripters are smart!
|
And mpl is the coolest one ever! No needless descriptions or anything. JUST A SOLUTION. Baaaamm, here you are!
I love it.
|
|
|
06-18-2017, 07:51 AM
|
#12
|
Human being with feelings
Join Date: Aug 2007
Location: Near Cambridge UK and Near Questembert, France
Posts: 22,754
|
evidently Mixbus 4 (I didnt update from 3) now has lua scripting so it will be interesting to see what sort of stuff HEIR user come up with.
__________________
Ici on parles Franglais
|
|
|
06-18-2017, 10:29 AM
|
#13
|
Human being with feelings
Join Date: Jan 2007
Location: Canada
Posts: 120
|
Wow, the Reaper community is amazing!
Thanks so much mpl! I'll give it a try and hopefully I can get it working.
|
|
|
07-06-2017, 12:10 PM
|
#14
|
Human being with feelings
Join Date: Jan 2007
Location: Canada
Posts: 120
|
Yup. Works brilliantly, even better than the Presonus example. Thanks mpl!
|
|
|
09-26-2017, 09:56 AM
|
#15
|
Human being with feelings
Join Date: Sep 2017
Posts: 2
|
Hello everyone!
mpl, I tried to use your scripts in a project but they weren't working for me, and after some testing I found that it was because simultaneous notes are listed in the order they are created which does not provide consistency. Using the procedure showcased in your scripts I expanded them to be able to manage these cases.
I'll leave them here so that in the future they can be of use to anyone who needs this functionality.
Code:
function CopySelectedNotesVelocities()
local script_name = "MIDI-velocity-copy"
--Get current take
local midieditor = reaper.MIDIEditor_GetActive()
if not midieditor then
reaper.ShowConsoleMsg( script_name.." error: there is no active MIDI Editor.\n" )
return
end
local take = reaper.MIDIEditor_GetTake( midieditor )
if not take or not reaper.TakeIsMIDI(take) then
reaper.ShowConsoleMsg( script_name.." error: there is no selected MIDI take.\n" )
return
end
local _, notecnt, _, _ = reaper.MIDI_CountEvts( take )
--Set needed variables
local current_note = {} --Store the current note
local last_note = {} --Remember the last selected note while iterating through all the notes
local temp = {} --Temporary table to remember all the notes that share position to sort them by pitch
local str = "" --String of concatenated velocities to export
local action_definitions = { --Define the different actions the script has to perform while iterating through the take
["clean_temp"] = function(current_note, last_note, temp, str)
local temp_size = #temp
if temp_size > 0 then
table.sort(temp, function (note1, note2) return note1.pitch < note2.pitch end)
for _, note in ipairs(temp) do
str = str..note.vel..','
end
temp = {}
end
return current_note, last_note, temp, str
end,
["add_note_to_temp"] = function(current_note, last_note, temp, str)
table.insert(temp, current_note)
return current_note, last_note, temp, str
end,
["update"] = function(current_note, last_note, temp, str)
last_note = current_note
return current_note, last_note, temp, str
end
}
--Iterate through the take
for i = 1, notecnt do
local last_run = (i == notecnt and true or false) --true if this is the last note in the take
--Get current note data
local _, current_selected, _, current_pos, _, _, current_pitch, current_vel = reaper.MIDI_GetNote( take, i-1 )
local current_note = {
selected = current_selected,
pos = current_pos,
pitch = tonumber(current_pitch),
vel = current_vel }
--Create stack of actions to resolve and populate it with the right actions in the right order for the situation
local actions = {}
--If position has changed, current temp will have to be cleaned before current note is processed
if current_note.pos ~= last_note.pos then table.insert(actions, "clean_temp") end
--If current note is selected it will have to be added to temp
if current_note.selected then table.insert(actions, "add_note_to_temp") end
--If current note is the last note and it is selected, temp needs to be cleaned after it is processed
if current_note.selected and last_run then table.insert(actions, "clean_temp") end
--After everything else, update last_note
table.insert(actions, "update")
--Perform actions
for _, to_do in ipairs(actions) do
current_note, last_note, temp, str = action_definitions[to_do](current_note, last_note, temp, str)
end
end
reaper.SetExtState( 'CopyVel', 'buf', str, false )
reaper.ShowConsoleMsg( script_name .. " copied velocities: "..str )
end
CopySelectedNotesVelocities()
Code:
function PasteVelocitiesToSelectedNotes()
local script_name = "MIDI-velocity-paste"
--Get current take
local midieditor = reaper.MIDIEditor_GetActive()
if not midieditor then
reaper.ShowConsoleMsg( script_name.." error: there is no active MIDI Editor.\n" )
return
end
local take = reaper.MIDIEditor_GetTake( midieditor )
if not take or not reaper.TakeIsMIDI(take) then
reaper.ShowConsoleMsg( script_name.." error: there is no selected MIDI take.\n" )
return
end
local _, notecnt = reaper.MIDI_CountEvts( take )
--Get copied velocities
if not reaper.HasExtState('CopyVel', 'buf') then --Exit if there are none
reaper.ShowConsoleMsg( script_name.." error: copy some velocities first.\n" )
return
end
local str = reaper.GetExtState('CopyVel', 'buf') --Load the string
local velocities = {} --Create a table to store them
for velocity in str:gmatch('[%d]+') do
table.insert(velocities, tonumber(velocity)) --Add them to the table
end
--Iterate through the take and find the ids and all atributes of selected notes.
local selected_notes = {}
for i = 1, notecnt do
local retval, sel, m, s, e, c, p, v = reaper.MIDI_GetNote( take, i-1 )
if sel == true then
local current_note = {
id = i-1,
muted = m,
startpos = s,
endpos = e,
channel = c,
pitch = p,
velocity = v }
table.insert( selected_notes, current_note )
end
end
--Exit if number of velocities is different than the number of selected notes
if #velocities ~= #selected_notes then
reaper.ShowConsoleMsg( script_name.." error: can't paste " .. #velocities .. " velocity/ies into " .. #selected_notes .. " note/s. Number must be the same.\n" )
return
end
--selected_notes are already sorted by position, now sort notes in the same position by pitch from low to high
local sorting_function = function (note1, note2)
local values_to_compare = {
{ note1.startpos, note2.startpos },
{ note1.pitch, note2.pitch }
}
for _, values in ipairs(values_to_compare) do
if values[1] < values[2] then return true
elseif values[1] > values[2] then return false end
end
return false
end
table.sort( selected_notes, sorting_function )
--Perform the changes
for i, note in ipairs( selected_notes ) do
reaper.MIDI_SetNote( take, note.id, true, note.muted, note.startpos, note.endpos, note.channel, note.pitch, velocities[i], true )
end
reaper.MIDI_Sort( take )
reaper.ShowConsoleMsg( script_name.." successfully copied velocities into " .. #selected_notes .. " note/s.\n" )
end
PasteVelocitiesToSelectedNotes()
|
|
|
11-01-2017, 11:50 AM
|
#16
|
Human being with feelings
Join Date: Oct 2017
Location: Black Forest
Posts: 5,054
|
Thanks guys, this is an awesome script! I always wished for something like that in Cubase.
|
|
|
12-24-2017, 08:40 AM
|
#17
|
Human being with feelings
Join Date: Apr 2010
Location: Turkey/Istanbul
Posts: 1,820
|
Thank you mpl & jojojopo!
@jojojopo
nothing serious but
any change to have a version that doesn't run the Console after action executed?
|
|
|
12-26-2017, 07:08 AM
|
#18
|
Human being with feelings
Join Date: Sep 2017
Posts: 2
|
@timbralzoom
Sure, you are right that it can get annoying. I made it so that a message is showed only when there is some kind of error.
Code:
function CopySelectedNotesVelocities()
local script_name = "MIDI-velocity-copy"
--Get current take
local midieditor = reaper.MIDIEditor_GetActive()
if not midieditor then
reaper.ShowConsoleMsg( script_name.." error: there is no active MIDI Editor.\n" )
return
end
local take = reaper.MIDIEditor_GetTake( midieditor )
if not take or not reaper.TakeIsMIDI(take) then
reaper.ShowConsoleMsg( script_name.." error: there is no selected MIDI take.\n" )
return
end
local _, notecnt, _, _ = reaper.MIDI_CountEvts( take )
--Set needed variables
local current_note = {} --Store the current note
local last_note = {} --Remember the last selected note while iterating through all the notes
local temp = {} --Temporary table to remember all the notes that share position to sort them by pitch
local str = "" --String of concatenated velocities to export
local action_definitions = { --Define the different actions the script has to perform while iterating through the take
["clean_temp"] = function(current_note, last_note, temp, str)
local temp_size = #temp
if temp_size > 0 then
table.sort(temp, function (note1, note2) return note1.pitch < note2.pitch end)
for _, note in ipairs(temp) do
str = str..note.vel..','
end
temp = {}
end
return current_note, last_note, temp, str
end,
["add_note_to_temp"] = function(current_note, last_note, temp, str)
table.insert(temp, current_note)
return current_note, last_note, temp, str
end,
["update"] = function(current_note, last_note, temp, str)
last_note = current_note
return current_note, last_note, temp, str
end
}
--Iterate through the take
for i = 1, notecnt do
local last_run = (i == notecnt and true or false) --true if this is the last note in the take
--Get current note data
local _, current_selected, _, current_pos, _, _, current_pitch, current_vel = reaper.MIDI_GetNote( take, i-1 )
local current_note = {
selected = current_selected,
pos = current_pos,
pitch = tonumber(current_pitch),
vel = current_vel }
--Create stack of actions to resolve and populate it with the right actions in the right order for the situation
local actions = {}
--If position has changed, current temp will have to be cleaned before current note is processed
if current_note.pos ~= last_note.pos then table.insert(actions, "clean_temp") end
--If current note is selected it will have to be added to temp
if current_note.selected then table.insert(actions, "add_note_to_temp") end
--If current note is the last note and it is selected, temp needs to be cleaned after it is processed
if current_note.selected and last_run then table.insert(actions, "clean_temp") end
--After everything else, update last_note
table.insert(actions, "update")
--Perform actions
for _, to_do in ipairs(actions) do
current_note, last_note, temp, str = action_definitions[to_do](current_note, last_note, temp, str)
end
end
reaper.SetExtState( 'CopyVel', 'buf', str, false )
--reaper.ShowConsoleMsg( script_name .. " copied velocities: "..str )
end
CopySelectedNotesVelocities()
Code:
function PasteVelocitiesToSelectedNotes()
local script_name = "MIDI-velocity-paste"
--Get current take
local midieditor = reaper.MIDIEditor_GetActive()
if not midieditor then
reaper.ShowConsoleMsg( script_name.." error: there is no active MIDI Editor.\n" )
return
end
local take = reaper.MIDIEditor_GetTake( midieditor )
if not take or not reaper.TakeIsMIDI(take) then
reaper.ShowConsoleMsg( script_name.." error: there is no selected MIDI take.\n" )
return
end
local _, notecnt = reaper.MIDI_CountEvts( take )
--Get copied velocities
if not reaper.HasExtState('CopyVel', 'buf') then --Exit if there are none
reaper.ShowConsoleMsg( script_name.." error: copy some velocities first.\n" )
return
end
local str = reaper.GetExtState('CopyVel', 'buf') --Load the string
local velocities = {} --Create a table to store them
for velocity in str:gmatch('[%d]+') do
table.insert(velocities, tonumber(velocity)) --Add them to the table
end
--Iterate through the take and find the ids and all atributes of selected notes.
local selected_notes = {}
for i = 1, notecnt do
local retval, sel, m, s, e, c, p, v = reaper.MIDI_GetNote( take, i-1 )
if sel == true then
local current_note = {
id = i-1,
muted = m,
startpos = s,
endpos = e,
channel = c,
pitch = p,
velocity = v }
table.insert( selected_notes, current_note )
end
end
--Exit if number of velocities is different than the number of selected notes
if #velocities ~= #selected_notes then
reaper.ShowConsoleMsg( script_name.." error: can't paste " .. #velocities .. " velocity/ies into " .. #selected_notes .. " note/s. Number must be the same.\n" )
return
end
--selected_notes are already sorted by position, now sort notes in the same position by pitch from low to high
local sorting_function = function (note1, note2)
local values_to_compare = {
{ note1.startpos, note2.startpos },
{ note1.pitch, note2.pitch }
}
for _, values in ipairs(values_to_compare) do
if values[1] < values[2] then return true
elseif values[1] > values[2] then return false end
end
return false
end
table.sort( selected_notes, sorting_function )
--Perform the changes
for i, note in ipairs( selected_notes ) do
reaper.MIDI_SetNote( take, note.id, true, note.muted, note.startpos, note.endpos, note.channel, note.pitch, velocities[i], true )
end
reaper.MIDI_Sort( take )
--reaper.ShowConsoleMsg( script_name.." successfully copied velocities into " .. #selected_notes .. " note/s.\n" )
end
PasteVelocitiesToSelectedNotes()
|
|
|
12-26-2017, 07:44 AM
|
#19
|
Human being with feelings
Join Date: Apr 2010
Location: Turkey/Istanbul
Posts: 1,820
|
Great! Thank you so much!
|
|
|
09-21-2021, 02:47 AM
|
#20
|
Human being with feelings
Join Date: Nov 2012
Posts: 178
|
This script is not working for me. I installed it via Extensions - Reapack - Browse - 'Copy selected notes velocities' and 'Paste selected notes velocities'
See the video - it's clearly pasting the velocities onto the selected notes too quickly. The notes are identical, except for being a semitone higher than the copied notes.
https://streamable.com/ypoion
How do I fix this please?
|
|
|
06-08-2022, 03:53 AM
|
#21
|
Human being with feelings
Join Date: Apr 2020
Posts: 6
|
Thanks for the script!
I'm a bit of a noob when it comes to scripts: would you be kind enough to explain how I can make it work in Reaper?
And how does it work while it's installed?
Thanks a bunch
|
|
|
03-09-2024, 05:31 AM
|
#22
|
Human being with feelings
Join Date: Aug 2021
Posts: 6
|
Scripting wizard to extend these scripts?!?!
This is my dream:
- Copy selected cc1 points in a MIDI editor lane
- Paste values from copied cc1's as velocities where note-on events are present at this "time"
I'm too inept to script this myself... May be a piece of cake for a reascript pro...
Thanx to anyone who can do it! ;-)
|
|
|
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 07:32 AM.
|