The 'Stream Byter' module is a powerful tool for transforming MIDI
events passing through a port. By entering transformation rules in a
text based script style language, it is possible to rewrite, clone or block
any incoming message. The Stream Byter allows you to do such things as:
- Split your keyboard into as many zones as you like
- Create overlapping keyboard splits
- Finer detail event blocking (eg. block just active sense)
- Convert note presses to program changes
- Split controllers over channels
- Control many controllers with just one controller
- ... and loads more
With power, unfortunately, comes complexity and to program the Stream Byter
requires familiarity with the MIDI protocol at a byte level. This guide will
attempt to explain in detail how rules are constructed and also provide
some recipes for some of these 'interesting' transformations.
If you are not ready to write your own rules, then fear not, as we can
write rules for you which can be copied from an email and pasted into the
Stream Byter. If there is something you are trying to do, why not post your
requirements to our soapbox forum and
we or other MidiBridge users will try and construct suitable rules for you
to configure your copy of MidiBridge with.
Let's begin. Here is the Stream Byter configuration page:
An editable text area is where you paste/edit your rules for events
passing through the port on which it is configured. You get to this page by
touching the 'beaker' button on the port where you want the transformations
to occur.
To help you remember what the rules do, it is possible to comment the
rulesets. You simply add a '#' symbol before any commentary. You can comment
on a new line or after a rule:
# this comment is on its own
C0 = C1 # map program changes
|
Rules will be detailed in a moment, but when you want to install or test
your rules, you press the 'Install Rules' button. If any of your rules are
not valid, then you will see something like:
You'll notice the rule in error has been commented out and prefixed
with 'ERR'. To fix a rule, correct it and press 'Install Rules' again.
If a rule was marked with '#ERR' and you correct it, there is no need to remove
the '#ERR' part yourself, as the rule checker knows this is a correction and
will remove the '#ERR' for you before checking the rule again.
If all your rules are valid, then the edit area text will appear in blue
and the rules are now active. Do remember to save your rules into a preset
so that you can recall your ruleset on other ports too.
That is how you enter rules, now lets look at how to create them.
Rules must be of the format:
On the left of the equal sign is where you specify what to look for
on an incoming message in order to apply the transformation to the message
as specified in the output clause. Essentially, if an incoming message
matches the input clause, then the output clause is applied to it.
The Stream Byter evaluates each rule in order from top to bottom
and the current message (which could have been modified by a prior
rule) is used to match against the input clause. Here is a simple (but
fairly silly) example which maps all events coming in on channel 1 to
channel 3 having mapped to channel 2 in the process:
# map all events on channel 1 to channel 3
X0 = X1 # map channel 1 to channel 2
X1 = X2 # map channel 2 to channel 3
# of course the above is the same as X0 = X2
|
The exception to this evaluation order is when rules have optional
flags set, but we will look at that later.
The input clause is made up of 1, 2 or 3 hex bytes that correspond
to a MIDI message. The more bytes in the clause, the more finer the
matching. Here are some single byte input clauses (these are not valid rules
as they do not have and equal sign or output clause!)
# one byte input clause examples
B0 # matches all controller events on channel 1
FE # matches active sense messages
BX # matches all controller events on any channel (X = wildcard)
N0 # matches all note on/off events on channel 1 (N = note on/off)
8-9X # matches all note on/off events on all channels (8-9 is range, same as N)
B-C0 # matches all controller AND program change messages on channel 1
B0-3 # matches all controller events on channels 1,2,3 and 4
XX # matches all events on all channels
|
The above examples have introduced wildcards and ranges which can be used
to fine tune the event matching:
- An 'X' denotes any value
- An 'N' denotes note on and note off events
- You can specify a range using the minus sign surrounded by the low and
high values, eg 4-6 means values 4 through 6 inclusive.
The second byte in the input clause relates to the second byte of the
MIDI message. It can be a fixed value, wildcard or range. Here are some
examples:
# two byte input clause examples
C0 00 # program change zero on channel 1
C1 XX # all program changes on channel 2 (same as just C1)
N0 00-40 # note events on channel 1 from note number 0 to 64
|
Finally, adding a third byte to the input clause (fixed, wildcard or
range) increases the matching granularity. Some examples:
# three byte input clause examples
B0 07 00 # controller 7, channel 1, value 0
90 00-40 41-7F # notes on on channel 1, note number 0-64, velocity 65 to 127
|
The output clause is what determines what happens when an event
is matched by the input clause. Here you specify what values will be
written into the message. The output clause can be 1,2 or 3 bytes and
the 'X' wildcard character is used to denote that the original value
is to be preserved. Here are examples of 1,2 and 3 byte output clauses:
B0 # change event to a controller message on channel 1
BX # change event to a controller message, leaving channel alone
X0 40 # force all matching events on channel 1 to middle C
90 XX 7F # maximise the velocity on all notes on on channel 1
|
Finally, flags can be specified at the end of each rule. The
available flags are:
- +C - clone the message before rewriting. This creates a new copy of
the message and applies the output clause to it and schedules it for
routing after the original event. The original event is left untouched.
Note that the cloned message is passed through all the modules
that the original message passes through. In order to prevent infinite
loops, the Stream Byter will skip any rule that has the +C flag set
when processing a cloned message.
- +B - block the message. The message is immediately blocked and
the message is not routed nor passed through any further Stream Byter rules
or other modules.
Let's put all of the above together and create some real-world example
rules that will hopefully put things into prespective:
Remap all events on channel 1 to channel 2
X0 = X1 # remap channel 1 to 2
|
Duplicate all events on channel 1 to channel 2
X0 = X1 +C # duplicate channel 1 to 2
|
Block all active sense messages:
FE = XX +B # block active sense
|
Split the keyboard on channel 1 into 4 zones going to channels 1-4
N0 20-40 = X1
N0 41-60 = X2
N0 61-7F = X3
|
Overlapping split, 2 octaves around middle C to channels 1 & 2
N0 30-47 = X1 +C
N0 48-7F = X1
|
Mirror channel volume changes on channel 1 to channels 2,3 and 4
B0 07 = B1 +C
B0 07 = B2 +C
B0 07 = B3 +C
|
Hopefully, this will get you going with the Stream Byter module.
We have produced a short video showing how to setup an overlapping
keyboard split and controlling the volumes of channels separately and
conjoined on our youtube channel
If you are having any issues with the Stream Byter, do
please
contact us
or use our
soapbox forum.
|