Writing efficient mScore.js scores
Musical scores often contain some sort of repeating patterns. Usually there will be rhythmical patterns which occur many times, or patterns of formatting. To save on writing source code and also make the source code more readable, mScore.js offers two methods: Rhythm patterns and macros.
Writing the note values of a piece can be cumbersome if almost every note has a different value from the one preceding it. But it will often be the case that a musical piece contains a small number of rhythmical patterns which make up most or all of its content. In that case you can store these patterns once in rhythm pattern(s), then just set a pattern like a note value, whereupon the following notes’s values follow that pattern. Let’s look at an example:
Instead of notes and rests, a rhythm pattern definition contains (reciprocal) note values. These can also be dotted, but unlike with voice content the following note is not automatically made shorter, you have to put in the appropriate value. Note values can also be connected by beams; if you don’t, the notes using the pattern in a voice content element can still have a beam added there, and it is often advisable to put those beams there anyway to improve code readability. Rhythm patterns contain no bar lines, and when used can cross over bar boundaries.
A tuplet is applied once, then the voice continues with regular note values. If you have many tuplets of the same type following each other, you might want to use a persistent tuplet switch (tssplit: resp. tslength/split:). This will produce tuplets of that type until it is stopped by starting a rhythm pattern or by t0:. Tuplets cannot contain rhythm patterns, but you can use (non-repeating) tuplets within rhythm patterns. In this case use the syntax tpbaseBeat/split: resp. tpbaseBeat/length/split:.
Tuplets cannot contain rhythm patterns, but you can use (non-repeating) tuplets within rhythm patterns. In this case use the syntax tpbaseBeat/split: resp. tpbaseBeat/length/split:.
A macro is inserted (called) in a voice content element or in another macro by writing mname [argument 1,...,argument n], i.e. “m” immediately followed by the macro’s name, then (after optional space) the arguments (data) passed to the macro in square brackets, separated by commas if there are several. If a macro uses no arguments (i.e. is just a piece of content which is inserted as it is) the empty square bracket can be ommitted. Note that unlike mScore.js’s various switch commands macro calls do not end with a colon.
Macro calls can appear anywhere, in voice content, in macro definitions, inside arguments passed to other macros. Note that if you call a macro inside its own definition (directly or indirectly) the result will be an infinite loop. It is your own responsibility not to do that.
The content of a macro definition contains the same sort of material as regular voice content, except for one additional type of command, arg1/, arg2/ etc., which mark places where the respective arguments are inserted when the macro is called.
Example Macro1 contains a macro named “xy” with one argument. As this page explains, a macro’s name is given as an attributes of the macro definition element, and if you specify no name they just get consecutive numbers starting with 1 — see example Macro2.
The number of arguments a macro has can also be given as an attribute args; if you omit it the number of arguments is counted from the highest <argn/> which appears in the macro definition. mScore.js allows any number of macro arguments, although using a large number is very strange.