Old 03-30-2016, 03:00 AM   #1
snooks
Human being with feelings
 
Join Date: Sep 2015
Posts: 1,444
Default Issue setting note end pos to following note start pos



So I was putting together a quick script for a thread in General Discussion, but noticed that setting the end position of a note to the start position of the next note of equal pitch sometimes results in a note length of zero. I can subtract one PPQ from the length of course, but if we draw adjoining notes with the MIDI editor, the List View displays the start and end being equal.

If you run this on a selected note a couple of times you should see the issue...

Code:
--get the take active in the MIDI editor
local take=reaper.MIDIEditor_GetTake(reaper.MIDIEditor_GetActive())

local cnt=0 --counter for notes, we access notes by their index number

local notes_to_insert={} -- create a table of notes we want to insert
                         -- because inserting whilst getting them
                         -- messes with getting them all in the right order
                         
--try and get the first note, ok=true if we get one
local ok, selected, muted, sppq, eppq, chan, pitch, vel=reaper.MIDI_GetNote(take, 0)

--this bit only runs if we have a note (ok = true)
while ok do
  if selected then -- only do this if the note we just got is selected
    length=eppq-sppq -- end position (in ppq) minus start = length
    
    new_length=math.floor(length/2) -- always round after dividing
                                      -- for stuff that needs a whole number
    
    eppq=sppq+new_length
    
    reaper.MIDI_SetNote(take,cnt,selected,muted,sppq,eppq,chan,pitch,vel,false) --false=don't sort
    
    -- we want to insert a new note of the same length at the end of the one
    -- we just halved, so we'll store the details to insert later
    notes_to_insert[#notes_to_insert+1]={
         take=take,selected=selected,muted=muted,sppq=eppq,
         eppq=eppq+new_length, chan=chan, pitch=pitch, vel=vel}
  end
  -- increase the counter and try to get the next note, this
  -- "while loop" we are in will repeat if we get one
  cnt=cnt+1
  ok, selected, muted, sppq, eppq, chan, pitch, vel=reaper.MIDI_GetNote(take, cnt)      
end


-- now we go through the table of new notes we stored, inserting them into take
for i=1,#notes_to_insert,1 do
  local n=notes_to_insert[i]
  reaper.MIDI_InsertNote(n.take,n.selected,n.muted,n.sppq,n.eppq,n.chan,n.pitch,n.vel,false)
end


reaper.MIDI_Sort(take) --make sure everything is back in order
Attached Images
File Type: png zero-length-note.png (1.4 KB, 218 views)
snooks is offline   Reply With Quote
Old 04-01-2016, 02:01 PM   #2
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 1,584
Default

Ran into something like that here:
http://forum.cockos.com/showthread.php?t=143366

Some note division scripts here:
http://forum.cockos.com/showthread.php?t=174008

In short, I guess I would say: Delete the notes, then replace them with both (or more.)
FnA is offline   Reply With Quote
Old 04-01-2016, 05:44 PM   #3
snooks
Human being with feelings
 
Join Date: Sep 2015
Posts: 1,444
Default

Yes, deleting all notes then re-adding them works.

It turns out that it's the sorting that Reaper does that causes the issue. If I pass true for noSort and do not sort the take with MIDI_Sort then everything is fine. It looks like the sorting can put the note-off of a previous note after a note-on of a current note or something. Which explains why deleting and re-adding them sequentially works too.

I think it's approaching a definable bug.
snooks is offline   Reply With Quote
Old 04-01-2016, 06:56 PM   #4
FnA
Human being with feelings
 
FnA's Avatar
 
Join Date: Jun 2012
Posts: 1,584
Default

The trickiness is discouraging. I should have added in the join notes thread that spk77s eel script was apparently working fine for a while, then something went bad. Some "definition" would help!
FnA is offline   Reply With Quote
Old 04-02-2016, 03:37 AM   #5
snooks
Human being with feelings
 
Join Date: Sep 2015
Posts: 1,444
Default

I don't know, it looks encouraging because it seems as though there's a three stage process:

1. Insert Events -> events go after rest of events
2. Sort Events -> events put in time order
3. Stuff to prevent broken MIDI existing in items

And it's only #2 that's putting note-offs after note-ons for proceeding events, making #3 tidy stuff that shouldn't need tidied. So only #2 needs tweaked.

At least that's what I gather from looking at the raw MIDI.
snooks is offline   Reply With Quote
Old 04-02-2016, 04:51 AM   #6
schwa
Administrator
 
schwa's Avatar
 
Join Date: Mar 2007
Location: NY
Posts: 9,158
Default

It looks like that script is "split notes in half" rather than what you said?

Regardless, if you are iterating over notes to edit them, and re-sorting them as you go, you can run into trouble (besides being inefficient).
schwa is offline   Reply With Quote
Old 04-02-2016, 05:15 AM   #7
snooks
Human being with feelings
 
Join Date: Sep 2015
Posts: 1,444
Default

Thanks for the reply.. yes, it just splits notes.

The issue still arises when I pass noSort to MIDI_InsertNote when MIDI_Sort is run once at the end of the script.

So this works (running multiple times)...
Code:
--get the take active in the MIDI editor
local take=reaper.MIDIEditor_GetTake(reaper.MIDIEditor_GetActive())

local cnt=0 --counter for notes, we access notes by their index number

local notes_to_insert={} -- create a table of notes we want to insert
                         -- because inserting whilst getting them
                         -- messes with getting them all in the right order
                         
--try and get the first note, ok=true if we get one
local ok, selected, muted, sppq, eppq, chan, pitch, vel=reaper.MIDI_GetNote(take, 0)

--this bit only runs if we have a note (ok = true)
while ok do
  if selected then -- only do this if the note we just got is selected
    length=eppq-sppq -- end position (in ppq) minus start = length
    
    new_length=math.floor(length/2) -- always round after dividing
                                      -- for stuff that needs a whole number
    
    eppq=sppq+new_length
    
    reaper.MIDI_SetNote(take,cnt,selected,muted,sppq,eppq,chan,pitch,vel,false) --false=don't sort
    
    -- we want to insert a new note of the same length at the end of the one
    -- we just halved, so we'll store the details to insert later
    notes_to_insert[#notes_to_insert+1]={
         take=take,selected=selected,muted=muted,sppq=eppq,
         eppq=eppq+new_length, chan=chan, pitch=pitch, vel=vel}
  end
  -- increase the counter and try to get the next note, this
  -- "while loop" we are in will repeat if we get one
  cnt=cnt+1
  ok, selected, muted, sppq, eppq, chan, pitch, vel=reaper.MIDI_GetNote(take, cnt)      
end


-- now we go through the table of new notes we stored, inserting them into take
for i=1,#notes_to_insert,1 do
  local n=notes_to_insert[i]
  reaper.MIDI_InsertNote(n.take,n.selected,n.muted,n.sppq,n.eppq,n.chan,n.pitch,n.vel,true)
end

--reaper.MIDI_Sort(take) --make sure everything is back in order
... but uncommenting the reaper.MIDI_Sort() at the end shows the issue. Here I need to run it twice in a row to produce a zero-length note.

So at least here it doesn't appear to be repeated sorting that is the issue, but any call to MIDI_Sort. It looks like the sort that happens in the MIDI editor is different from MIDI_Sort in some way because if I leave MIDI_Sort commented out, the MIDI is sorted without issues in the MIDI editor when I click in it (viewing raw MIDI).
snooks is offline   Reply With Quote
Old 04-02-2016, 05:27 AM   #8
snooks
Human being with feelings
 
Join Date: Sep 2015
Posts: 1,444
Default

Here's the raw MIDI after a sort that produces a zero length note....
Code:
   +0       0:  90 3C 60
 +1680    1680:  80 3C 00
    +0    1680:  90 3C 60
 +1680    3360:  90 3C 60
    +0    3360:  80 3C 00
 +1680    5040:  80 3C 00
    +0    5040:  90 3C 60
 +1680    6720:  80 3C 00
+20160   26880:  B0 7B 00
... and here it is re-running after commenting MIDI_Sort...
Code:
    +0       0:  90 3C 60
 +1680    1680:  80 3C 00
 +1680    3360:  90 3C 60
 +1680    5040:  80 3C 00
+21840   26880:  B0 7B 00
+-25200    1680:  90 3C 60
 +1680    3360:  80 3C 00
 +1680    5040:  90 3C 60
 +1680    6720:  80 3C 00
... which is sorted correctly when clicking the MIDI editor...
Code:
    +0       0:  90 3C 60
 +1680    1680:  80 3C 00
    +0    1680:  90 3C 60
 +1680    3360:  80 3C 00
    +0    3360:  90 3C 60
 +1680    5040:  80 3C 00
    +0    5040:  90 3C 60
 +1680    6720:  80 3C 00
+20160   26880:  B0 7B 00
snooks is offline   Reply With Quote
Old 04-02-2016, 05:43 AM   #9
schwa
Administrator
 
schwa's Avatar
 
Join Date: Mar 2007
Location: NY
Posts: 9,158
Default

Hm, this is somewhat technical. I'll see if there is a simple way to fix the problem.
schwa is offline   Reply With Quote
Old 04-02-2016, 05:43 AM   #10
snooks
Human being with feelings
 
Join Date: Sep 2015
Posts: 1,444
Default

Whoops, I'm sorting with SetNote while getting them too, I'll just check with that off.... phew, still doesn't work.

@schwa: thanks for looking into this!

Last edited by snooks; 04-02-2016 at 05:49 AM.
snooks 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 04:47 AM.


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