Post by nic on May 3, 2019 18:48:54 GMT
In any programming language you need to perform calculations, make decisions and do something multiple times. This article will detail the logic, maths and looping rule types.
Calculating
The MATH rule takes two values, performs a mathematical operation on them and then assigns the result to a destination variable array element:
math I0 = I0 + 1 # add 1 to I0
math P0 = I0 * I1 # multiply I0 and I1 and put result in P0
math I0 = M1 % 2 # take mod 2 of second MIDI message byte and put result into I0
math LI0 = %100 / $10 # you can use indirect variables too
The integer operators are +, -, *, /, and % and bit operators are |, & and ^
Note the keyword CALC can be used in place of MATH if you like.
Making Decisions
Where would we be without being able to make decisions? I don't know.
The IF/ELSE rule is used to branch logic depending upon whether a specified condition is true (or not):
if <literal/variable> <comparison operator> <literal/variable> [<literal/variable> ... ]
# code here if condition is true
else
# code here if condition is false
end
Comparison operators are: ==, !=, <, <=, > or >=
If the left hand side of the comparison operator is an array variable, then you can specify up to 4 values on the right hand side which will be compared in turn against the array starting from the element on the left side. See below for an example of this.
To specify AND conditions you simply nest the if statements:
if MT == B0
if I0 == 1
# code here if both conditions are true
end
end
OR logic is done using multiple parallel ifs. To prevent code duplication for each of the ifs you can either use a subroutine or set a flag in each OR condition like so:
assign L0 = 0 # OR flag
if MT == B0
assign L0 = 1
end
if I0 == 1
assign L0 = 1
end
if L0 == 1
# OR was true
else
# OR was false
end
As it happens, ORs tend to be less common in MIDI processing than one would think.
Recall where we said it was handy for variable arrays to be numbered sequentially? Well, the if (and while for that matter) condition allows the specification of more than 1 value on the right hand side of the comparison operator if the left hand value is an array element, so instead having to do:
if M0 == B0
if M1 == 50
if M2 == 7F
end
end
end
we can instead just say:
if M0 == B0 50 7F
end
You will see this all the time in StreamByter code - it's a very handy way of comparing multiple items against an array in one fell swoop.
Looping
Loops are really just if conditionals that just keep on going while the condition is true, so to specify a loop you write:
if <condition> +loop
end
or:
while <condition>
end
Practically, though, you will generally want some sort of loop counter to do something different each time. Here is a real-life example of copying all the data from a sysex message into the I variable array:
assign L0 = 0
while L0 < ML
assign IL0 = ML0
math L0 = L0 + 1
end
To prevent infinite loops and hanging hosts, a loop will only ever iterate a maximum of 128 times. A side effect of this is that if you wish to do something exactly 128 times, you can just make the condition always tru and let StreamByter finish the loop at 128:
while 1 == 1 # always true
# this code will be run exactly 128 times
end
Calculating
The MATH rule takes two values, performs a mathematical operation on them and then assigns the result to a destination variable array element:
math I0 = I0 + 1 # add 1 to I0
math P0 = I0 * I1 # multiply I0 and I1 and put result in P0
math I0 = M1 % 2 # take mod 2 of second MIDI message byte and put result into I0
math LI0 = %100 / $10 # you can use indirect variables too
The integer operators are +, -, *, /, and % and bit operators are |, & and ^
Note the keyword CALC can be used in place of MATH if you like.
Making Decisions
Where would we be without being able to make decisions? I don't know.
The IF/ELSE rule is used to branch logic depending upon whether a specified condition is true (or not):
if <literal/variable> <comparison operator> <literal/variable> [<literal/variable> ... ]
# code here if condition is true
else
# code here if condition is false
end
Comparison operators are: ==, !=, <, <=, > or >=
If the left hand side of the comparison operator is an array variable, then you can specify up to 4 values on the right hand side which will be compared in turn against the array starting from the element on the left side. See below for an example of this.
To specify AND conditions you simply nest the if statements:
if MT == B0
if I0 == 1
# code here if both conditions are true
end
end
OR logic is done using multiple parallel ifs. To prevent code duplication for each of the ifs you can either use a subroutine or set a flag in each OR condition like so:
assign L0 = 0 # OR flag
if MT == B0
assign L0 = 1
end
if I0 == 1
assign L0 = 1
end
if L0 == 1
# OR was true
else
# OR was false
end
As it happens, ORs tend to be less common in MIDI processing than one would think.
Recall where we said it was handy for variable arrays to be numbered sequentially? Well, the if (and while for that matter) condition allows the specification of more than 1 value on the right hand side of the comparison operator if the left hand value is an array element, so instead having to do:
if M0 == B0
if M1 == 50
if M2 == 7F
end
end
end
we can instead just say:
if M0 == B0 50 7F
end
You will see this all the time in StreamByter code - it's a very handy way of comparing multiple items against an array in one fell swoop.
Looping
Loops are really just if conditionals that just keep on going while the condition is true, so to specify a loop you write:
if <condition> +loop
end
or:
while <condition>
end
Practically, though, you will generally want some sort of loop counter to do something different each time. Here is a real-life example of copying all the data from a sysex message into the I variable array:
assign L0 = 0
while L0 < ML
assign IL0 = ML0
math L0 = L0 + 1
end
To prevent infinite loops and hanging hosts, a loop will only ever iterate a maximum of 128 times. A side effect of this is that if you wish to do something exactly 128 times, you can just make the condition always tru and let StreamByter finish the loop at 128:
while 1 == 1 # always true
# this code will be run exactly 128 times
end