Minc
default scorefile parsing/interface language for RTcmix
Minc is the default 'interface' for RTcmix, invoking the command
CMIX < some_score.file
will use Minc to parse the score and make the appropriate function
calls to run RTcmix. There are other options, including the ability
to run RTcmix from
perl,
python,
embedded
within another application, or through a
TCP/IP socket.
Minc is also used to parse buffer-scripts in the Max/MSP
rtcmix~
object and in the
iRTcmix
package for iOS devices.
Minc takes most of its functionality from the "C" programming
language, including
flow-of-control features such as for and while
loops, if decision-constructs, etc. See the
RTcmix tutorial
(especially the later sections about algorithmic composition)
for examples of Minc use. The biggest differences between
Minc and "C" is the lack of pre- and post-fix operators in
Minc (i.e. "i++" or "--counter") and the absence of semicolons
as line/statement terminators (note: semicolons are still required in
"for(...)" statements). Semicolons may be used at the end of
Minc lines, but they are not required (they are simply ignored).
Some other useful features of Minc:
- Combination assignment operators are supported. This means that
expressions such as:
for (i = 0; i < 7; i += 2) { ...
and
while (asympt > 0.001) { asympt *= 0.5; ...}
will be parsed correctly.
- The Minc array facility is very useful.
The following are acceptable Minc constructions:
a = { 1, 2, 3, 4, 5 }
INSTRUMENT(a[3], a[0], ...)
b = {} // note that "b" is dimensioned by use
for (i = 0; i < 10; i += 1)
b[i] = i * 3
Minc arrays can also contain 'mixed' data types:
afloat = 1.2345
astring = "hey hey!"
b = { 123, afloat, "ho ho", astring }
Arrays can also contain
pfield-handle
handles for tables, etc.:
e = {}
x = 1
for (i = 0; i < 10; i += 1) {
e[i] = maketable("random", 1000, "linear", min=x, max=x*2, seed=x*3)
x *= 2
}
Arrays can be passed into
maketable
consructions:
d = { 0,0, 1,1, 3,1, 5.5,0 }
env = maketable("line", 1000, d)
Array elements may also include other arrays. However, to access
the sub-arrays, a 'temp' array variable is necessary:
arr1 = { 1, 2, 3, 4, 5, 6, 7 }
arr2 = { 77, 87, 97, 107 }
superarr = { arr1, arr2 }
temparr = superarr[0]
for (i = 0; i < len(arr1); i += 1) {
print(temparr[i])
}
'temparr' in the above code temporarily represents the 'arr1' array.
Note that arrays of different lengths may be stored in a 'super' array.
The len
built-in function is used to determine the length of an array
(as well as lengths of other Minc data-types).
Arrays can be concatenated using the '+' operator:
first = { 1, 2, 3 }
second = { 4, 5, 6 }
third = first + second
print(third)
[1, 2, 3, 4, 5, 6]
All the elements of an array can be modified via operators +, -, *, and / followed a float variable:
arr = { 1, 2, 3 }
arr = arr + 10
print(arr)
[11, 12, 13]
arr = arr * 100
print(arr)
[1100, 1200, 1300]
- Minc allows you to define and use custom data types which are very much like the "struct" concept in the C and C++ languages. In Minc, a struct type must be named as part of its definition:
struct MyData { ... }
What goes between the curly braces is called a member list, and it consists of a comma-separated list of variable declarations:
struct MyData { string name, float number, list array }
These variables can be any of the normal built-in Minc types, and there is no limit on the number of member variables. Their names must all be unique within the struct definition. For now, structs cannot be nested within each other.
To declare a variable in your score to be a struct, just use the struct type as follows:
struct MyData instrumentData
To assign and read from the members, use the "dot" syntax:
instrumentData.name = "Loud Instrument"
instrumentData.number = 1
instrumentData.array = {}
printf("Instrument %s: %f\n", instrumentData.name, instrumentData.number)
All struct member variables are set to 0 or NULL by default.
You cannot auto-declare struct variables unless you are assigning from one to another:
OK:
struct MyData someData;
// initialize members of someData...
copyOfMyData = someData // These two now point at the same struct object
NOT OK:
autoStructData.name = "something" // cannot auto-declare 'autoStructData'
Struct variables may be used as arguments and return types for custom functions. This is a very convenient way to get lots of different variables into your function calls without having to create long lists of arguments.
- Comments may be included in Minc scripts using "C"
comment syntax:
/* a comment may be between two slash-asterisk markers */
/* and it
may also span several lines
*/
// anything after two backslashes on a line will be construed as a comment
- Actions are performed by Minc functions or
operators ("+", "-", "*", "/", "^", etc.). Functions may be
Instruments or built-in functions used to perform scorefile calculations.
Return values are assigned to Minc variables with the "="
assignment operator:
aval = somecalculation(anotherval, something_else)
thisone = thatone + those
ANINSTRUMENT(with, many, different, parameters)
In addition, operations and functions may be embedded (or 'nested'):
INSTRUMENT(somefunction(var1, var2), val^3.2, aval, 3.1654, func1(func2(array[3])))
- Several "C" conditional-branching
statements are included in Minc ("if-then-else", "while").
The standard "C" comparison operators ("==", "&&", "||", "!=", ">",
"<", etc.) are used for the conditional comparison. Using parantheses
to group and determine precedence of evaluation is also supported:
if ((val > 2.0) && < (val2 != 0)) { ... }
Note that the "do-until" and "switch" statements are not supported in Minc.
- Minc supports the ability to create custom functions right in your score.
The format for these functions is nearly identical to that used to define functions
in the C programming language:
return_type function_name(arg0_type arg0_name, arg1_type arg1_name, ..., argN_type, argN_name)
{
<function body>
}
Rules:
- The return_type and the argument types must be either float, string, handle (the type for tables, etc.), or list (the type for MinC arrays).
- The function can have any number of arguments, including zero.
- It must return a value of one type or another. Use a dummy zero if nothing else. The type of the variable returned must match .
- Use the 'return' keyword to mark the place where the value should be returned. There can be more than one such place (e.g. inside if() blocks).
- The arguments passed to the function must match the declared types (i.e., no type conversion supported).
- If the score provides fewer arguments that the function expects, the remainder will be set to 0 (or NULL). This is legal but you will get a friendly warning.
- There can only be one function defined with any given function name.
- Functions can call other functions, including themselves (recursively).
- A function must be defined before (i.e., above) the place where it is first used (except when it is calling itself).
- Functions can be defined in a separate file which is "include"d by a score. This makes it easy to create and re-use function "libraries"!
- The body of a function may contain any legal Minc score commands.
- Variable visibility rules. These are a bit complicated.
- Any variable declared globally in the main score (outside of any function) is visible inside the body of all functions.
- This is true even if that global variable is declared after the function is declared in the score, as long as it is declared before the function is called.
- Any variable declared inside a function is not visible outside of the function.
- All Minc numerical values are floating-point, although
care is taken to prevent round-off errors from causing problems
for counting variables that would normally use integers. The
trunc
and
round
built-in functions can be used to guarantee a correct 'integer'
value.
- Minc can also handle character-strings and the
pfield-handle
variables (obviously!), including operations performed
on those types. The
stringify
function can be used to coerce a Minc string into a
floating-point value that RTcmix instruments may use internally.
- The
index
and the
type
commands are also very useful with Minc variables and
arrays. The
type
command can determine the Minc data-type of a particular
variable, and the
index
can retrieve items at a particular index within an array. Also
be awafe that
Minc lists will also be 'unpacked' properly
in many scorefile commands, such as the
print
and
maketable("literal"...)
commands.
a = { 1, 2, 3, 4, 5, 6 }
print(a) // print can handle arrays
foo = "foo"; bar = "bar"
afloat = 1.2345; astring = "blah"
b = { 123, afloat, "blabber", astring, a, foo + bar } // an array can embed other arrays
// also note the string concat with '+' operator
numitems = len(b) // get length of array
printf("array b: %d items: %l\n", numitems, b) // printf for ints and lists (i.e., arrays)
printf("afloat=%f, astring=%s\n", afloat, astring) // printf for floats and strings
idx = index(b, 345) // Return a zero-based index into array (arg 1) of item (arg 2)
print(idx)
- The
include
command can be used to embed one (or more) Minc scorefiles within
another.
- When Minc encounters a parsing error, it generally exits
(RTcmix) or returns a FATAL_ERROR value (embedded apps like
rtcmix~
or
iRTcmix)
with an attempt to identify the number of the line with the syntax
error. Line numbers are cumulative, however, so for embedded apps
the reported line may be radically different from the line in the
sent scorefile.
- The original Minc parser was coded by Lars Graf. Additional
modifications were made by John Gibson, Doug Scott and others.
The following is from the original cmix Minc documentation. Some
is a bit dated, but the basic concepts are still valid. For a more
complete and current grammar, see the RTcmix/src/parser/minc/minc.y file:
Minc (Minc is not c)
is the data specification language for
cmix. It was written by Lars Graf. Minc almost follows a
C-like syntax. Arithmetic, conditional and logical expressions are permitted, as well as looping. Any statment of
the form foo(val,num, etc) results in the execution of
foo() if it is a cmix procedure and declared as such, either
in the user's profile.c or in cmix's ug_intro.c. If it is
neither the evaluated terms within parentheses will simply
be printed and returned. The arguments within the
parentheses are passed to the cmix procedure in its float *p
array. All variables must be declared as float. The sign ;
has the meaning 'clear out any syntax errors'. cmix routines
such as open, input, output which have a file name as a
first argument, must pass that argument between " signs.
Minc, has two modes of operation: batch and interactive (the
default). The only difference between them is that loops
cannot be executed in interactive mode. To run in batch
mode a -b flag must be specified on the Cmix command line,
and all data must be entered either by redirecting input
from a file, or by typing all data followed by a <cntrl-D>.
Comments are inclosed by /* and */ as in C. Any user function which returns a value can return that value to Minc if
it is declared as a type double and introduced in the
profile.c file.
The following is Lars Graf's formal statement of the
language:
Order of precedents:
||
&&
= !=
< > <= >=
+ -
* /
** ^
CASTS
Syntax:
prg: stml
stml : stmt
| stml stmt
| stmt ;
| stml stmt ;
stmt: float idl /* declare ids */
| id = exp
| IF bexp stmt
| IF bexp stmt ELSE stmt
| WHILE bexp stmt
| FOR ( stmt , bexp , stmt ) stmt
| id ( expl ) /* a call to a cmix function */
| { stml }
idl: id /* like: fnct_name(arg1,arg2,arg3) */
| idl , id
id: any letter/digit/"_" combination, but start with letter
expl: exp
| exp ',' expl
| or no function argument
bexp: exp
| ! bexp
| bexp && bexp
| bexp || bexp
| bexp = bexp /* note the comparison of booleans */
| exp < exp
| exp > exp
| exp != exp
| exp <= exp
| exp >= exp
| TRUE
| FALSE
exp: exp ** exp
| - exp
| exp * exp
| exp / exp
| exp + exp
| exp - exp
| ( bexp )
| any number: e.g. 34 -645.34 234.E23 ...
Note:
1) Semicolon and are optional.
2) '=' is used for assignments and boolean expressions.
3) False = 0; True = 1(or nonzero).
Samples:
/* this is a legal comment */
float foo,x;
if i=3 && foo>4 say_mumble( foo**i , i-foo*3)
else mumble_foo()
while x=3 {
this_is_a_cmix_function_call()
x= 5 * (foo=i) /* this is slime */
while true nested_loops_are_possible()
}
for (x=1, x <= 10,x=x+1) dispatch(x)
Minc also has the following facilities:
1) function calls can return values
e.g. i = rand(j)
NOTE: those are calls to your own C-functions.
You may adjust your dispatcher and your functions accordingly
The function must be introduced in the profile, and must
be of type double.
2) assignment statements have the value of the assignment.
e.g. i = j = 5
while (i=j) == 5 { mumblings .. }
3) strings can be passed as arguments.
e.g. file_id = open("name of file",2)
printf("some string %f %f0,i,j)
/* of course, the dispatcher has to know about printf */
NOTE: the string pointer is passed as a double; to convert
back, you have to first cast it into an integer, and then
you have to cast the integer into a char*.
4) use '=' for assigment; and '==' as the booleam equal operator.
Here is a simple example file:
open("sf/bigsound",0,0)
open("sf/bigmix",1,2)
sfclean(1)
float a,b,c,d
a=2 b=3 c=28000 d=-4
sound(a,b,c,1,22*19,d=d-a)
sound(a=a+2, b+.1, 99, d=d-a+2)
|