MIDI Lab





MIDI Lab now has LUA and ExprTk support for scripting.
ExprTk scripts can be written with 4 blocks: Expression (for value events), MIDI Expression, Script (for value 
events) and MIDI Script blocks (Python\JavaScript may also be added in the future). Below is the ExprTk 
must-know guide, while the LUA API reference is available from within MIDI Lab (in the LUA Script menu).

All 4 types of ExprTk scripting blocks are executed on every received MIDI message (appearing on its 'In' port).
There are loops, conditional expressions, functions, variables etc. + some extra MIDI-specific stuff available.

Functions:
All standard ExprTk functions and constants +
bin(string): binary to int (only MIDI Script)
hexStrToValue(string) or hex(string): hex to int (only MIDI Script)
type(int): retrieves MIDI type (int) from status (only MIDI Script)
channel(int) or ch(int): retrieves MIDI channel (int) from status (only MIDI Script)
valueToStr(double) or toStr(double) - converts a number to a string
strToValue(string) or fromStr(string) - tried converting a string to a number
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 Script/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 Script and MIDI Script blocks):
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 local vectors having size of 128 each (can store numbers only)
gvec1..gvec1024 - 1024 global (available and shared between all scripting blocks and read/write variable blocks) vectors having size of 1024 each (can store numbers only)

Expression/MIDI Expression blocks 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;
}