|
|
|
04-30-2021, 05:58 AM
|
#1
|
Human being with feelings
Join Date: Dec 2017
Location: Brazil
Posts: 2,011
|
Fast way to Delete MIDI Notes from specific channel
Hi People I am using in my MIDI Transfer script a function to delete MIDI Notes with the objective to solo a Channel.
The problem is that it is too slow for huge amount of MIDI it takes a lot of time.
In my test a item with 5600 MIDI notes took 10 second to run. I need to run this more than one time in the script so...
I am wondering if there is a better solution. Here the function I am using
Code:
function SoloChannel(take, ch)
local retval, notecnt, ccevtcnt, textsyxevtcnt = reaper.MIDI_CountEvts( take )
--NOTES
for i = notecnt, 1, -1 do
local retval, selected, muted, startppqpos, endppqpos, chan, pitch, vel = reaper.MIDI_GetNote(take, i-1)
if ch ~= 0 and chan ~= (ch-1) then
reaper.MIDI_DeleteNote(take, i-1)
end
end
--CC
for i = ccevtcnt, 1, -1 do
local retval, selected, muted, ppqpos, chanmsg, chan, msg2, msg3 = reaper.MIDI_GetCC( take, i-1 )
if ch ~= 0 and chan ~= (ch-1) then
reaper.MIDI_DeleteCC( take, i-1 )
end
end
end
|
|
|
05-01-2021, 05:59 AM
|
#2
|
Human being with feelings
Join Date: Sep 2020
Posts: 149
|
Code:
function deletechannel(ch)
local gotAllOK
local MIDIstring
gotAllOK, MIDIstring = reaper.MIDI_GetAllEvts(take, "")
MIDIlen = MIDIstring:len()
tableEvents = {}
stringPos = 1
while stringPos < MIDIlen do
offset, flags, ms, stringPos = string.unpack("i4Bs4", MIDIstring, stringPos)
if ms:len() == 3 and (ms:byte(1)>>4 == 9 or ms:byte(1)>>4 == 8) then
channel = ms:byte(1)&0x0F
if channel == ch-1 then ms="" end
end
table.insert(tableEvents, string.pack("i4Bs4", offset, flags, ms))
end
reaper.MIDI_SetAllEvts(take, table.concat(tableEvents))
end
hwnd = reaper.MIDIEditor_GetActive()
take = reaper.MIDIEditor_GetTake(hwnd)
deletechannel(1)
|
|
|
05-01-2021, 10:37 AM
|
#3
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
As Malfunction advised, MIDI_Get/SetAllEvts is the fastest way to edit many thousands of events. However, if you prefer to use the older functions MIDI_Delete/SetNote/CC, then you should always use MIDI_DisableSort at the start, and MIDI_Sort at the end. This will speed up your script by orders of magnitude. (When using DisableSort, take into account that your note and CC indices will not change while you edit them.)
|
|
|
05-01-2021, 08:14 PM
|
#4
|
Human being with feelings
Join Date: Dec 2017
Location: Brazil
Posts: 2,011
|
hey thanks people for the suggestions I made some bench here:
Code:
function SoloChannel(ch)
local retval, MIDIstring = reaper.MIDI_GetAllEvts(take, "")
local MIDIlen = MIDIstring:len()
local tableEvents = {}
local stringPos = 1
--local pos=0
while stringPos < MIDIlen do
offset, flags, ms, stringPos = string.unpack("i4Bs4", MIDIstring, stringPos) -- Unpack the MIDI[stringPos] event
--pos=pos+offset -- For keeping track of the Postion of the notes in Ticks
if ms:len() == 3 and (ms:byte(1)>>4 == 9 or ms:byte(1)>>4 == 8) then -- if ms:len == 3 means it have 3 messages(Notes, CC,Poly Aftertouch, Pitchbend ) (ms:byte(1)>>4 == 9 or ms:byte(1)>>4 == 8) note on or off
local channel = ms:byte(1)&0x0F -- 0x0F = 0000 1111 in binary . ms is decimal. & is an and bitwise operation "have to have 1 in both to be 1". Will return channel as a decimal number
if channel ~= ch-1 then ms="" end
end
table.insert(tableEvents, string.pack("i4Bs4", offset, flags, ms))
end
reaper.MIDI_SetAllEvts(take, table.concat(tableEvents))
end
function SoloChannelSort(take, ch)
reaper.MIDI_DisableSort( take )
local retval, notecnt, ccevtcnt, textsyxevtcnt = reaper.MIDI_CountEvts( take )
--NOTES
for i = notecnt, 1, -1 do
local retval, selected, muted, startppqpos, endppqpos, chan, pitch, vel = reaper.MIDI_GetNote(take, i-1)
if ch ~= 0 and chan ~= (ch-1) then
reaper.MIDI_DeleteNote(take, i-1)
end
end
--CC
for i = ccevtcnt, 1, -1 do
local retval, selected, muted, ppqpos, chanmsg, chan, msg2, msg3 = reaper.MIDI_GetCC( take, i-1 )
if ch ~= 0 and chan ~= (ch-1) then
reaper.MIDI_DeleteCC( take, i-1 )
end
end
reaper.MIDI_Sort( take )
end
function SoloChannelNoSort(take, ch)
local retval, notecnt, ccevtcnt, textsyxevtcnt = reaper.MIDI_CountEvts( take )
--NOTES
for i = notecnt, 1, -1 do
local retval, selected, muted, startppqpos, endppqpos, chan, pitch, vel = reaper.MIDI_GetNote(take, i-1)
if ch ~= 0 and chan ~= (ch-1) then
reaper.MIDI_DeleteNote(take, i-1)
end
end
--CC
for i = ccevtcnt, 1, -1 do
local retval, selected, muted, ppqpos, chanmsg, chan, msg2, msg3 = reaper.MIDI_GetCC( take, i-1 )
if ch ~= 0 and chan ~= (ch-1) then
reaper.MIDI_DeleteCC( take, i-1 )
end
end
end
function print(val)
reaper.ShowConsoleMsg(tostring(val).."\n")
end
hwnd = reaper.MIDIEditor_GetActive()
take = reaper.MIDIEditor_GetTake(hwnd)
time1 = reaper.time_precise()
--SoloChannel(2) -- 0.028 s
--SoloChannelOriSort(take,2) -- 7s
SoloChannelOri(take,2) -- 95s
print(reaper.time_precise()-time1)
the results in a MIDI with 15k MIDI notes are
1. SoloChannel 0.028s +-
2. SoloChannelSort 7s
3 SoloChannelNoSort 98s
|
|
|
05-01-2021, 08:51 PM
|
#5
|
Human being with feelings
Join Date: Dec 2017
Location: Brazil
Posts: 2,011
|
I wonder if there is a problem deleting all CC using this:
(because of CC that even Reaper don't let the user edit like CC123)
Code:
function DelCC(take, ch)
local retval, MIDIstring = reaper.MIDI_GetAllEvts(take, "")
local MIDIlen = MIDIstring:len()
local tableEvents = {}
local stringPos = 1
--local pos=0
while stringPos < MIDIlen do
offset, flags, ms, stringPos = string.unpack("i4Bs4", MIDIstring, stringPos) -- Unpack the MIDI[stringPos] event
--pos=pos+offset -- For keeping track of the Postion of the notes in Ticks
if ms:len() == 3 and ms:byte(1)>>4 == 11 then -- if ms:len == 3 means it have 3 messages(Notes, CC,Poly Aftertouch, Pitchbend ) (ms:byte(1)>>4 == 9 or ms:byte(1)>>4 == 8) note on or off
ms=""
end
table.insert(tableEvents, string.pack("i4Bs4", offset, flags, ms))
end
reaper.MIDI_SetAllEvts(take, table.concat(tableEvents))
end
|
|
|
05-02-2021, 01:23 PM
|
#6
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by daniellumertz
I wonder if there is a problem deleting all CC using this:
(because of CC that even Reaper don't let the user edit like CC123)
|
Yes, there will be a problem. The loop should end before the final All-Notes-Off CC.
If REAPER doesn't find an A-N-O CC at the end of a take, it will automatically insert one, but the new A-N-O will likely be at a different position (directly after the last event), thereby changing the source length of your take.
|
|
|
05-02-2021, 05:58 PM
|
#7
|
Human being with feelings
Join Date: Dec 2017
Location: Brazil
Posts: 2,011
|
Ok I will make it quit the loop from MIDI CC 120 to match reaper preferences
|
|
|
07-21-2021, 01:24 PM
|
#8
|
Human being with feelings
Join Date: Oct 2017
Location: Black Forest
Posts: 5,067
|
A little follow up here, do we actually need MIDIsort for SetAllEvts?
|
|
|
07-21-2021, 02:53 PM
|
#9
|
Human being with feelings
Join Date: Dec 2017
Location: Brazil
Posts: 2,011
|
In the function I made with Set All Events I haven't used MIDI Sort. So I don't think so (?)
|
|
|
07-21-2021, 03:06 PM
|
#10
|
Human being with feelings
Join Date: Oct 2017
Location: Black Forest
Posts: 5,067
|
Great, that's what I hoped
|
|
|
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.
|