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