Sys-ex Expressions are used to generate MIDI System-Exclusive messages (aka: "Sys-ex" messages) from a binding.
Sys-ex expressions can consist of a simple fixed series of data bytes or can be used to dynamically generate sys-ex messages based on the source value of a binding.
Accessing the Sys-ex Expression Editor
Sys-ex expressions are used in bindings where the target side of the binding is a MIDI Sys-ex. To enter the sys-ex data, create a binding where the Target is a MIDI port, the action is "Sys-ex" and then click in the second half of the action column:
A sys-ex expression consists of a series of individual expressions which are evaluated to generate the final sys-ex message. The following data types and syntaxes are supported:
A simple decimal value. eg:
A hex value prefixed by
An math expression evaluating to an integer value: (see below for a list of supported operators)
(10 + 20) * 2=> 60 decimal => 3C
Floating point math is also supported, but will be converted to integer value in the final sys-ex data:
0.5 * 10=> 05
Strings (which will be ascii encoded in the final byte stream)
"Hello"=> 48 65 6C 6C 6F
Arrays (which will be flattened to an array of bytes)
[ 1, 2, 3 ]=> 01 02 03
Sys-ex Patterns (a more convenient way to express a series of hex values). See here for more.
x"F7000000F0"=> F0 00 00 00 F0
SongTitle=> "Yellow Submarine" => 59 65 6C 6C 6F 77 20 53 75 62 6D 61 72 69 6E 65
substr(SongTitle, 0, 6)=> "Yellow" => 59 65 6C 6C 6F 77
Normally you don't need to include separators between each element in an sys-ex expression:
`0xF7 0x00 0x00 0x00 0xF0` => F7 00 00 00 F0
However you can use semicolons or commas if you prefer:
`0xF7,0x00,0x00,0x00,0xF0` => F7 00 00 00 F0
Or if necessary eg:
`0xF7 100 -20 30 0xF0` is interpreted as `0xF7 100-20 30 0xF0` => F7 50 1E F0
What you probably want is:
0xF7 100, -20 30 0xF0
0xF7 100 (-20) 30 0xF0
(That said negative numbers arean't really supported in sys-ex data like this so it's moot point)
The result of evaluating each element in the sys-ex expression must be one of the following types:
- A number between 0 and 255 (ie: a byte). Values outside this range are considered an error
- A string which will be ASCII encoded
- An array in which each element must be a number between 0 and 255, a string, or another array.
The final byte stream is constructed by flattening and concatenating the result of all expression elements.
You can use local variables to store intermediate values during the evaluation of the sys-ex expression.
eg: this takes the first 8 letters of the song name, wraps it in "--" delimiters, converts it to an ASCII encoded byte array and stores the byte array in a variable called "shortName".
var shortName = ascii("-- " + substr(SongTitle, 0, 8) + " --"); 0xF7 0x00 0x10 length(shortname) shortname 0x00 0xF0
and will generate sys-ex data similar to the following:
0000: F7 00 10 0E 2D 2D 20 59 65 6C 6C 6F 77 20 53 20 | ....-- Yellow S 0010: 2D 2D 00 F0 | --..
Note that the
0E byte is the length of the shortName byte array.
All of Cantabile's string expansion variables are available for use in a sys-ex expression however they should be used without the normal
$(...) delimiters. ie: use
The "VALUE" Variable
A special variable named
value represents the current source value of a binding.
eg: suppose you bound a MIDI CC event to a sys-ex expression you could do something like this:
0xF7 0x00 value 0xF0
value would be replaced with the current value of the MIDI controller.
Depending on the source of the binding, the value variable might take on different types.
- For MIDI source values the value is typically an integer value, 0-127 for controllers, 0-16383 for fine controllers etc...
- For audio gain based source values it's a gain multiplier where 1.0 = 0dB
- For string bindings (eg: Song name) it's a string (obviously)
- For key range data bindings it's a byte array (see below)
Key Range Data Format
The "Engine - Key Range Data" binding sends a byte array for the value variable. The byte array contains three bytes for each key range currently visible on the on-screen keyboard, as follows:
- byte 0 = the color of the key range where 0 = default, 1 = red, 2 = maroon, 3 = green etc.. (see Cantabile's color menus for the rest of the colors)
- byte 1 = the note number of the lowest note in the key range
- byte 2 = the note number of the highest note in the key range
For example, consider the following byte array value:
01 00 32 03 35 66
This represents two visible key ranges:
01 00 32= color 1, key range 0x00 (decimal 0) (C-2) to 0x32 (decimal 50) (D2)
03 35 66= color 3, key range 0x35 (decimal 53) (F2) to 0x66 (decimal 102) (F#6)
See the Function Reference, or the popup menu in the expression editor for commonly used functions:
If an error is encountered while editing the sys-ex expression it will be shown in the editor output preview area.
If an error is encountered when attempting to send the sys-ex message, a suitable message will be written to Cantabile's debug log and the sys-ex message won't be sent. You can check the debug log by either:
- In Tools -> Open Settings Folder -> look for the file log.txt
- In Options -> Diagnostics, turn on Console Logger to see the error messages as they happen
The expression engine supports the following operators:
- Subtract and negative
- Ternary (aka conditional) operator
- Conditional Not
- Conditional And
- Conditional Or
- Bitwise Not
- Bitwise Or
- Bitwise And
- Bitwise Xor
- Bit-Shift Left
- Bit-Shift Right