Sona 0.50 Source

Sona 0.50/doc/sonamml.txt

SonaMML is the MML variant used by the mml2sona tool.

This documentation is for MML as implemented by mml2sona version 0.50. It does
*not* explain MML for now so you will need to look up elsewhere (sorry), it
just goes into the details of this particular dialect.

The ; character introduces comments (everything from ; to the end of the line
will be ignored). If a line begins with ' then that ' will be ignored (as if it
hadn't been written).


*** MML channels ***

Channels are assigned as follows:

   A-F   FM channels 1-6
   G-I   PSG square channels 1-3
   J     PSG noise channel
   K-L   PCM channels 1-2
   Z     Control

MML channel Z doesn't map to any actual channel, but it can be used to include
commands that affect the whole track (e.g. tempo or loop) without having to
shoehorn them between the notes of another channel.


*** MML commands ***

Spaces are optional (assuming they don't cause an ambiguity). Text between « »
represents arguments.

@$

   [SFX only] Locks the current channel. Sound effects need to lock the
   channels that they use.

@ «instrument»

   Sets the instrument ID (0~255) for this channel.

l «length»

   Sets the length for the following notes without length.
   
   «length» is one of 1, 2, 4, 8, 16, 32, 64 or 128 (note length is
   1/«length») and may be followed by . to extend the length by half (e.g.
   l32. is a length of 1/32 + 1/64), except for 128. You can add up lengths
   with ^ (e.g. l4^16 is 1/4 + 1/16).
   
   Alternatively, «length» can be % followed by the number of ticks (e.g.
   %32 is 32 ticks). The number must be larger than 0. You can't use . with
   this format but you can still use ^ to add lengths.
   
   Other lengths may also be achieved by use of the s or & commands.

«note»
«note» «length»

   Note is one of c, d, e, f, g, a, b. It inserts a note (key-on) with that
   pitch. «length» is optional. The note can be suffixed with + and - signs
   to change the pitch (e.g. c+ is C#, d++ is E, b- is A#, etc.).
   
   For PSG channel 4 (noise), you must use the n command instead. For PCM
   channels, the note pitch is ignored, the current instrument ID determines
   what sound to play.

n «value»
n «value» , «length»

   For FM channels and PSG channels 1~3, «value» is the pitch in semitones
   (0~95 for FM, 24~95 for PSG). For PSG channel 4, «value» is the noise mode
   (see below). For PCM channels, «value» is the instrument ID.
   
   Possible values for PSG channel 4:
   
      0 = periodic noise, high pitch
      1 = periodic noise, medium pitch
      2 = periodic noise, low pitch
      3 = periodic noise, pitch from PSG3
      4 = white noise, high pitch
      5 = white noise, medium pitch
      6 = white noise, low pitch
      7 = white noise, pitch from PSG3

r
r «length»

   Inserts a rest (key-off). «length» is optional.

s
s «length»

   Inserts a wait (no key-on nor key-off). «length» is optional.

o «octave»

   Set the octave for the following notes. «octave» is 0~7 for FM channels
   and 1~6 for PSG channels.

<

   Lowers the octave for the following notes by 1.

>

   Raises the octave for the following notes by 1.

k «semitones»
K «semitones»

   Transposes the pitch for the following notes (adds that many semitones). The
   number of semitones can be negative. The k command is absolute (replaces the
   previous transpose), while the K command is relative (adds to the previous
   transpose instead).
   
   You can reset transpose with k0
   
   Transpose is independent from the o < > commands (the effect of the two is
   accumulated).

v «volume»

   Set the volume for this channel. «volume» is 0~15, where 0 is mute and
   15 is loudest.

(
( «value»

   Lowers the channel volume by «value». If «value» is missing then it lowers
   the channel volume by 1.

)
) «value»

   Raises the channel volume by «value». If «value» is missing then it raises
   the channel volume by 1.

_

   The next note doesn't have key-on (only sets pitch).

&

   The next note is turned into a wait (no key-on, no key-off, no pitch).
   The s command does the same without needing a & command.

p «setting»

   FM channels only, sets the channel panning:
   
      0 = no output
      1 = right speaker only
      2 = left speaker only
      3 = both speakers
   
   For PSG channels this command is ignored.
   Note: FM channel 6's panning also affects PCM channels!

L

   Set loop point here. When the stream is over it jumps back to the loop
   point instead of stopping.

[ «commands» ] «count»

   Repeat section. The commands between [ and ] are executed «count» times.

t «tempo»

   [BGM only] Sets the tempo of the track. The default tempo value is
   120 (60Hz), higher values are faster and lower values are slower,
   proportionally. A whole note (l1) is 128 ticks.

y «register» , «value»

   Write directly to a YM2612 register. «register» is 0~255 for bank 1 or
   256~511 for bank 2.

yFB «value»
yDM «operator» , «value»
yTL «operator» , «value»
yKA «operator» , «value»
yDR «operator» , «value»
ySR «operator» , «value»
ySL «operator» , «value»
ySE «operator» , «value»

   Write directly to a YM2612 register (like the y command), but using the
   name of the register instead of the number. It writes to the register for
   the current FM channel and the specified «operator» (0~3).

@# «byte» , «byte» , «byte»...

   Inserts bytes as-is into the stream. Each «byte» must be between 0 and 255.
   Useful to insert commands not supported by SonaMML yet.

@ { «dest» = «src» }

   Copies a value into VM variable «dest».
   
   «dest» must be a variable, while «src» can be either another variable or a
   number between 0 and 255. Global variables range from V0 to V127, while
   local variables range from v0 to v7.
   
   Note that local variables overlap global variables:
   
      A (FM ch1)  = V0 to V7
      B (FM ch2)  = V8 to V15
      C (FM ch3)  = V16 to V23
      D (FM ch4)  = V24 to V31
      E (FM ch5)  = V32 to V39
      F (FM ch6)  = V40 to V47
      G (PSG ch1) = V48 to V55
      H (PSG ch2) = V56 to V63
      I (PSG ch3) = V64 to V71
      J (PSG ch4) = V72 to V79
      K (PCM ch1) = V80 to V87
      L (PCM ch2) = V88 to V95
      Z (control) = V96 to V103
      
      SFX #1      = V104 to V111
      SFX #2      = V112 to V119
      SFX #3      = V120 to V127

@ { «dest» += «src» }

   Same as = above, but it adds «src»'s value to «dest».
   
   The result must fit in one byte (0..255), if the result is larger than 255 it
   will wrap around (e.g. 250 + 10 = 260, becomes 260 - 256 = 4).

@ { «dest» -= «src» }

   Same as = above, but it substracts «src»'s value from «dest».
   
   The result must fit in one byte (0..255), if the result is smaller than 0 it
   will wrap around (e.g. 5 - 10 = -5, becomes -5 + 256 = 251).

@ { «dest» &= «src» }

   Same as = above, but it does a binary AND of «src» and «dest». Bits that are
   1 in both «src» and «dest» are left intact, while the rest are turned into 0.
   Used to clear bits (e.g. AND with 254 will clear bit 0).

@ { «dest» |= «src» }

   Same as = above, but it does a binary OR of «src» and «dest». Bits that are
   0 in both «src» and «dest» are left intact, while the rest are turned into 1.
   Used to set bits (e.g. OR with 8 will set bit 3).

@ { «dest» ^= «src» }

   Same as = above, but it does a binary XOR of «src» and «dest». Bits that are
   the same in both «src» and «dest» are turned into 0, while bits that differ
   between them are turned into 1. Used to flip bits (e.g. XOR with 32 will flip
   bit 5).

|

   Bar separator. Does nothing (like spaces).

«macro»

   Where «macro» is one of !A~Z, !a~z or !0~255. It inserts the macro here.
   The macro is inserted as-is and can have incomplete commands.