Chapter 19
Score expressions

Score expressions allows to defines score objects (gmn or pianoroll) by dynamically combine various resources using a formal expression. To define such object one should use the basic set messages using a score expressions as arguments:

EXAMPLE
The following example defines a gmn and a pianoroll object using score expressions, the meaning of the expression is explained further.

/ITL/scene/score set gmn expr(seq [a] [b]);
/ITL/scene/pianoroll set pianoroll expr(score);

19.1 General Syntax

A score expression always starts with expr( and ends with ), then 2 syntaxes are handled:

EvaluableExpression PICT

Each of these tokens can, of course, be separated by spaces, tabulations or carriage returns (allowing multiline expression definition).

When defining an object using a score expressions, INScore will parse it, construct an internal representation and finally evaluate it, reducing the formal expressions to a valid GMN string.

EXAMPLE
Creating a guido object by sequencing two guido string

/ITL/scene/score set gmn expr( seq "[c d e]" "[f g h]");

is equivalent to

/ITL/scene/score set gmn "[c d e f g h]";

19.2 Score Operators

All the score operators of INScore make use of guido operators implemented in the GuidoAR library.





operationargumentsdescription



seqs1 s2 puts the scores s1 and s2 in sequence
pars1 s2 puts the scores s1 and s2 in parallel
rpars1 s2 puts the scores s1 and s2 in parallel, right aligned
tops1 s2 takes the n first voices of s1 where n is s2 voices count
bottoms1 s2 cut the n first voices of s1 where n is s2 voices count
heads1 s2 takes the head of s1 up to s2 duration
evheads1 s2 takes the n first events of s1 where n is the event’s count of s2
tails1 s2 cut the beginning of s1 up to the duration of s2
evtails1 s2 cut the n first events of s1 where n is the event’s count of s2
transposes1 s2 transposes s1 so its first note of its first voice match s2 one
durations1 s2 stretches s1 to the duration of s2
if not used carefully, this operator can output impossible to display rhythm
pitchs1 s2 applies the pitches of s1 to s2 in a loop
rhythms1 s2 applies the rhythm of s1 to s2 in a loop




19.3 Score Arguments

The syntax for arguments is quite permissive and various resources can be used as arguments for score expressions. In any case, when evaluating the expression, all the arguments will be reduce to GMN string so they can then be processed by the operators.

Argument PICT

Arguments specification

Arguments prefix

EXAMPLE
Defining /ITL/scene/score as a copy of /ITL/scene/simpleScore duplicated 4 times.

/ITL/scene/simpleScore set gmn "[e {c,g} |]";

/ITL/scene/score set gmn expr( &simpleScore );
/ITL/scene/score set gmn expr( seq ~score ~score);
/ITL/scene/score set gmn expr( par ~score ~score);

/ITL/scene/score should look like:

PIC

Querying for the expanded expression of /ITL/scene/score (see Section 19.4) should return:

/ITL/scene/score expr  
  expr( par  
       ( seq  
          &simpleScore  
          &simpleScore  
       )  
       ( seq  
          &simpleScore  
          &simpleScore  
       )  
  )

NOTE ON ARGUMENTS QUOTING
Arguments using special characters (space, tabulation, parenthesis, braces...), should be simple or double quoted, otherwise quotes can be omitted.

19.4 expr commands

ITLObject defined using an evaluable expression gain access to these specific commands:

Applied to an object which wasn’t defined by an evaluable expression, all this commands will cause a bad argument error.

The renew command reset the internal state of the evaluated variable, forcing the re-evaluation and update of every arguments in the expression. Be aware that the track of copy evaluated arguments is lost after the first evaluation, thus renewing an expression defined using copy evaluated arguments won’t update these arguments to their targeted ITLObject expression. Though, static arguments added by the copy shall be renewed.

19.5 newData event

newData is triggered by any object when its value change (generally because of a set message). Neither trying to set an object to its actual value without changing its type, nor re-evaluating an object to its actual value will trigger newData.

Of course, the newData event can be used together with reeval to automatically update an object when the value of an other changes.

EXAMPLE
Creating a copy of score, and automatise its update when score is changed

/ITL/scene/score set gmn "[c e]";
/ITL/scene/copy set gmn expr(&score);
/ITL/scene/score watch newData (/ITL/scene/copy expr reeval);

To avoid infinite loop when using recursion, newData event is delayed of one event loop, meaning that, in the previous example, during the event loop that follow score’s modification, score and copy are different (copy has not been updated yet...).

NOTE
Because newData event is delayed, if score experiences multiple modifications during the same event loop (because multiple set messages have been sent together), only his final value will be accessible when newData will be actually triggered, however the event will be sent as many times as score have been modified.

NOTE WHEN AUTOMATISING UPDATE
For the reasons raised in the previous note, one should be very careful to delayed update when automatise reeval with newData. Indeed, in some extreme case, executing a script one line after an other won’t have the same result as executing the all script at once!!

EXAMPLE
Creating a "score buffer", storing every state adopted by score

/ITL/scene/score set gmn "[c]";

/ITL/scene/buffer set gmn "[]";
/ITL/scene/buffer set gmn expr(seq &buffer (seq "[|]" &score));
/ITL/scene/score watch newData (/ITL/scene/buffer expr reeval);

/ITL/scene/score set gmn "[e]";
/ITL/scene/score set gmn "[g]";
/ITL/scene/score set gmn "[{c,e,g}]";

Won’t have the same result if run line by line, or the all script as once:

Line by line:

PIC

All script at once:

PIC

To avoid such undeterministic behaviour, one should, in this case, manually trigger reeval after each modification of score.