an open-source digital signal processing and sound synthesis language
about · links · contact

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)