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; }