MDX is a Music Macro Language format, with commands such as Note, Rest, Set Tempo and many others. It was used for storing music on the Sharp X68000 computer. There is a large library of MDX files available (see README for some links).
WARNING: this document is work in progress. Since I've had to rely on Google Translate, some of the commands might be ambiguously translated. Wherever you see the question marks, there are uncertainties.
Info here is based on http://www16.atwiki.jp/mxdrv/pages/23.html
MDX files are composed of a header, the voices, and the MML commands.
- Title in Shift_JIS encoding, followed by 0x0d 0x0a 0x1a
- PDX file name, followed by 0x00 (just 0x00 if there is no PDX file)
- Word: Voice data offset
- Word[9 or 16] MML data offset
The voice and MML offsets are relative to the voice data offset position (right after the title and PDX file name). To implement this in code, just use a ftell() after you've read the PDX file name. The MML data offset array points to each of the channels. Some files use 9 channels, other use 16. To detect which is which, subtract the file position of the first MML data offset word from its value, then divide by 2. See MDX.h for the implementation.
The FM channels are labeled A through H. The PCM channel is labeled P. The extra channels, when the Mercury expansion card is present, are labeled Q through W.
This corresponds to the OPM registers. Each field is 1 byte. The x4 fields are 4 bytes corresponding to M1, M2, C1, C2. Total is 27 bytes per voice.
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
Voice ID | ||||||||
FL | CON | |||||||
Slot Mask | ||||||||
DT1 | MUL | ×4 | ||||||
TL | ×4 | |||||||
KS | AR | ×4 | ||||||
AME | D1R | ×4 | ||||||
DT2 | D2R | ×4 | ||||||
D1L | RR | ×4 |
Unused bits are set to 0. Set bits 6 and 7 of [FL & CON] to 0.
Each command consists of one byte, followed by specific parameters. Integers are in big endian format.
Command | MML | Description |
---|---|---|
0x00-0x7f | r | Rest +1 clock cycles. |
0x80-0xdf n | n#,# | Note data, followed by duration n + 1. 0x80 corresponds to MML o0d+, which means octave 0, note D♯. 0xdf corresponds to o8d, octave 8, D. To calculate the MIDI equivalent note, subtract 0x80 and add 3 . For the PCM channels, P through W, this represents the sample index, the first sample is 0x80 , second sample is 0x81 and so on. |
0xff n | @t# | Set tempo to n . Tempo applies to all tracks at the same time, not just current track. |
0xfe n m | y#1,#2 | Set OPM register n to value m . |
0xfd n | @# | Set current voice. |
0xfc n | p# | Pan. |
0xfb n | @v# | Set volume. |
0xfa | ( | Decrease volume. |
0xf9 | ) | Increase volume. |
0xf8 n | q# | Set note length (staccato). |
0xf7 | & | Legato. Disable key off for next note. Corresponds to MML command & , except it precedes the note instead of following it. |
0xf6 n 0x00 | [ | Repeat n times until a Repeat end command. Corresponds to MML command [ , but loop multiplier is specified here instead of the closing ] . |
0xf5 nn | ] | Repeat end. Loop back nn (signed word) bytes. |
0xf4 nn | / | Repeat escape. In the last repetition, skip nn bytes, thus shortening it. Loosely corresponds to MML command / , inside [] . |
0xf3 nn | D# | Detune nn /64 semitones. |
0xf2 nn | _ | Portamento. Change pitch nn /16384 semitones per clock. This is issued before the starting note. |
0xf1 0x00 | ! (?) | Performance end. |
0xf1 nn | L | Performance end, but loop from nn bytes (nn is a negative int16). |
0xf0 n | k# | Delay key-on n ticks. |
0xef n | S# | Sync send on channel n . If channel n is in Sync Wait, resume playback on that channel. |
0xee | W | Sync Wait on current channel. Pause playback on this channel until resumed by a Sync Send signal (see above). |
0xed n | F# | ADPCM / noise frequency set to n . For FM channels (A-H), 0 means disable noise, 128+ means set noise frequency (without bit 7). For ADPCM channels (P-W), sets sampling frequency. |
0xec 0x80 | MPOF | Pitch LFO disable. |
0xec 0x81 | MPON | Pitch LFO enable. |
0xec m nn aa | MP#1,#2,#3 | LFO Pitch control. m controls the waveform (0=sawtooth, 1=square, 2=triangle), nn is the frequency, expressed in clock cycles / 4, and aa is the amplitude. |
0xeb 0x80 | MAOF | LFO Amplitude Modulation disable. |
0xeb 0x81 | MAON | LFO Amplitude Modulation enable. |
0xeb m nn aa | MA#1,#2,#3 | LFO Volume control. Same parameters as LFO Pitch. |
0xea 0x80 | MHOF | OPM LFO Off. |
0xea 0x81 | MHON | OPM LFO On. |
0xea m n o p q | MH#1,#2,#3,#4,#5,#6,#7 | Set OPM LFO values m =sync/wave, n =lfrq, o =PMD, p =AMD, q =PMS/AMS. |
0xe9 n | MD# | Set LFO key-on delay. |
0xe8 | Enable PCM8 mode (PCM channels Q -W ). | |
0xe7 0x01 n | Fade-out at speed n . |