Go Back   Cockos Incorporated Forums > REAPER Forums > REAPER General Discussion Forum

Reply
 
Thread Tools Display Modes
Old 08-22-2016, 03:24 AM   #1
dream_of_the_night
Human being with feelings
 
Join Date: Mar 2013
Posts: 86
Default 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!
dream_of_the_night is offline   Reply With Quote
Old 08-22-2016, 04:44 AM   #2
hopi
Human being with feelings
 
hopi's Avatar
 
Join Date: Oct 2008
Location: Right Hear
Posts: 14,441
Default

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
__________________
...should be fixed for the next build... http://tinyurl.com/cr7o7yl
https://soundcloud.com/hopikiva/angel-rain
hopi is online now   Reply With Quote
Old 08-22-2016, 05:19 AM   #3
dream_of_the_night
Human being with feelings
 
Join Date: Mar 2013
Posts: 86
Default

Thanks!
That's a good workaround...but it's a little time consuming
dream_of_the_night is offline   Reply With Quote
Old 08-22-2016, 08:33 AM   #4
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 2,576
Default

Quote:
Originally Posted by dream_of_the_night View Post
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.
juliansader is offline   Reply With Quote
Old 08-22-2016, 07:08 PM   #5
hopi
Human being with feelings
 
hopi's Avatar
 
Join Date: Oct 2008
Location: Right Hear
Posts: 14,441
Default

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
__________________
...should be fixed for the next build... http://tinyurl.com/cr7o7yl
https://soundcloud.com/hopikiva/angel-rain
hopi is online now   Reply With Quote
Old 08-22-2016, 11:59 PM   #6
dream_of_the_night
Human being with feelings
 
Join Date: Mar 2013
Posts: 86
Default

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. :/
dream_of_the_night is offline   Reply With Quote
Old 08-24-2016, 10:43 PM   #7
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 2,576
Default

Quote:
Originally Posted by hopi View Post
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 View Post
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.)
juliansader is offline   Reply With Quote
Old 08-23-2016, 03:21 AM   #8
dream_of_the_night
Human being with feelings
 
Join Date: Mar 2013
Posts: 86
Default

Quote:
Originally Posted by juliansader View Post
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?
dream_of_the_night is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 01:37 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.