Jump to content

Multiple MIDI CC Remap Plugin?


michaelrasbury

Recommended Posts

Could you help me by adding code that also sends this across all 16 MIDI channels. This works really well on the current channel. I have a KONTAKT instance with 11 different articulations each on their own MIDI channel. I use Logic's articulation sets to switch between them using the TYPE: PROGRAM and CHANNEL commands to switch between them. When I am recording, my CC data physically being triggered by an assigned fader or foot pedal seems to affect any articulation on any channel, but when I play the recording back, the captured CC data seems to only impact the articulation on MIDI channel one. So, I'd like to be able to transform CC data like the attached code so eloquently does, but add something that then sends it out to all MIDI channels. I have two scripts- one that you cleaned up that I use for transposing CC numbers, and a second one that I found that sends all CC data across all MIDI channels, but I must be using incorrect syntax because I can't combine them and make them work. Both of them work perfectly when loaded into scripter independently, though. I will attach what I am trying to do! I have tried to remove the redundant "HandleMIDI" function and nest all this in different ways but one negates the other. I assume it has everything to do with the duplicate "var i" language.

 

var ccMap = [];
for(let i=0;i<128;i++) {
   ccMap[i] = {num: i, revorder: false};
}

ccMap[11].num = 1;
ccMap[7].num = 11;

ccMap[47].num = 47;
ccMap[47].revorder = true;

function HandleMIDI(event) {
  if (event instanceof ControlChange) {
      if (ccMap[event.number].revorder == true) {
          event.value = 127 - event.value;
      }
      event.number = ccMap[event.number].num;
  }
  
  event.send();
}   

function HandleMIDI(event) {
  if (event instanceof ControlChange) {
     // Duplicate for all 16 channels.
     var i = 1;
     while (i <= 16) {
        event.channel = i;
        event.send();
        i++
     }
  }
  else {event.send()}
}

The above works fine.. It could be done different ways... There is not necessarily any right or wrong way to do it. I would prefer to setup this kind of situation with an array map, because its easy to maintain and tweak.

 

var ccMap = [];
for(let i=0;i<128;i++) {
   ccMap[i] = i;
}

ccMap[2] =   1;
ccMap[1] =  21;
ccMap[3] =  20;
ccMap[15] = 26;
ccMap[42] = 16;
ccMap[43] = 17;
ccMap[46] = 28;
ccMap[50] = 29;
ccMap[52] = 33;

function HandleMIDI(event) {
   if(event instanceof ControlChange) {
       event.number = ccMap[event.number];
   }
   
   event.send();
};
Link to comment
Share on other sites

So first... each call to event.send() can only send to one midi channel. if you want to send it to all 16 midi channels, then you have to write some code at all the right places that will call that function 16 times, changing the midi channel attribute of the midi event to values 1-16 for one.

 

You can write a little function to do that, and then call that function instead of calling event.send()

 

For example,

 

function sendAll(event) {
   let remember = event.channel;
   for(let m=1; m<=16; m++) {
       event.channel = m;
       event.send();
   }
   event.channel = remember;
}

 

Then after making that function, you have to go find all the places in your code where you are now calling event.send() and change them to call this sendALL function instead (for the cases where you want it sent to all 16 midi channels

 

   .
   .
   sendAll(event);
   .
   .

 

Here is an advanced solution, perhaps slightly more elegant way, to the above for people interested in learning more about Scripter. In this solution I will extend the capability of the Event object to include a sendAll method inside the Event object itself.

 

Event.prototype.sendAll = function() {
   let remember = this.channel;
   for(let m=1; m<=16; m++) {
       this.channel = m;
       this.send();
   }
   this.channel = remember;
};

In the above, the sendAll feature becomes part of the actual event, so in your code whenever you want something sent to all midi channels you would simply do this:

 

   .
   .
   event.sendAll();
   .
   .

 

Really its not much different just throwing it out for pondering possibilities..

 

Now all that being said... you should consider that when you duplicate all your CC's to all 16 channels...you are going to create 16x as much midi traffic in the Logic midi streams...and this can cause substantial CPU usage as well as a potential for dropped events if the midi stream in LogicPro gets clogged from too much traffic at once. This is a bit of a sledge hammer approach to the problem you're trying to solve. if you think about it, out of 16 channels hosting your 16 articulations, at any one time, only one or MAYBE 2 will be actually making any sounds at once. So you don't actually need the CC's all copied 16 times always. You need them copied to the right channels at the right times...hehe..but that is complicated topic and script to make. Fortunately I have made a few already that can do that for you.

 

I understand why you are remapping your CC's, now you should draw some attention to different topic which is about how to channelize your articulation notes, as well as any CC's coming from your source track that needs to be channelized to various channels where articulations are listening. Its not only CC's, actually PitchBend, AfterTouch could also matter too!

 

Here are two scripts I have done already that you can look into using. Use two instances of Scripter...one for your remapping task...separately...and then from there go to one of these channelizer scripts which will re-channelize things appropriately for you. One of them re-channelizes the notes as well as CC's...based on articulation ID. The other one doesn't re-channelize the notes..it simply re-channelizes CC's to the other 16 channels...but only when there are actually notes sounding on them!

 

Channelizer: viewtopic.php?f=45&t=143326

 

EventChaser: viewtopic.php?f=45&t=139186

 

Note - I haven't looked at the second one in a couple years, so let me know if it actually still works or any problems.

Link to comment
Share on other sites

This is awesome information. Thank you so much. It will take me a little while to digest it all. I will ask-why do you think I should use the EventChaser over the channelizer? Why would it be better to use one that only sends CC data when there are notes sounding? Do you recommend your Channelizer over the EventChaser?

 

I immediately started using channelizer. I did not read that I shouldn’t have anything in the output section, yet did not run into any problems. I will try removing all of that and stick just to the articulation IDs and name as you suggest in your other post. However, what if I have a play instance with five articulations on five different midi channels but one of those articulations also has key switches? How do I access those articulations found on the key switches in the patch loaded on that one midi channel without programming the output section of the articulation set? And without loosing the MIDI CC Data channelizing to channel 5?

 

Another example... I have a Kontakt instance set up with the five Violin patches available between both Musical Sampling's Soaring and Adventure Strings libraries.

Channel 1-Adventure Strings Patch

Channel 2-Sustains Patch

Channel 3-Legato Patch

Channel 4-Stacc-Spicc Patch (Velocity controls dynamics, CC controls a crossfade between Spiccato notes and Staccato notes)

Channel 5-Trills KS Patch (C2 triggers minor 2nd trill and C#2 triggers major 2nd trill)

 

How do I use your script AND on MIDI CHANNEL 4, add an articulation ID that chooses Spiccato by choosing MIDI CHANNEL 4 and CC Value of zero, and a second articulation that chooses Staccato by choosing MIDI CHANNEL 4 and CC Value of 127.

On MIDI Channel 5 I need two articulations because the patch has a key switch. I would like one Articulation call "Trills Minor 2nd" that switches to MIDI channel 5 and sends a keyswitch of C2 in the output window- and then a second one to select the major 2nd trill.

 

And of course need CC Data to channelize along with the MIDI notes to the proper channel.

 

I guess some of that is not possible with the Channelizer script?

 

I will say that the EventChaser script seems to allow me to do all of the above, but what I'm not sure about is if it is increasing the MIDI traffic by 16x like you said. It lets me use output settings per articulation, specifying which MIDI channel, and note and CC data to use.

 

Logic handles multitimbral instruments in less than logical ways. This is a solution for that! I couldn't stand they way Logic handled what I thought of as multi-timbral until I found I could load an instance of Kontakt or Play with multiple patches on individual MIDI channels and then assign Articulation ID's to notes to send to these different patches. It's just that I was stymied when I found that the CC data (for dynamic crossfading, etc.) that was captured on MIDI Channel 1 was not also being send to those patches on other MIDI channels when selected.

Link to comment
Share on other sites

When articulationset uses anything in the output section it strips articulation away from the midi event. So channelizer cannot function function without articulation Id.

 

The main advantage of channelizer is that it can support more then 16 channels in vepro7. If you’re not using vepro you can keep it simple with event chaser.

 

There is a work around for using channelizer in combination with articulation set keyswitches but ask me later about that if you need it.

 

With these two scripts the cc, after touch and pitch bend events will all be propagated to the channels where notes are sustaining and will specifically not propagate when there are no notes and doesn’t need to be sent. As I said above the excess midi traffic can become problematic if you just send all cc to all 16 channels all the time

Link to comment
Share on other sites

OK. Thank you so much for your expertise. I will stick with EventChaser for now! Just above it I am running a second scripter instance that transforms my midi cc data from one number to another so I don’t have to change the manufacturer’s default in their patches. I did a quick test and for now it all seems to be working :-)
Link to comment
Share on other sites

Yea, LogicPro multi-timbral handling has a few wierdities, but on the other hand, there is Scripter. You can't do anything like this with Cubase...channelizing with the propagation of CC's.. So we live with LogicPro's quirks..

 

I wasn't entirely clear on what you were asking earlier..about mixing different libraries. if you were meaning to layer some of them, that's another topic.

 

But in any case, if you use Vepro, then you can have up to 127 source tracks feeding up to 768 articulation channels in hosting articulations in various ways. So channelizer is great for that situation. But in order to do that, it needs to do its own channelizing.....mostly.. hehe.

 

if and when LogicPro is using AU3 instrument (which Kontakt is not), then you will see a port field on each track..so that you can specify both port and channel. But articulation Sets currently do not provide a way to specify port.

 

So you could use articulation set to channelizing the channel parameter, so long as any given instrument track doesn't need to go around ports. That could work with EventChaser if you use always one source track per port and never put more than one source track into any single port, etc.

 

Channelizer is able to automatically detect the incoming channels being used and just provides a bit more flexibility with VePro. if you aren't using VePro, you probably don't need channelizer. And as you said, channelizer won't let you send key switches from the articulation set.

 

Well there is one work around for channelizer... you can use an extra CC in the articulation set output section to basically encode the articulation ID as a CC value. Then later you can use a Scripter script that can translates that CC back to articulationID, so that Channelizer can function. Eventually I may build that functionality right into Channelizer itself. That would allow you to use two more key switches per articulation, and sill shave the articulationID sent along to channelizer. (LogicPro only allows up to three key switches per articulationID.

 

Still another possible solution is to use a script to add key switches for those couple of cases where you need them, when most of the time channelizing alone will suffice, so it would not be hard to use a script to insert a few specific key switches for those cases. LogicPro wins again there, thanks to Scripter.

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...