MIDI Lab





MIDI Lab uses ExprTk for scripting
with both MIDI Expression and MIDI Script blocks (Python or LUA is on the todo list but
won't appear in days - I would say it will come within months) - so you have loops,
conditional expressions, functions, variables etc. + some extra MIDI-specific stuff.
MIDI Script is basically executed on every received MIDI message (appearing on its 'In' port).

Functions:
All Exprtk functions and constants +
bin(string): binary to int (only MIDI Script)
hex(string): hex to int (only MIDI Script)
type(int): retrieves MIDI type (int) from status (only MIDI Script)
ch(int): retrieves MIDI channel (int) from status (only MIDI Script)
rnd: generates random int (both MIDI Script and MIDI Expression)
bitwise functions:
bitwise_and
bitwise_or
bitwise_not
bitwise_xor
bitwise_shiftl
bitwise_shiftr

send (only MIDI Script): a versatile function for sending MIDI messages from within the script.
You can call is in variety of ways (depending on the type of message that you want to send):
- send(status)
- send(status, data1)
- send(status, data1, data2)
- send(vector,numBytes)
(status/data1/data2 can be either integers of hex strings (ie. '0x90')).
The last syntax send(vector,numBytes) is useful for SysEx etc.


Available variables (only MIDI Script):
status, data1, data2 - represent first 3 bytes of received MIDI message
raw - it's a vector holding all bytes received (so it's especially helpful when working with SysEx) -
number of bytes received is stored in the rawSize variable (max size of 1024*1024)
time - ms from startup time (double - high resolution)
bpm, bar, beat - self-explanatory variables

Static variables (keep values between calls to the script):
a,b,c,x,y,z,i,j,k (of double/real datatype)
str - to store text values for debugging etc.
vec1..vec10 - 10 vectors having size of 128 each (can store numbers only)

MIDI Expression can use only the a,b,c,x,y,z variables.

Exprtk syntax, statements, functions, packages (even files I/O operations!) and constants apply

*** Examples *** (more advanced sample script attached)

// ******************************
// MIDI Amplifier
// Doubles MIDI notes velocity
// ******************************

if(type(status) == hex('0x90')) { // process only note on msgs
     send(status,data1,min(data2*2,127));
}
else
    send(status,data1,data2); // for other msgs just pass them through


// ***********************************
// Monophonic MIDI Notes Randomizer
// ***********************************

var v[8]:={0,2,3,5,7,8,10,12};

if(type(status) == hex('0x90')) {
     a:=rnd()%8; send(status,v[a]+48,data2);
}
else if(type(status) == hex('0x80')) {
     send(status,v[a]+48,0);
};


// ******************************
// MIDI Sequencer
// ******************************

var minor[8]:={0,2,3,5,7,8,10,12};
var major[8]:={0,2,4,5,7,9,11,12};
if(status == hex('0xF8')) { // execute on every MIDI beat clock received
     send(hex('0x80'),major[i]+32,0);
i:=(i+1)%8;
     send(hex('0x90'),major[i]+32,rnd()%64);
    
    
// ******************************
// File operations
// ******************************
    
var file_name    := 'data.txt';
var stream         := null;

if (stream := open(file_name,'w'))
    println('Successfully opened file: ' + file_name);
else
{
    println('Failed to open file: ' + file_name);
    return;
}

var s := 'Hello world...\n';
for (var i := 0; i < 10; i += 1)
{
    write(stream,s);
}
    
    
// ******************************
// Transform MIDI
// ******************************
    
if(type(status) == hex('0xD0')) // Channel Pressure
{
    if(data1 > a)
    {
        a := data1;
        send(status,data1);
    }
}
else if(type(status) == hex('0x80')) // Note Off
{
    for(var ii:=a;ii>=0;ii -= 1)
    {
        send(hex('0xD0'),ii);
    };
    a := 0;
}