MML File Structure
The overall structure of a .mml file describing one song's sequence data,
and the parameters for each of its sections. For the performance commands themselves (notes, rests,
note notation, etc.), see the MML Command Reference.
Overall file structure
- A plain text file in go-fmml's own format, with the extension
.mml. - Comment lines start with
#(leading whitespace is ignored). Blank or whitespace-only lines are also ignored. - The very first line must be the header string:
[GoFMML File] - Followed by the
[global],[conductor],[partSetting],[pcmPartSetting]sections and each part's own body ([part1]-[part16],[pcmPartA]-[pcmPartP]). - Load with one of
fileio.LoadMMLFile/LoadMMLFileFS/SetMMLTextData.
[global] — song-wide initial settings
Written in YAML format.
[global]
tempo: 120
sequenceID: SampleMML
loop: false
volume: 100
startOffset: 1
reverb: false
reverbType: normal
reverbTime: 1.5
reverbLevel: 50
| Key | Range / format | Description |
|---|---|---|
tempo | numeric (BPM) | The song's tempo. If [conductor]
also specifies a tempo, that one takes priority. |
sequenceID | string | Uniquely identifies this sequence - the key
passed to player.Play and similar. |
loop | true / false | Whether reaching the song's end loops back to
the start (or the startOffset position / a jump point). The longest of all parts is
treated as the song's own end. |
volume | 0-127 | The engine-wide master volume. Full volume if omitted. |
startOffset | number of whole notes (integer) | Playback start
offset. E.g. 1 skips one whole note's worth of time on every part before playback
begins (non-note commands within the skipped span are still processed internally). Omitted or
invalid is ignored. When loop: true and no jump point is set, this offset position is
also where a loop rewinds to. |
reverb | true / false | Whether to use the master reverb. Bypassed if false or omitted. |
reverbType | simple / normal |
simple = Schroeder type (lightweight), normal = FDN type (higher quality,
somewhat more expensive). |
reverbTime | 0.5-3.0 seconds (one decimal place) | The reverb's decay time. 0.5 or below bypasses reverb; above 3.0 is clamped to 3.0. |
reverbLevel | 0-127 | Reverb volume relative to the dry signal. 0 = dry only. |
reverbSend, no reverb is applied at all
while [global]'s reverb is false.[conductor] — conductor part (optional)
A special part that sets a loop's jump point and tempo changes over the course of the song. At most one per song; it doesn't need to be present at all.
[conductor]
[conductorPart]
R1 R1 J
T120 R4 T115 R4 T110 R4
T80
[conductorPartEnd]
| Command | Description |
|---|---|
Tnumber | Changes tempo to the given value (decimal point ignored). At the
very start of the part this takes priority over [global]'s tempo. Placed
mid-song, it changes the whole song's tempo (every part) from that point on. |
R+number | A rest (elapsed time for the conductor part itself). 2 = half
note, . for a dot, 6/12/24 for triplets. |
J | A jump point. When [global]'s loop: true,
reaching the song's end loops back to this jump point rather than to the start (or
startOffset) - useful for a one-time intro followed by a repeating section. At most one
is honored per song (any additional ones are ignored). |
[partSetting] — FM voice part initial setup
YAML format. Up to 16 parts (partNo: 1-16).
[partSetting]
part:
- partNo: 1
voiceID: 0
volume: 100
pan: 0
reverbSend: 30
transpose: -12
mute: false
solo: false
| Key | Range / format | Description |
|---|---|---|
partNo | 1-16 | Part number, matching a [partN] body
section. |
voiceID | integer | The FM voice to use. If the ID isn't in memory, a default voice is substituted. |
volume | 0-127 | Part volume. |
pan | -16(left)-16(right) | Pan. 0 = center. |
reverbSend | 0-127 | Send level to the master reverb. 127 = 100% wet. |
transpose | -36-36 (semitones) | Transposes the whole part. 1 = semitone, 12 = one octave. Omitted or out-of-range is ignored. |
mute | true / false | true silences this part. Omitted or invalid is treated as false. |
solo | true / false | true plays only this part (and any other solo:true parts), automatically muting every other part (mainly a debugging aid). |
[pcmPartSetting] — PCM voice part initial setup
YAML format. To distinguish PCM parts from FM parts, part numbers use A-P (up to 16 parts).
[pcmPartSetting]
pcmPart:
- partNo: A
voiceID: 0
partType: oneShot
volume: 60
pan: 0
transpose: 2
mute: false
solo: false
reverbSend: "C1: 5, E1: 30, F#1: 15"
- partNo: B
voiceID: 1
partType: long
volume: 100
pan: 5
reverbSend: 40
| Key | Range / format | Description |
|---|---|---|
partNo | A-P | Part number, matching a [pcmPartX] body
section. |
voiceID | integer | The PCM voice to use. |
partType | oneShot / long | Must match
that PCM voice's own voiceType (an oneShot part can only use an oneShot voice). |
volume | 0-127 | Part volume. |
pan | -16-16 | Pan. Ignored when partType is oneShot - the
voice's own per-sample voiceSetting pan takes priority instead. Used normally for
long. |
transpose | -36-36 | Same as an FM part. Only meaningful for long. |
mute | true / false | Same as an FM part. |
solo | true / false | Same as an FM part. |
reverbSend | depends on partType (see below) | Send level to the master reverb. |
reverbSend format differs by partType:For
partType: long, a single number (0-127), same as an FM part.For
partType: oneShot, since each WAV-mapped note needs its own send level, it's written
as a string (in double quotes): "note: level, note: level, ...". A note not listed gets
no reverb (send 0).
Each part's body: [partN] / [pcmPartX]
| Section | Start tag | End tag | Target |
|---|---|---|---|
| FM voice part | [part1]-[part16] |
[part1End]-[part16End] | Sounded by the FM synthesis core |
| PCM voice part | [pcmPartA]-[pcmPartP] |
[pcmPartAEnd]-[pcmPartPEnd] | Sounded from WAV samples (command grammar differs by oneShot vs. long voiceType) |
Between a start tag and its end tag you may freely add line breaks and whitespace within the performance commands (MML text) - they are stripped out and the whole block is parsed as one continuous command stream. See the MML Command Reference for the commands themselves.
[part1]
O3 C4D4E4F#4
G8A8B8
O4 C16C#16D16e16 F2R4G8
[part1End]