|
|
|
08-22-2016, 03:24 AM
|
#1
|
Human being with feelings
Join Date: Mar 2013
Posts: 86
|
Midi editor: how to move notes back of "x" milliseconds?
As written in the title: how to move back some notes back of "x" milliseconds.
I know that there is the function "nudge" for midi items, but this move all the midi item back, while I need to move back just certain notes and leave others on beat.
Any help?
Thanks!
|
|
|
08-22-2016, 04:44 AM
|
#2
|
Human being with feelings
Join Date: Oct 2008
Location: Right Hear
Posts: 15,618
|
good question and I recently was dealing with the same need...
could not get the nudge to work on selected notes, but I wish it did...
so I did it manually by turning off the snap to grid, zooming way the hell in and moving the notes until they played as I wanted...
Now I could imagine another way, that would use the nudge function:
duplicate the track...
select all the notes you want to nudge
invert the selection and delete all the other notes
now you have a midi item that can be nudged
go back to the original item and mute or remove the notes that you used in the nudged item...
now you could also use free item positioning to keep both these midi items on the same track if you like...
or you could re-combine them into one item
|
|
|
08-22-2016, 05:19 AM
|
#3
|
Human being with feelings
Join Date: Mar 2013
Posts: 86
|
Thanks!
That's a good workaround...but it's a little time consuming
|
|
|
08-22-2016, 08:33 AM
|
#4
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by dream_of_the_night
As written in the title: how to move back some notes back of "x" milliseconds.
I know that there is the function "nudge" for midi items, but this move all the midi item back, while I need to move back just certain notes and leave others on beat.
|
Is the BPM constant? If it is, you can convert the milliseconds to ticks and use the Properties popup window to change the position of the selected notes. (For example, enter "-0.0.480" or "+0.0.480" in the Position field to move the notes back or forward 1 eighth note, respectively.)
EDIT:
What to do if the BPM changes? I don't know if there is a better, native method, but sometimes it is easier to just write a quick script:
Code:
-- Quick script that is intended to nudge selected notes in the active take
-- by a user-defined number of milliseconds
-- WARNING: Do not use if there are overlapping notes in the take, since
-- ReaScripts are not compatible with such notes.
reaper.Undo_BeginBlock()
editor = reaper.MIDIEditor_GetActive()
take = reaper.MIDIEditor_GetTake(editor)
reaper.MIDI_Sort(take)
repeat
OKorCancel, userTime = reaper.GetUserInputs("Nudge notes by millisecs", 1, "Time (in milliseconds)", "0")
until OKorCancel == false or (OKorCancel == true and type(tonumber(userTime)) == "number")
if OKorCancel == false then
return(0)
else
nudgeTime = tonumber(userTime) / 1000
end
i = reaper.MIDI_EnumSelNotes(take, -1)
while i ~= -1 do
noteOK, selected, _, noteStartPPQ, noteEndPPQ, _, _, _ = reaper.MIDI_GetNote(take, i)
if noteOK and selected then
noteStartTime = reaper.MIDI_GetProjTimeFromPPQPos(take, noteStartPPQ)
newNoteStartPPQ = reaper.MIDI_GetPPQPosFromProjTime(take, noteStartTime + nudgeTime)
newNoteEndPPQ = noteEndPPQ + (newNoteStartPPQ - noteStartPPQ)
reaper.MIDI_SetNote(take, i, nil, nil, newNoteStartPPQ, newNoteEndPPQ, nil, nil, nil, true)
end
i = reaper.MIDI_EnumSelNotes(take, i)
end
reaper.MIDI_Sort(take)
reaper.Undo_EndBlock("Nudge notes by milliseconds", -1)
EDIT 2: BTW, if you use the MIDI Inspector while working in the MIDI editor, you can choose to display note position info in time or seconds instead of the usual measure:beat:ticks.
Last edited by juliansader; 08-22-2016 at 11:47 AM.
|
|
|
08-22-2016, 07:08 PM
|
#5
|
Human being with feelings
Join Date: Oct 2008
Location: Right Hear
Posts: 15,618
|
nice one julian....
so if that script works as I believe it would, is it possible have one where the user has a slider of entry field to set the number of milisecs [left or right] while working ... in other words much like the normal nudge window?
I know so little about script creation code... sorry for the dumbness
|
|
|
08-22-2016, 11:59 PM
|
#6
|
Human being with feelings
Join Date: Mar 2013
Posts: 86
|
Thank you!
But because I'm a little dumb with computers I can't get the script work, probably because when I donwnloaded the file it was saved .txt and not .lua so that I cannot load the script in the action list. :/
|
|
|
08-23-2016, 12:12 AM
|
#7
|
Human being with feelings
Join Date: Jul 2012
Location: Netherlands
Posts: 5,247
|
If you're on mac:
Click on the script.
Hit CMD key plus I key.
In "Name & Extension" area, change .txt for .lua
Then click "use .lua" in the window that appears.
|
|
|
08-23-2016, 12:13 AM
|
#8
|
Human being with feelings
Join Date: Mar 2013
Posts: 86
|
I0m on windows 10
|
|
|
08-23-2016, 12:17 AM
|
#9
|
Human being with feelings
Join Date: Jul 2012
Location: Netherlands
Posts: 5,247
|
Right mouse click on the script.
choose "rename"
change .txt to .lua
confirm that you want to rename.
|
|
|
08-23-2016, 12:24 AM
|
#10
|
Human being with feelings
Join Date: Mar 2013
Posts: 86
|
It doesn't work the same, it saves the new file ".lua.text"
|
|
|
08-23-2016, 12:28 AM
|
#11
|
Human being with feelings
Join Date: Mar 2013
Posts: 86
|
Solved using "notepad"
|
|
|
08-23-2016, 12:38 AM
|
#12
|
Human being with feelings
Join Date: Jul 2012
Location: Netherlands
Posts: 5,247
|
Good for you !
|
|
|
08-23-2016, 03:21 AM
|
#13
|
Human being with feelings
Join Date: Mar 2013
Posts: 86
|
Quote:
Originally Posted by juliansader
Is the BPM constant? If it is, you can convert the milliseconds to ticks and use the Properties popup window to change the position of the selected notes. (For example, enter "-0.0.480" or "+0.0.480" in the Position field to move the notes back or forward 1 eighth note, respectively.)
EDIT:
What to do if the BPM changes? I don't know if there is a better, native method, but sometimes it is easier to just write a quick script:
Code:
-- Quick script that is intended to nudge selected notes in the active take
-- by a user-defined number of milliseconds
-- WARNING: Do not use if there are overlapping notes in the take, since
-- ReaScripts are not compatible with such notes.
reaper.Undo_BeginBlock()
editor = reaper.MIDIEditor_GetActive()
take = reaper.MIDIEditor_GetTake(editor)
reaper.MIDI_Sort(take)
repeat
OKorCancel, userTime = reaper.GetUserInputs("Nudge notes by millisecs", 1, "Time (in milliseconds)", "0")
until OKorCancel == false or (OKorCancel == true and type(tonumber(userTime)) == "number")
if OKorCancel == false then
return(0)
else
nudgeTime = tonumber(userTime) / 1000
end
i = reaper.MIDI_EnumSelNotes(take, -1)
while i ~= -1 do
noteOK, selected, _, noteStartPPQ, noteEndPPQ, _, _, _ = reaper.MIDI_GetNote(take, i)
if noteOK and selected then
noteStartTime = reaper.MIDI_GetProjTimeFromPPQPos(take, noteStartPPQ)
newNoteStartPPQ = reaper.MIDI_GetPPQPosFromProjTime(take, noteStartTime + nudgeTime)
newNoteEndPPQ = noteEndPPQ + (newNoteStartPPQ - noteStartPPQ)
reaper.MIDI_SetNote(take, i, nil, nil, newNoteStartPPQ, newNoteEndPPQ, nil, nil, nil, true)
end
i = reaper.MIDI_EnumSelNotes(take, i)
end
reaper.MIDI_Sort(take)
reaper.Undo_EndBlock("Nudge notes by milliseconds", -1)
EDIT 2: BTW, if you use the MIDI Inspector while working in the MIDI editor, you can choose to display note position info in time or seconds instead of the usual measure:beat:ticks.
|
Thank you very much, the script works nicely and just what I was looking for!
Can I share your script in other forums?
|
|
|
08-24-2016, 10:43 PM
|
#14
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by hopi
so if that script works as I believe it would, is it possible have one where the user has a slider of entry field to set the number of milisecs [left or right] while working ... in other words much like the normal nudge window
|
This would indeed be possible. (It will require a GUI with a slider, though, which is somewhat laborious to do in Lua.) The normal nudge window does not have a slider, however - would a slider offer an advantage?
Quote:
Originally Posted by dream_of_the_night
Thank you very much, the script works nicely and just what I was looking for!
Can I share your script in other forums?
|
You are welcome to share it anywhere!
(BTW, the script preserves the notes' *beats* (PPQ) lengths, not their *time* (millisecond) lengths. If it would be more appropriate to preserve their time lengths instead, it would be easy to adapt the script.)
|
|
|
08-26-2016, 08:15 AM
|
#15
|
Human being with feelings
Join Date: Mar 2013
Posts: 86
|
The script works just as it should: I use it to move back true legato samples
|
|
|
09-22-2016, 07:51 AM
|
#16
|
Human being with feelings
Join Date: Nov 2010
Location: In the abyss...gazing at you...
Posts: 1,237
|
Mouse-Modifier
This is one of the functions I do miss a bit from Cubase.
You could choose a tool (from a toolbox) which works like a mouse-modifier.
The cursor turned into a shoe and the notes could be kicked around at a small amount of time.
I never worried about that amount of time, it always worked great for me.
Would a script be capable of that (or two scripts for left/right) ?
|
|
|
02-20-2018, 03:38 PM
|
#17
|
Human being with feelings
Join Date: May 2016
Posts: 49
|
Quote:
Originally Posted by juliansader
(BTW, the script preserves the notes' *beats* (PPQ) lengths, not their *time* (millisecond) lengths. If it would be more appropriate to preserve their time lengths instead, it would be easy to adapt the script.)
|
First off, sorry to everyone for the massive necro!
Second, thank you @juliansader for your massive contributions to the Reaper community, I use a couple of your scripts and they rock!
Now regarding this script and what you mentioned in my quote above:
The script nearly does what I want it to, and very conveniently too!
But, if you look at this GIF below, here I have 3 notes and I would want to extend the last two notes so they start 125ms earlier for the legato transition, problem is it moves the notes rather than extend them;
So this way the second note ends too early and there's no legato transition between note 2 and 3.
You mention it being easy to change how the script preserves the notes, would it be possible to have it preserve the note end entirely and merely stretch/nudge the note start?
|
|
|
02-20-2018, 05:26 PM
|
#18
|
Human being with feelings
Join Date: Oct 2008
Location: Right Hear
Posts: 15,618
|
Julian.... thanks for that lua [yet again you are so kind]
I am wondering if it would be hard to adapt a version of it that would work in the Inline Editor?
The poor little orphan Inline Editor ...so kewl and soooo much in need of some serious DEV love
|
|
|
05-15-2018, 05:11 AM
|
#19
|
Human being with feelings
Join Date: May 2011
Posts: 150
|
+1 bump!!!!!!!
|
|
|
05-15-2018, 11:44 AM
|
#20
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by hopi
I am wondering if it would be hard to adapt a version of it that would work in the Inline Editor?
|
Sorry that I didn't see this post before.
It would be easy to adapt the script for the inline MIDI editor. The only problem is that scripts don't know which inline editor is focused, so it is not straightforward to run scripts for the inline editor from the Actions list. (Please bump the FR: ReaScript: API functions to get and set focus on an item in the arrange view.) The script must therefore either work with
1) the editor under the mouse, or
2) the selected item(s).
Here are both alternatives:
Code:
-- Quick script that is intended to nudge selected notes in
-- ALL OPEN INLINE MIDI EDITORS IN ALL SELECTED ITEMS
-- by a user-defined number of milliseconds
-- WARNING: Do not use if there are overlapping notes in the take, since
-- ReaScripts are not compatible with such notes.
repeat
OKorCancel, userTime = reaper.GetUserInputs("Nudge notes by millisecs", 1, "Time (in milliseconds)", "0")
until OKorCancel == false or (OKorCancel == true and type(tonumber(userTime)) == "number")
if OKorCancel == false then
reaper.defer(function() end) -- Prevent unnecessary undo points
return(0)
else
nudgeTime = tonumber(userTime) / 1000
end
reaper.Undo_BeginBlock2(0)
for i = 0, reaper.CountSelectedMediaItems(0)-1 do
item = reaper.GetSelectedMediaItem(0, i)
for t = 0, reaper.CountTakes(item)-1 do
take = reaper.GetTake(item, t)
if reaper.BR_IsMidiOpenInInlineEditor(take) then
reaper.MIDI_Sort(take)
n = reaper.MIDI_EnumSelNotes(take, -1)
while n ~= -1 do
noteOK, selected, _, noteStartPPQ, noteEndPPQ, _, _, _ = reaper.MIDI_GetNote(take, n)
if noteOK and selected then
noteStartTime = reaper.MIDI_GetProjTimeFromPPQPos(take, noteStartPPQ)
newNoteStartPPQ = reaper.MIDI_GetPPQPosFromProjTime(take, noteStartTime + nudgeTime)
newNoteEndPPQ = newNoteStartPPQ + (noteEndPPQ - noteStartPPQ)
reaper.MIDI_SetNote(take, n, nil, nil, newNoteStartPPQ, newNoteEndPPQ, nil, nil, nil, true)
end
n = reaper.MIDI_EnumSelNotes(take, n)
end
reaper.MIDI_Sort(take)
end -- if reaper.BR_IsMidiOpenInInlineEditor(take)
end -- for t = 0, reaper.CountTakes(item)-1
end -- for i = 0, reaper.CountSelectedMediaItems(0)-1
reaper.Undo_EndBlock2(0, "Nudge notes by milliseconds", -1)
Code:
-- Quick script that is intended to nudge selected notes in the
-- INLINE (OR MAIN) MIDI EDITOR UNDER THE MOUSE
-- by a user-defined number of milliseconds
-- WARNING: Do not use if there are overlapping notes in the take, since
-- ReaScripts are not compatible with such notes.
reaper.defer(function() end) -- Prevent unnecessary undo points
if not reaper.APIExists("SN_FocusMIDIEditor") then reaper.MB("This script requires a recent version of the SWS extension", "ERROR", 0) return end -- Old versions of SWS have bug in Context function
window, segment, details = reaper.BR_GetMouseCursorContext()
if window ~= "midi_editor" then return end
editor, inlineEditor = reaper.BR_GetMouseCursorContext_MIDI()
if inlineEditor then
take = reaper.BR_GetMouseCursorContext_Take()
else
take = reaper.MIDIEditor_GetTake(editor) -- Also works on main MIDI editor
end
repeat
OKorCancel, userTime = reaper.GetUserInputs("Nudge notes by millisecs", 1, "Time (in milliseconds)", "0")
until OKorCancel == false or (OKorCancel == true and type(tonumber(userTime)) == "number")
if OKorCancel == false then
return(0)
else
nudgeTime = tonumber(userTime) / 1000
end
reaper.Undo_BeginBlock2(0)
reaper.MIDI_Sort(take)
i = reaper.MIDI_EnumSelNotes(take, -1)
while i ~= -1 do
noteOK, selected, _, noteStartPPQ, noteEndPPQ, _, _, _ = reaper.MIDI_GetNote(take, i)
if noteOK and selected then
noteStartTime = reaper.MIDI_GetProjTimeFromPPQPos(take, noteStartPPQ)
newNoteStartPPQ = reaper.MIDI_GetPPQPosFromProjTime(take, noteStartTime + nudgeTime)
newNoteEndPPQ = newNoteStartPPQ + (noteEndPPQ - noteStartPPQ)
reaper.MIDI_SetNote(take, i, nil, nil, newNoteStartPPQ, newNoteEndPPQ, nil, nil, nil, true)
end
i = reaper.MIDI_EnumSelNotes(take, i)
end
reaper.MIDI_Sort(take)
reaper.Undo_EndBlock2(0, "Nudge notes by milliseconds", -1)
Quote:
The poor little orphan Inline Editor ...so kewl and soooo much in need of some serious DEV love
|
Indeed. I have tried to adapt my CC editing scripts for the inline MIDI editor, and also uploaded some channel and CC lane scripts.
|
|
|
09-14-2018, 05:26 AM
|
#21
|
Human being with feelings
Join Date: Jan 2008
Location: LI, NY
Posts: 15
|
Julian,
Thank you so much for this script! I'm a Cinematic Strings user and this script is a part of my daily MIDI editing workflow!
I'm trying to make an action with a modified MPL script for setting fixed velocity for selected notes, and your MS MIDI Nudge. I've tried to modify your script with no luck. I'm still trying to learn how to script properly.
Is there a way to make your script nudge the selected MIDI note to a fixed MS value without asking for a prompt and having to input the desired amount?
Thanks for your time!
|
|
|
09-14-2018, 01:23 PM
|
#22
|
Human being with feelings
Join Date: Oct 2008
Location: Right Hear
Posts: 15,618
|
Julian... in the second script for the Inline Editor...
when I have the item selected and the Inline Editor open and run that script nothing happens... I am expecting to get the entry field but I don't
Am I missing something???
I have the item selected and some of the notes selected...
|
|
|
09-14-2018, 01:28 PM
|
#23
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by hopi
Julian... in the second script for the Inline Editor...
when I have the item selected and the Inline Editor open and run that script nothing happens... I am expecting to get the entry field but I don't
|
Try the first script -- the second one is for the editor under the mouse.
Code:
-- Quick script that is intended to nudge selected notes in the
-- INLINE (OR MAIN) MIDI EDITOR UNDER THE MOUSE
|
|
|
09-14-2018, 01:31 PM
|
#24
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by FlowDenny
Is there a way to make your script nudge the selected MIDI note to a fixed MS value without asking for a prompt and having to input the desired amount?
|
Sure, just replace these lines:
Code:
repeat
OKorCancel, userTime = reaper.GetUserInputs("Nudge notes by millisecs", 1, "Time (in milliseconds)", "0")
until OKorCancel == false or (OKorCancel == true and type(tonumber(userTime)) == "number")
if OKorCancel == false then
reaper.defer(function() end) -- Prevent unnecessary undo points
return(0)
else
nudgeTime = tonumber(userTime) / 1000
end
with (X is time in milliseconds)
|
|
|
09-14-2018, 01:41 PM
|
#25
|
Human being with feelings
Join Date: Jan 2008
Location: LI, NY
Posts: 15
|
Quote:
Originally Posted by juliansader
Sure, just replace these lines:
Code:
repeat
OKorCancel, userTime = reaper.GetUserInputs("Nudge notes by millisecs", 1, "Time (in milliseconds)", "0")
until OKorCancel == false or (OKorCancel == true and type(tonumber(userTime)) == "number")
if OKorCancel == false then
reaper.defer(function() end) -- Prevent unnecessary undo points
return(0)
else
nudgeTime = tonumber(userTime) / 1000
end
with (X is time in milliseconds)
|
Thank you for such a quick reply and sharing such great work!!!
It works perfect. Now I can create 3 different actions(with shortcuts) that adjust the MIDI notes velocity AND proper delay for CSS's legato! This is going to save me so much time and make working with CSS even better!!!
I also tried sending you a PM. I wanted to verify your donation info please.
Last edited by FlowDenny; 09-14-2018 at 01:50 PM.
Reason: Unable to send user PM
|
|
|
09-14-2018, 02:09 PM
|
#26
|
Human being with feelings
Join Date: Oct 2008
Location: Right Hear
Posts: 15,618
|
thanks Julian.... yeah that works OK now
funny how reaper sometimes brings up the correct set of actions for the Inline Editor when it is open and selected and other times brings up the actions for the Main instead...
EDIT: never mind ... seems to work OK now... maybe ghosts in the machine
Last edited by hopi; 09-14-2018 at 02:18 PM.
|
|
|
08-29-2020, 04:02 AM
|
#27
|
Human being with feelings
Join Date: Dec 2018
Location: Paris (France)
Posts: 157
|
Quote:
Originally Posted by juliansader
Is the BPM constant? If it is, you can convert the milliseconds to ticks and use the Properties popup window to change the position of the selected notes. (For example, enter "-0.0.480" or "+0.0.480" in the Position field to move the notes back or forward 1 eighth note, respectively.)
EDIT:
What to do if the BPM changes? I don't know if there is a better, native method, but sometimes it is easier to just write a quick script:
Code:
-- Quick script that is intended to nudge selected notes in the active take
-- by a user-defined number of milliseconds
-- WARNING: Do not use if there are overlapping notes in the take, since
-- ReaScripts are not compatible with such notes.
reaper.Undo_BeginBlock()
editor = reaper.MIDIEditor_GetActive()
take = reaper.MIDIEditor_GetTake(editor)
reaper.MIDI_Sort(take)
repeat
OKorCancel, userTime = reaper.GetUserInputs("Nudge notes by millisecs", 1, "Time (in milliseconds)", "0")
until OKorCancel == false or (OKorCancel == true and type(tonumber(userTime)) == "number")
if OKorCancel == false then
return(0)
else
nudgeTime = tonumber(userTime) / 1000
end
i = reaper.MIDI_EnumSelNotes(take, -1)
while i ~= -1 do
noteOK, selected, _, noteStartPPQ, noteEndPPQ, _, _, _ = reaper.MIDI_GetNote(take, i)
if noteOK and selected then
noteStartTime = reaper.MIDI_GetProjTimeFromPPQPos(take, noteStartPPQ)
newNoteStartPPQ = reaper.MIDI_GetPPQPosFromProjTime(take, noteStartTime + nudgeTime)
newNoteEndPPQ = noteEndPPQ + (newNoteStartPPQ - noteStartPPQ)
reaper.MIDI_SetNote(take, i, nil, nil, newNoteStartPPQ, newNoteEndPPQ, nil, nil, nil, true)
end
i = reaper.MIDI_EnumSelNotes(take, i)
end
reaper.MIDI_Sort(take)
reaper.Undo_EndBlock("Nudge notes by milliseconds", -1)
EDIT 2: BTW, if you use the MIDI Inspector while working in the MIDI editor, you can choose to display note position info in time or seconds instead of the usual measure:beat:ticks.
|
Hi Julian !
Is this script included in ReaPack ?
I've found a bunch of script from you (included the amazing MIDI inspector) there, but nothing that looks like MIDI nudge...
If it's not the case, could you add it to Reapack please ?
Massive thanks !
|
|
|
03-18-2022, 11:10 AM
|
#28
|
Human being with feelings
Join Date: Apr 2019
Location: Cleveland, Ohio
Posts: 16
|
midi nudge
Howdy,
just in case someone is trying to find a way to nudge midi, I was able to do it in the main arranger window . I selected nudge contents by ms of the midi file and it shifted the material.
My problem was my drums were nailed the the click. The overall project bpm does vary starts at 107.9 and ends at 109.1 (gradually speeding up and slowing down along the way ) BUT "1" was always "1" and the drums still felt like a metronome in the background . I can now slight shift kit pieces(each one has its own track) and loosen the sequencers grip . I tried the Humanize and was disappointed and I couldn't manage to get the scripts to work .
just in case someone is looking for a work around.
|
|
|
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 12:28 AM.
|