Skip to content

MML Reference

Damián Silvani edited this page Aug 17, 2018 · 4 revisions

Instruments

An Instrument is a named collection of parameters, and can be declared like this:

bass {
  v: [7 8 7'2 6'2 5:0],
  pw: [0x80 | 0x40],
}

Parameters

Usually parameter values are Integers or Sequences, unless otherwise stated (like in adsr).

Sequence

A Sequence is an ordered list of Integers or Range of Integers, each element separated by whitespace

[ 1 2 3 4 5 6 ]

A Range of Integers is made up of two Integers joined by :

An optional step can be added (also with :), by default is 1 or -1 depending if the first number is greater or lesser than the second number.

Last number is included in range (e.g [1:5 10] => [1 2 3 4 5 10])

[0:10 11:4 3 1]
; == [0 1 2 3 4 5 6 7 8 9 10 11 10 9 8 7 6 5 4 3 1]

There's an optional loop point marker |

For example, this will generate an infinite sequence like [10 9 3 2 1 3 2 1 ...

[10 9 | 3:0]

Sometimes you might have a sequence that contains different values that are repeated the same amount of times, but cannot be expressed as a Range. For example:

[ 11 11 11 11 8 8 8 8 10 10 10 10 7 7 7 7 ]

This can be simplified with the ' (single quote) operator:

[ 11'4 8'4 10'4 7'4 ]

Instrument extensions

You can declare instruments based on other instruments. All properties are merged in the declared order, overriding existing ones.

For example, this:

basicEnv { v: [1 2 3 4] }
bass2 bass, basicEnv, { pitch: [80:10] }

is the same as:

bass2 { volume: [1 2 3 4], pitch: [80:10] }

This allows one to reuse instruments and use modified versions of them when composing.

Instrument Parameters

Volume

v: <values>: Volume sequence

Specifies a volume sequence / envelope. <values> can be an Integer or a Sequence, and values have a valid range of 0-15 (0 being silence and 15 being the loudest / maximum level).

Pulse-Width Modulation (PWM)

pw: <values>: Pulse-width sequence

Specifies a pulse-width sequence. This only affects pulse wave channels, i.e channels A and B. <values> can be an Integer or a Sequence, and values have a valid range of 0-255.

Note and Pitch

np: <values>: Note sequence

TODO

This can be used to create arpeggios.

p: <values>: Pitch sequence

TODO

This can be used to create handcrafted vibrato effects.

ap: <values>: Absolute Pitch sequence

TODO

This is the same as p but using absolute values


Commands

With Commands you describe a sequence of notes and use instruments for some specific channels. In C64 there are 3 configurable channels that can be referred with A, B, and C. A command starts by declaring which channels will be affected, and a sequence of commands follows.

<channels> <commands>

Entering notes

<note><sharp/flat><len>,<q>
  • <note> is the musical note: (c, d, e, f, g, a or b)
  • <sharp/flat> specifies an accident (+ or -), it raises or lowers the note one semitone.
  • <len> (1 - 65536) is the length of the note. This number is the length of a measure divided by this number. For example, a c4 will play a quarter note C.
  • <q> (1 - 8) is the quantization length.

If no length is given, the length you specified with the l<len> command is assumed. Likewise, if no quantization length is given, length specified with q<len> command is used.

r<len>: Rests
  • <len> (1 - 65536) is the length of the note you'd like to rest. This number is the length of a measure divided by this number. For example, a c4 will play a quarter note C.

If no length is given, a the length you specified with the l<len> command is assumed.

Tempo and Note Length

t<num>: Tempo
  • <num> (1 - 255) The tempo of the channel (not the entire song)

You'll use this after a channel header to set its tempo. It won't set all channels simulataneously unless you type every channel letter you're using before this command.

By default, 120 bpm is used for all channels (ABC t120).

l<len>: Note Length
  • <len> (1 - 65536) The default note length for the channel you specify. Same rules as entering a note.

By default, quarter notes is used (ABC l4).

q<len>: Quantize Note
  • <len> (1 - 8) The default quantization note lenght for the channel you specify.

The quantize command makes part of the note silent, which can be useful for things like string sounds or drums.

Positive numbers will mute the last 8-num eights of the note. E.g. q8 would play every note unchanged, but q4 will play half the note length.

Negative numbers will mute the beginning of the note, while the latter part of the note is allowed to play. (not implemented yet)

With this, real note length is: n - (n/8) * (8-q)

Q<frames>: Quantize Note in Frames

Same as q<len> but in number of frames. Useful when you want to cutoff a note more precisely than the values given by q.

^: Note tie

Ties two of the same notes together, but you only need to tie lengths, note completely written out notes.

For example

; Two quarter notes combined = one half note
A c4^4

; This sounds the same
A c2

Octaves and More Notation

o<num>: Octave
  • <num> (0 - 7) Sets default octave for a channel.
>, <: Raise / Lower Octave

This will raise or lower the notes following one octave. You can use more than one in a row.

Example:

A b-16 a16 a8 > c8 < f+8 a8 g8 d4
K<num>: Transpose
  • <num> (-99 - 99)

Transposes the notes that follow <num> semitones relative to the notes entered.

Loops and Other Commands

[ ... ]<num> : Repeat Loop
  • <num> (1 - 256)

Will loop the notation inside the [ ] <num> times. By default <num> is 2.

p<num>: Pitch
  • <num> (-128 - 127)

Change pitch tone of the following sequence of notes. Useful for detuning or creating a chorus effect when used on another channel with a duplicate sequence of notes.

V<num>: Timbre / Pulse width
  • <num> (0 - 255)

Change timbre / pulse width of the following sequence of notes. Only affects pulse wave channels (A and B).

v<num>: Set Master Volume
  • <num> (0 - 15)

This will set the master volume to <num>. Note that there is only one global volume that affects all channels in the SID chip. To get different loudness levels for specific channels you should use ADSR envelopes and/or filters.

v+<num>, v-<num>: Increase / Decrease Master Volume
  • <num> (0 - 15) The number of levels you want to increase or decrease the volume by.

If volume is already 15, v+ does not do anything. Same happens with v- when the volume is already 0.

Using instruments

By using @var you apply all the instrument properties to the current state for the affected channels. An instrument named var must exist beforehand.

AB t120
A @bass cdefg

You can define a scope with parenthesis, ( and ), so that all state changes are reverted once you are out of it.

Here, @bass is set for a single note g, but then c4d8 uses @keys+@myPW, not @bass.

B @keys cdef (@bass g) (@myPW c4d8) (@bass cdef)

Another example: A C-major arpeggio that goes only up and extends to 3 octaves can be written as:

A l16 [[ceg>]3 <<<]2

As you can see, when reaching the 3rd octave, you have to go back to the first octave with <<<. But with scopes, state is reverted automatically.

A l16 [([ceg>]3)]2

This is particularly useful when used with multiple instruments and for channel stealing (using a single channel to play different voices/instruments).

You can apply an ad-hoc or anonymous instrument with the @{} syntax, like this:

A @keys cde (@{pw:70} l32 f>f>f) cde

This is the same as:

foo { pw: 70 }
A @keys cde (@foo l32 f>f>f) cde

but without having to name it. Try not to use this too much as it makes your song more difficult to work with!

Headers

#include <filename>

Include another MML document. <filename> is the path to that file, relative to the current file.

#title <string>

<string> is the title of your tune.

#author <string>

<string> is the name of the person who composed or arranged the tune.

#released <string>

<string> is the release date or copyright information.

The last 3 header directives set the Title, Author and Released fields in the final .SID file. For all of them, up to 32 characters is permitted.


Comments

3 styles of commenting are supported:

  • Block comments with /* and */
/**
 * this is a block comment
 */
  • Line comments with // or ;
// this is a line comment
; this is a line comment