Old 05-25-2017, 08:33 AM   #1
daeavelwyn
Human being with feelings
 
daeavelwyn's Avatar
 
Join Date: Dec 2014
Posts: 597
Default Set item events to a specific chan

Hi everyone,

I'm trying to find a solution to the strange behaviour I get and explained here : http://forum.cockos.com/showthread.php?t=187524 and here : http://forum.cockos.com/showthread.php?t=188474

And I wonder if there is a way to assign specific channel for midi events in an item WITHOUT using MIDI Editor.

I mean, I select a midi item in the arrange view and call a custom action/script that automatically sets all events in this item to chan 16.

thanks for your suggestions
daeavelwyn is offline   Reply With Quote
Old 05-25-2017, 12:21 PM   #2
lunker
Human being with feelings
 
lunker's Avatar
 
Join Date: Nov 2007
Location: Lucas, TX, USA (via Luleå, Sweden)
Posts: 2,008
Default

I'm not sure I understand the context of your question.

I don't think there is a native command to do this, but it is certainly something that could be done with reascript.

I have several eel and lua programs where I select a MIDI item in the arrange view, and the program does things to the events in the item (such as changing the channel) without the user having to open a MIDI editor.

So yes, definitely possible. I couldn't tell from the threads you referenced whether you have tried writing one, and couldn't get it to work, or whether you are asking if it's possible so that you know whether to try writing one.
__________________
Best Regards, Ernie "lunker" Lundqvist
BDSM (Bad Dog Studio Musicians)
Windows 10 running on Z390 + i7-8700

Last edited by lunker; 05-25-2017 at 12:29 PM.
lunker is online now   Reply With Quote
Old 05-25-2017, 01:01 PM   #3
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
Default

Sorry, for crossing by, but...

Quote:
Originally Posted by lunker View Post

I have several eel and lua programs where I select a MIDI item in the arrange view, and the program does things to the events in the item (such as changing the channel) without the user having to open a MIDI editor.
that's exctly what I'm also looking for currently (setting all events of selected MIDI items to a specific channel. Not having to use the MIDI editor for it would even be better).

http://forum.cockos.com/showthread.php?t=192250

http://forum.cockos.com/showthread.php?t=192213

Would you mind sharing this script ?
nofish is offline   Reply With Quote
Old 05-25-2017, 01:13 PM   #4
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 3,960
Default

first try with lua
native API looks buggy

Code:
  channel = 16
  
  function SetEventsChannelForSelectedItem()
    local item = reaper.GetSelectedMediaItem(0,0)
    if not item then return end
    local take = reaper.GetActiveTake(item)
    if not take or not reaper.TakeIsMIDI(take) then return end
    local _, notecntOut, ccevtcntOut = reaper.MIDI_CountEvts( take )    
    for i = 1, math.max(notecntOut, ccevtcntOut) do
      if reaper.MIDI_GetCC( take, i-1 )  then reaper.MIDI_SetCC( take, i-1, nil, nil, nil, nil, channel-1, nil, nil, true ) end
      if reaper.MIDI_GetNote( take, i-1 ) then reaper.MIDI_SetNote( take, i-1, nil, nil, nil, nil, channel-1, nil, nil, true ) end
    end
    reaper.MIDI_Sort( take )  
  end 
  
  SetEventsChannelForSelectedItem()

EDIT: SWS/FNG (note only) also buggy

Code:
channel = 16
  
  function SetEventsChannelForSelectedItem_FNG_mod()
    local item = reaper.GetSelectedMediaItem(0,0)
    if not item then return end
    local take = reaper.GetActiveTake(item)
    if not take or not reaper.TakeIsMIDI(take) then return end
    local fng_tk = reaper.FNG_AllocMidiTake( take )
    for i = 1, reaper.FNG_CountMidiNotes( fng_tk )  -1 do
      local fng_note = reaper.FNG_GetMidiNote( fng_tk, i-1 )
      if fng_note then reaper.FNG_SetMidiNoteIntProperty( fng_note, 'CHANNEL', channel )    end
    end
    reaper.FNG_FreeMidiTake( fng_tk )
  end 
  
  SetEventsChannelForSelectedItem_FNG_mod()

Last edited by mpl; 05-25-2017 at 01:31 PM.
mpl is offline   Reply With Quote
Old 05-25-2017, 01:25 PM   #5
lunker
Human being with feelings
 
lunker's Avatar
 
Join Date: Nov 2007
Location: Lucas, TX, USA (via Luleå, Sweden)
Posts: 2,008
Default

EDIT: ACK!! I was too slow!

I certainly don't mind. I posted one here a while ago: http://forum.cockos.com/showpost.php...01&postcount=5

If you try to run it, make sure you grab the library file that I included a few posts later. If you just want to look at the code, don't bother with the library file. It's just a function that gaussian randomizer function.

That program does a lot of other stuff, which obscures the task you are trying to perform. After sifting through this program, I think the basic structure you want would be something like this:

Code:
// eel code (lua would be similar)

// get the current take of the selected item

    Item = GetSelectedMediaItem   (0, 0);
    Take = GetMediaItemInfo_Value (Item, "I_CURTAKE");


// get the number of events

    MIDI_CountEvts (Take, Count.Note, Count.Cc, Count.TextSysex);


// loop through all the CC events, and reset the channel

    Cc.Index = 0;

    while (Cc.Index < Count.Cc) (

        MIDI_GetCC (
            Take
          , Cc.Index
          , Cc.IsSelected
          , Cc.IsMuted
          , Cc.Pos
          , Cc.Msg1
          , Cc.Channel
          , Cc.Msg2
          , Cc.Msg3
        );

        MIDI_SetCC (
            Take
          , Cc.Index
          , Cc.IsSelected
          , Cc.IsMuted
          , Cc.Pos
          , Cc.Msg1
          , 15 // 0 = channel 1, 15 = channel 16
          , Cc.Msg2
          , Cc.Msg3
        );

        Cc.Index += 1;

    );

I can't guarantee that the code above is correct, because I cut it from different parts of the program, and had to modify some terms when I pasted it in here. But that should be the basic structure you want. Now that I've learned lua, I can certainly say that I prefer it over eel. But it seems that I don't actually have a lua program that does this type of thing yet. But the lua structure would be identical. The only difference would be the syntax of some commands (and of course the fact that I liked to use periods in my eel variable names, which doesn't work in lua).
__________________
Best Regards, Ernie "lunker" Lundqvist
BDSM (Bad Dog Studio Musicians)
Windows 10 running on Z390 + i7-8700

Last edited by lunker; 05-25-2017 at 01:33 PM.
lunker is online now   Reply With Quote
Old 05-25-2017, 02:49 PM   #6
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
Default

Thank you both, this helps a lot.

The surrounding stuff for my needs (work on all selected items, add user prompt for channel) I'm fine adding myself.

mpl, of course I'll also test myself soon but what do you mean with 'buggy' ?
Did you find the used API functions not working correctly already ?

Last edited by nofish; 05-25-2017 at 02:56 PM.
nofish is offline   Reply With Quote
Old 05-25-2017, 02:54 PM   #7
daeavelwyn
Human being with feelings
 
daeavelwyn's Avatar
 
Join Date: Dec 2014
Posts: 597
Default

Thanks mpl, your lua script seems to work for me ! :-D

[OutOfTopic] And I love your music, just listened your soundcloud [/OutOfTopic]
daeavelwyn is offline   Reply With Quote
Old 05-25-2017, 08:52 PM   #8
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 3,960
Default

Yes, nofish, they aren't applying properly (changed length, need to run twice or more to get all notes looped).
mpl is offline   Reply With Quote
Old 05-26-2017, 04:09 AM   #9
juliansader
Human being with feelings
 
Join Date: Jul 2009
Posts: 3,714
Default

If the scripts above are not applying properly, you can also try the following:

(It should change the channels of all CCs as well as notes and notation events.)

Code:
-- Change the channel of all notes and CCs in all selected items to specified channel

newChannel = 15 -- Channel to which events should be changed (0-15, NOT 1-16).


---------------
notationReplacementText = string.format("NOTE %i ", newChannel) -- Will be used to replace channel info in REAPER's notation events

-- First, loop through all selected items
for i = 0, reaper.CountSelectedMediaItems(0)-1 do
    item = reaper.GetSelectedMediaItem(0, i)
    
    -- Loop through all takes within each selected item
    for t = 0, reaper.CountTakes(item)-1 do
        take = reaper.GetTake(item, t)
        if reaper.TakeIsMIDI(take) then
        
            -- Use the new Get/SetAllEvts functions to directly (and quickly) edit the MIDI data
            local gotAllOK, MIDIstring = reaper.MIDI_GetAllEvts(take, "")
            if gotAllOK then
            
                local tableEvents = {} -- MIDI events will temporarily be stored in this table until they are concatenated into a string again
                local t = 1 -- Index inside tableEvents
                local MIDIlen = MIDIstring:len()
                local positionInString = 1 -- Position inside MIDIstring while parsing
                local offset, flags, msg
                -- Now parse through all events in the MIDI string, one-by-one
                -- (Excluding the final 12 bytes, which provides REAPER's All-notes-off end-of-take message)
                while positionInString < MIDIlen-12 do 
                    offset, flags, msg, positionInString = string.unpack("i4Bs4", MIDIstring, positionInString)
                    local msg1 = msg:byte(1) -- The first byte contains the event type and channel
                    if msg1 then -- If empty event that simply changes PPQ position, msg1 will be nil
                        if msg1>>4 ~= 0xF then -- First nybble gives event type; exclude text/sysex messages, which do not carry channel info
                            msg = string.char(((msg1 & 0xF0) | newChannel)) .. msg:sub(2) -- 2nd nybble gives channel
                        elseif msg1 == 0xFF then -- REAPER's notation events also refer to the note channel
                            msg = msg:gsub("NOTE %d+ ", notationReplacementText, 1)
                        end                    
                    end
                    tableEvents[t] = string.pack("i4Bs4", offset, flags, msg)
                    t = t + 1
                end
                
                -- This script does not change the order of events, so no need to call MIDI_Sort after updating take's MIDI
                reaper.MIDI_SetAllEvts(take, table.concat(tableEvents) .. MIDIstring:sub(-12))
                
            end -- if gotAllOK
        end -- if reaper.TakeIsMIDI(take)
    end
end

reaper.Undo_OnStateChange("Set channel of all MIDI in selected items")

Last edited by juliansader; 05-26-2017 at 03:41 PM.
juliansader is offline   Reply With Quote
Old 05-26-2017, 05:37 AM   #10
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
Default

Thanks Julian.

Actually I played around with using the new Get/SetAllEvts API for this (as I've read it's considerably faster) but couldn't quite wrap my head around it, so this is very welcome.
nofish is offline   Reply With Quote
Old 05-26-2017, 08:43 AM   #11
mpl
Human being with feelings
 
mpl's Avatar
 
Join Date: Oct 2013
Location: Moscow, Russia
Posts: 3,960
Default

whoa I didn`t saw that API, looks interesting, Julian
mpl is offline   Reply With Quote
Old 05-27-2017, 11:24 AM   #12
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
Default

I've added a user input prompt to Julian's version and some other small additions (like checking for required Reaper version).

edit:
Available now in my ReaPack repo.
(Julian, if you're not ok with this, just tell me and I'll take it down.)

Last edited by nofish; 05-29-2017 at 11:32 AM.
nofish is offline   Reply With Quote
Old 05-27-2017, 01:55 PM   #13
Pet
Human being with feelings
 
Pet's Avatar
 
Join Date: Nov 2015
Location: Germany
Posts: 1,015
Default

This is s.th. I really wanted to have since I use REAPER. (Well that's not THAT long, but...)

THANKS!
__________________
If the v5 Default Theme is too bright for you take a gander at my mod of it: Default v5 Dark Theme
Pet 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:35 AM.


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