Jump to content

Kontakt Multi-Port


Recommended Posts

I have worked out a way to use up to 64 midi channels into a single instance of Kontakt, using ports A,B,C,D, which normally are only accessible through the standalone version, but this tutorial and supplied templates will let you access them in the plugin version.

 

Here are two LogicPro projects provided, one is an empty template, and the other is a working example using the factory kontakt instruments as an example case using 28 midi channels into a single Kontakt instance.

 

Template: KontaktMulti64.zip

Example Project: KontaktMulti64Example.logicx.zip

 

Truthfully, its probably a better idea in LogicPro to spread the cpu load to multiple kontakt instances in most cases, but I offer this solution for anyone seeking anything similar or to build upon further. One case where this kind of thing can make a lot of sense is when working with an instrument that has more than 16 articulations as separate kontakt instruments.

 

Working Example

 

In this case Kontakt is loaded with 28 instruments in slots A and B. Here is a screenshot of the B slot with 14 channels B1->B14 using some instruments. Slot A also has 14 instruments.

 

kontakt.thumb.jpg.844cc4f9018be3bd8efa197fe88b5cce.jpg

 

Here is the arrange page showing the tracks.. Clicking on any track will find midi routed to the right instrument in kontakt, including in the B slot...

 

tracklist.thumb.jpg.9fbff28fbaa3c1f9df557e4412aebdc2.jpg

 

The mixer can accommodate up to 25 stereo returns, so in this example I have 28 instruments (a few are consolidated in the audio returns) and their separate returns are giving me all the mixer channels for each one:

 

mixer.thumb.jpg.0360975488650287a0056bfa0302ebe3.jpg

 

How it works

 

This is enabled by two special tricks. One is that I am using the old VePro6 multiport macro to insert CC99 events in front of all events coming from each track.

env.thumb.jpg.19958490bb6cde897b940231d896b9fa.jpg

 

In addition to that, a special Scripter script is being used on the kontakt channel. This script translates the CC99 events into ProgramChange events containing the port number. It also handles a few other housekeeping tasks related to ALL NOTES OFF that were part of the old VePro multiport macro templates. This script is already included in the above project templates. (Note, it might be possible to modify the environment multiport macro to generate PC messages directly instead of CC99 and then avoid needing this special script, but the ALL NOTES OFF handling is still somewhat needed. I just reused the old multiport macros as is for now.)

 

 

//=============================================================
// Handle NoteOff, like we had to do with CC99 stuff in VePro
// but also convert CC99 to PC messages 1-4
// don't index port value by zero.
//=============================================================


var NeedsTimingInfo = true; //only needed to detect play state

var TRACE = false;
var TRACE99 = false;
var MAXFLUSH = 20;

// array to track the last received port for any given channel
var lastPort = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
var tempLastPort = 0;
var maxPorts = 0;

var pc = new ProgramChange;

//=============================================================
// Actual HandleMIDI function
//=============================================================

function HandleMIDI(event) {
   
   // keep track of the current port for each channel
   // don't forward on the CC99 event
   if(event instanceof ControlChange && event.number == 99) { 
   
       //if( event.value+1 != lastPort[event.channel]) {
       if( event.value+1 != tempLastPort) {
           
           tempLastPort = event.value+1;
           lastPort[event.channel] = tempLastPort;
             
           // convert to PC by number       
           pc.number = event.value+1;
           pc.channel = event.channel;
           pc.port = event.value+1;
           pc.send();
           if(TRACE99) {
               logEvent(event);
           }               
       }
       return;       

   }
   else {
       event.port = lastPort[event.channel];
       if(event instanceof NoteOn && event.port > maxPorts) {
           maxPorts = event.port;
       }
   }
   
   //================================================
   // If all Notes Off for channel, handle specially, 
   // forward to all ports
   //================================================
   
   if (event instanceof ControlChange 
           && event.number == 123 
           && event.value == 0) {

       AllNotesOffByChannel(event.channel);
       return;
   }

   //==============================================
   // INSERT code here for sending keyswitches, etc
   // when inserting keyswitches, send the port attr
   // and call SendByPort(event).  For example:
   //     var keyswitch = new NoteOn;
   //     keyswitch.port = lastPort[event.channel];
   //     SendByPort(keyswitch);
   //==============================================

   // Send actual event 
   event.send();
   logEvent(event);

}


//=========================================
// send VEP multi port encoder in front
// of actual event
//=========================================


function SendByPort(event) {
   
   if(event.port != undefined && event.port > 0) {
       pc.channel = event.channel;
       pc.number = event.port;
       pc.send();
       if(TRACE99) {
           logEvent(cc99);
       }
   }

   event.send();
   logEvent(event);
}


//===================================================
// Prcoess MIDI is used to detact transport STOP
// in order to send AllNotesOff to all ports/channels
//===================================================

var playState = false;

function ProcessMIDI() {
   var ctx = GetTimingInfo();
   
   if (ctx.playing) {
       playState = true;
   } 
   
   else {
       if (playState == true) {
           // stop recently happened
           AllNotesOff();
           playState = false;
       }
   }
}

//====================================
// AllNotesOff all Channels
//====================================

function AllNotesOff() {
   for (var chan = 1; chan <= 16; chan++) {
       AllNotesOffByChannel(chan);
   }
   maxPorts = 0;
}

//=======================================
// Propagate AllNotesOff to all ports
// for a given midi channel
//=======================================

var ccOff = new ControlChange;
ccOff.number = 123;
ccOff.value = 0;
// var note = new NoteOn;

function AllNotesOffByChannel(channel) {
   for (var port = 1; port <= maxPorts; port++) {
       ccOff.channel = channel;
       ccOff.port = port;
       SendByPort(ccOff);
   }
}

//===================================
// Buffered Tracing if turned on
//===================================

var buffer = [];

function logEvent(event) {
   var port = (event.port == undefined || event.port < 1) 
               ? "" : (" [port:"+event.port.toString().padStart(2, "0")+"]");

   logMsg(event.toString() + port);
}

function logMsg(str) {
   if(TRACE) {
       buffer.push(str);
   }
}

function logErr(str) {
       buffer.push(str);
}

function Idle() {
   for (var i = 0; i < MAXFLUSH; i++) {
       if (buffer.length > 0) {
           Trace(buffer.shift());
       }
   }
}

 

 

In addition to the above, Kontakt is using a special KSP multi-script which translates the ProgramChange messages into appropriate midi routing to ports A,B,C,D. The preloaded Kontakt multi has this KSP script included in it.

 

on init
   declare $runningPort
   declare $channel
   $runningPort := 1
end on

on midi_in   
   { Detect PC#127, only for BYTE2 values 1-4 }
   if ($MIDI_COMMAND = $MIDI_COMMAND_PROGRAM_CHANGE)
       if( $MIDI_BYTE_1 < 5 ) 
           $runningPort := $MIDI_BYTE_1
           ignore_midi
           exit
       end if
   end if

   {All other midi events, rechannelize to port based on last running port# }
   $channel := ($runningPort-1) * 16 + $MIDI_CHANNEL
   set_event_par($EVENT_ID,$EVENT_PAR_MIDI_CHANNEL,$channel)
   
end on

 

That's all there is to say about it really. It works like a charm for the most part. 64 tracks to one kontakt instance.

 

The general approach can be further enhanced in combination with Articulation Sets to provide, for example, more than 16 articulations in a single kontakt instance.

 

Hope anyone finds this useful or generates further ideas or discussion. As I said, I think this is somewhat a hypothetical exercise to see if it was possible, in actuality, I would rather run separate instances of Kontakt per instrument in LogicPro in order to spread CPU load around. Generally.

Link to comment
Share on other sites

I also made some scripts and templates for handling more than 16 articulations to a large Kontakt multi. This is more interesting actually then the above example, and does not require any environment multi-port macro. I will be sharing more information about that at a future time, but suffice it to say for now that its possible to have up to 64 articulationID's that drive events to up to 64 separate listening midi channels within a single kontakt instance.. Nice. That is definitely interesting to me.

 

However, I also found that in some ways it might be easier to just send 64 articulationID's to multiple instances of kontakt..which is also possible in LogicPro by using a simple environment splitter or even a track stack and then a small script to filter out which articulationID's are handled by each kontakt instance. That avoids needing any special KSP script and is probably the way to go for this kind of task... but anyway, if someone wants it all in one simple channel..then the above KSP trick is definitely useful for that.

Link to comment
Share on other sites

  • 2 years later...

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...