Posted by & filed under Bitwig Studio, Blog, Featured, Tutorials.

One of the more exciting things about K-Mix is its flexibility. When connected to a computer this device can serve as an Audio Interface, Mixer, and Control Surface all at the same time. While using the K-Mix in Mix mode, the diamond pad will send standard Mackie Control Messages. These messages can be used with a variety of different software to control common transport functions. In this article we will quickly write a control script to get the K-Mix controlling transport functions in Bitwig Studio.

I won’t spend much time explaining the details of the code examples,  so it might be helpful to take a look at a series of posts from a while back that gives a general overview of creating a script from scratch. You’ll only need a text editor and a K-Mix!

So let’s start by setting up a folder to store our script by navigating to one of the following directories. Once there, create a new folder and call it KMI (if you already have a KMI controller folder, this will be unnecessary).

Mac: Documents/Bitwig Studio/Controller Scripts
Windows: %USERPROFILE%\Documents\Bitwig Studio\Controller Scripts\

Now that we have our folder, create a new text file and name it KMix.control.js, and save it in our KMI folder. Let’s initialize the script with all the pertinent controller information. This will allow the K-Mix to be detected automatically by Bitwig and it will also assign the proper MIDI port.


//Load the bitwig API
loadAPI(1);

//Define/set our controller properties [ company, device, version, uuid ]
host.defineController("Keith McMillen Instruments", "K-Mix", "1.0", "4034A480-F81D-11E5-A837-0800200C9A66");
host.defineMidiPorts(1,1);

//Define/set input/output port names
host.addDeviceNameBasedDiscoveryPair(["K-Mix Control Surface"],["K-Mix Control Surface"]);

We next need to declare our global variables, which can be accessed globally from any function. We will be interacting with the transport, so let’s create a new variable called ‘transport’.

var transport;

We can also create two variables that we will need later while we’re here. We will be dealing with the position of the playhead in Bitwig and a length of time to rewind, so let’s go ahead and declare those and initialize some values.

var position = 0;
var rewind_length = 1.0 //this is a value in bars

Then we need to make the init function that is called when we start the script. This will set up all of our objects and observers. In this case we only need to worry about the MIDI callback function and the transport. We assign a MIDI callback function ‘onMidiPort1’ to the first MIDI port. We haven’t created this function yet, but when we do it will be called every time we receive MIDI input on that port. We also create a view onto the Bitwig transport and assign it to our global ‘transport’ variable.

function init()
{
     //Setting the MIDI callback, and creating our transport object.
     host.getMidiInPort(0).setMidiCallback(onMidiPort1);
     transport = host.createTransport();
     //getting the transport position.
     time = transport.getPosition();
     time.addRawValueObserver(function(value)
     {
          position = Math.round(value);
     })
}

The code for getting the transport position will be used to calculate our rewinding function later. There isn’t a prebuilt rewind function (that I could find), so we’ll have to make our own. This observes the value of the position of the transport and rounds it to the nearest whole number, which represents bars.

Now that we can receive MIDI, we need to figure out what each of the button presses send out. The K-Mix sends MCU (Mackie Control Universal) MIDI messages, but it’s pretty simple to figure out what they are by creating our MIDI callback and adding a println function to print the MIDI input to Bitwig’s controller console.

function onMidiPort1(status, data1, data2)
{
println("Port 1 [status, data1, data2]: " + status + ", " + data1 + ", " + data2);
}

If you watch the control script console in Bitwig and hit the diamond pad on the K-Mix you will see some formatted strings of data giving you one status byte, and two data bytes. A status of 144 indicates a note on, and the first data byte tells us which button we pressed. We can easily format a conditional to control the transport based on this information. Let’s add this below our println statement.


if(status == 144){
     if(data1 == 93){
          //Stopping the transport
          transport.stop();
     }else if(data1 == 94){
          //playing the transport
          transport.play();
     }else if(data1 == 95){
          //arming the session
          transport.record();
     }else if(data1 == 91){
          //setting the new transport position
          time.setRaw(position - rewind_length)
          transport.rewind();
     }
}

All of the function calls on the transport are self-explanatory, except for the rewind. When we receive the rewind command we want to set the raw value of the time parameter to the current position minus the rewind length and then call the rewind function. What’s cool about this is that you can freely edit the rewind length to suit your needs, or assign that value to a MIDI controller to have real time control over the rewind length. You could also forego the suggested controls and create functions to map your K-Mix to anything in Bitwig.

After doing some cleaning up like commenting out any ‘println’ functions, and adding an exit() function, you’ve successfully implemented MCU control for your K-Mix in Bitwig! If you’d rather used a pre made solution you can find it here.