From http://www.xtracker32.org/fileformat.shtml
-----
This is the documentation of the DMF file format versions 6 and up, as used by
the original DOS xtracker and xtracker32.
- Versions up to 7 where only used in beta version of xtracker. Still there are
quite a few songs available that use these versions. - The xtracker final
version used file format version 8 - xtracker32 extensions are marked as file
format version 10.
DDMF (D-lusion digital music format) is a IFF-like chunk-orientated format
which should be really easy to use. The following chunks exist:
* [DDMF] Format identifier
* [INFO] reserved
* [CMSG] Song message
* [SEQU] Sequencer, order to play patterns in
* [PATT] Patterndata
* [INST] Instrument data, reserved
* [SMPI] Sample-Information
* [SMPD] Sample-Data. Must be saved after [SMPI] chunk
* [SMPJ] Sample Jump Positions. Must be saved after [SMPI] chunk (v10+)
* [ENDE] EOF marker
+-----------------------------------------------------------------------------+
| DDMF chunk - Format identifier |
|-----------------------------------------------------------------------------|
| Offset | Description | Type |
|----------+------------------------------------------------------+-----------|
| 00h | Chunk ID ('DDMF') | 4 Chars |
|----------+------------------------------------------------------+-----------|
| 04h | File version | 1 Byte |
|----------+------------------------------------------------------+-----------|
| 05h | Tracker software name | 8 Chars |
|----------+------------------------------------------------------+-----------|
| 0dh | Song name - fill unused chars with 0 | 30 Chars |
|----------+------------------------------------------------------+-----------|
| 2bh | Composer name - fill unused chars with 0 | 20 Chars |
|----------+------------------------------------------------------+-----------|
| 3fh | Creation date - one byte for day, month, year+1900 | 3 Bytes |
+-----------------------------------------------------------------------------+
+-----------------------------------------------------------------------------+
| CMSG chunk - Song message |
|-----------------------------------------------------------------------------|
| Offset | Description | Type |
|--------+----------------------------------------------------------+---------|
| 00h | Chunk ID ('CMSG') | 4 Chars |
|--------+----------------------------------------------------------+---------|
| | Blocklength - Offset to start of next block. This does | |
| 04h | NOT include the Chunk ID or the blocklength field itself | 1 dword |
| | (so blocklength is the length of the current chunk - 8) | |
|--------+----------------------------------------------------------+---------|
| 08h | Filler - reservered (0) | 1 byte |
|--------+----------------------------------------------------------+---------|
| 09h | Message - ASCII-Text with fixed length of 40 chars per | x chars |
| | line. Length of Message is blocklength-1 bytes | |
+-----------------------------------------------------------------------------+
+-----------------------------------------------------------------------------+
| SEQU chunk - sequencer data |
|-----------------------------------------------------------------------------|
| Offset | Description | Type |
|--------+----------------------------------------------------------+---------|
| 00h | Chunk ID ('SEQU') | 4 Chars |
|--------+----------------------------------------------------------+---------|
| 04h | Blocklength - (see above) | 1 dword |
|--------+----------------------------------------------------------+---------|
| 08h | Sequencer loop start | 1 word |
|--------+----------------------------------------------------------+---------|
| 0ah | Sequencer loop end | 1 word |
|--------+----------------------------------------------------------+---------|
| | Sequencer data - every word represents one entry in the | |
| 0ch | sequencer. Length is blocklength-4 ((blocklength-4)/2 | x words |
| | sequencer entries) | |
+-----------------------------------------------------------------------------+
+-----------------------------------------------------------------------------+
| PATT chunk - pattern data |
|-----------------------------------------------------------------------------|
| Offset | Description | Type |
|-----------------+-----------------------------------------+-----------------|
| 00h | Chunk ID ('PATT') | 4 Chars |
|-----------------+-----------------------------------------+-----------------|
| 04h | Blocklength - (see above) | 1 dword |
|-----------------+-----------------------------------------+-----------------|
| 08h | Pattern entries (1-1024) - number of | 1 word |
| | patterns in this song | |
|-----------------+-----------------------------------------+-----------------|
| 0ah | Max tracks (1-32) - highest number of | 1 byte |
| | tracks used in all patterns | |
|-----------------+-----------------------------------------+-----------------|
| 0bh | Patterns - the following structure is | |
| | repeated 'pattern entries' times | |
|-----------------------------------------------------------------------------|
| +-------------------------------------------------------------------------+ |
| | Pattoffs. | Description | Type | |
| |----------------+-----------------------------------------+--------------| |
| | 00h | Track entries (1-32) - number of tracks | 1 Byte | |
| | | in this pattern | | |
| |----------------+-----------------------------------------+--------------| |
| | | Beat - the lower nibble of this byte is | | |
| | | reserved. The upper nibble holds the | | |
| | 01h | number of rows per beat. A value of 64 | 1 Byte | |
| | | in this field would result in every 4th | | |
| | | row beeing highlighted (64 shr 4 = 4) | | |
| |----------------+-----------------------------------------+--------------| |
| | 02h | Row entries - number of rows in this | 1 Word | |
| | | pattern | | |
| |----------------+-----------------------------------------+--------------| |
| | | Patternlength - Length of the following | | |
| | 04h | pattern data in bytes = offset to begin | 1 DWord | |
| | | of next pattern | | |
| |----------------+-----------------------------------------+--------------| |
| | | Patterndata - Compressed stream of | | |
| | | pattern data. Sorry, now it's getting a | | |
| | | bit more complex ;) | | |
| | 08h | The following structure is repeated | x Bytes | |
| | | 'Row entries' times: (Attention: If the | | |
| | | last rows of the pattern are completely | | |
| | | empty, then they won't be saved) | | |
| |-------------------------------------------------------------------------| |
| | +---------------------------------------------------------------------+ | |
| | | [GLOBAL TRACK] ([TRACK] * [TRACK ENTRIES]) | | |
| | |---------------------------------------------------------------------| | |
| | | GLOBAL TRACK: | | |
| | | | | |
| | | INFO - 1 Byte | | |
| | | (COUNTER) - 1 Byte | | |
| | | (DATA) - 1 Byte | | |
| | | | | |
| | | INFO = zyxxxxxx | | |
| | | | | |
| | | xxxxxx (lowest 6 bits) = Global track effect | | |
| | | y = reserved | | |
| | | z = counter saved (pack indicator) | | |
| | | | | |
| | | In case the pack indicator is set, then the next byte in the stream | | |
| | | will be COUNTER. | | |
| | | COUNTER is a (guess what ;) counter that is count down for every | | |
| | | note row. There is no global track information saved until counter | | |
| | | is 0 again. At the begin of a pattern, COUNTER always starts with | | |
| | | 0. | | |
| | | If the pack indicator isn't set then no COUNTER is saved, instead | | |
| | | you have to assume COUNTER beeing 0 which means that the next row | | |
| | | will have a global track again. | | |
| | | If the global track effect is > 0, then a DATA byte containing the | | |
| | | effect data is saved in the stream. Else there is no DATA byte. | | |
| | |---------------------------------------------------------------------| | |
| | | TRACK: | | |
| | | | | |
| | | INFO - 1 Byte | | |
| | | (COUNTER) - 1 Byte | | |
| | | (INSTRUMENT) - 1 Byte | | |
| | | (NOTE) - 1 Byte | | |
| | | (VOLUME) - 1 Byte | | |
| | | (INSTRUMENT EFFECT) - 2 Bytes | | |
| | | (NOTE EFFECT) - 2 Bytes | | |
| | | (VOLUME EFFECT) - 2 Bytes | | |
| | | | | |
| | | INFO = 76543210 | | |
| | | bit 0: reserved | | |
| | | bit 1: 1=volume effect saved | | |
| | | bit 2: 1=note effect saved | | |
| | | bit 3: 1=instrumend effect saved | | |
| | | bit 4: 1=volume saved | | |
| | | bit 5: 1=note saved | | |
| | | bit 6: 1=instrument saved | | |
| | | bit 7: 1=counter saved (pack indicator) | | |
| | | | | |
| | | The following values are only saved if the corresponding bits in | | |
| | | INFO are set. | | |
| | | | | |
| | | COUNTER | | |
| | | See above - COUNTER is counted down for each row until it is zero. | | |
| | | There is no data saved in this track until counter reaches zero. If | | |
| | | the pack indicator isn't set, then there is no counter saved which | | |
| | | means that the next row will have track data again. | | |
| | | | | |
| | | INSTRUMENT | | |
| | | Instrument/Sample to play | | |
| | | | | |
| | | NOTE | | |
| | | 0 = No change | | |
| | | 1-108 = Note in halfnote-steps, C0=1 up to H8=108. | | |
| | | 109-128 = undefined | | |
| | | 129-236 = This note is saved into the notebuffer, the current | | |
| | | playing note won't be changed. The Notebuffer is used as a second | | |
| | | parameter for effects like "portamento to note", where the effect | | |
| | | parameter byte is already in use. | | |
| | | 237-254 = undefined | | |
| | | 255 = Note Off, sets the notes frequency to 0 hz | | |
| | | | | |
| | | VOLUME | | |
| | | 0 = undefined 1-255 = new volume, linear scaling | | |
| | | | | |
| | | INSTRUMENT EFFECT | | |
| | | 1. Byte: Instrument effect nr. | | |
| | | 2. Byte: Instrument effect data | | |
| | | | | |
| | | NOTE EFFECT | | |
| | | 1. Byte: Note effect nr. | | |
| | | 2. Byte: Note effect data | | |
| | | | | |
| | | VOLUME EFFECT | | |
| | | 1. Byte: Volume effect nr. | | |
| | | 2. Byte: Volume effekt data | | |
| | |---------------------------------------------------------------------| | |
| | +---------------------------------------------------------------------+ | |
| +-------------------------------------------------------------------------+ |
+-----------------------------------------------------------------------------+
+-----------------------------------------------------------------------------+
| SMPI chunk - Sample-Information |
|-----------------------------------------------------------------------------|
| Offset | Description | Type |
|-----------------+----------------------------------------+------------------|
| 00h | Chunk ID ('SMPI') | 4 Chars |
|-----------------+----------------------------------------+------------------|
| 04h | Blocklength - (see above) | 1 dword |
|-----------------+----------------------------------------+------------------|
| 08h | Sample entries - number of samples | 1 Byte |
| | saved in the song | |
|-----------------+----------------------------------------+------------------|
| 09h | Samples - the following structure is | Bytes |
| | repeated 'Sample entries' times | |
|-----------------------------------------------------------------------------|
| +-------------------------------------------------------------------------+ |
| | Sampleoff. | Description | Type | |
| |------------+--------------------------------------------------+---------| |
| | 00h | Samplename length (0-30) - number chars of | 1 Byte | |
| | | samplename | | |
| |------------+--------------------------------------------------+---------| |
| | 01h | Samplename - the name of the sample | x Chars | |
| |------------+--------------------------------------------------+---------| |
| | | Sample length - length of sample in bytes. | | |
| | x + 01h | Attention: This is the final length of the | 1 Dword | |
| | | depacked sample (unlike the sample length in the | | |
| | | SMPD chunk, which stores the packed length) | | |
| |------------+--------------------------------------------------+---------| |
| | x + 05h | Sample loop start - position of sample loop | 1 Dword | |
| | | start in bytes | | |
| |------------+--------------------------------------------------+---------| |
| | x + 09h | Sample loop end - position of sample loop end in | 1 Dword | |
| | | bytes | | |
| |------------+--------------------------------------------------+---------| |
| | x + 0dh | c3 frequency - frequency in hz of the sample at | 1 Word | |
| | | the note c-3. Valid range is 1000-45000 Hz | | |
| |------------+--------------------------------------------------+---------| |
| | x + 0fh | Volume - Sample volume, 0 = not set, 1-255 = | 1 Byte | |
| | | volume in linear scale | | |
| |------------+--------------------------------------------------+---------| |
| | | Sample Type - Different flags that define the | | |
| | | sample | | |
| | | xxxxxxx0 = no loop | | |
| | | xxxxxxx1 = sample is played looping. The sample | | |
| | | plays from its beginning on until it reaches | | |
| | | 'Sample loop end' and then repeats the range | | |
| | | from 'Sample loop start' to 'Sample loop end' | | |
| | | xxxxxx0x = 8BIT Sample | | |
| | x + 10h | xxxxxx1x = 16BIT Sample | 1 Byte | |
| | | xxxxXXxx = Compression type xxxx00xx = | | |
| | | Uncompressed signed PCM xxxx01xx = Compression | | |
| | | type 0 - modified huffmann xxxx10xx = | | |
| | | Compression type 1 - mp3 xxxx11xx = Compression | | |
| | | type 2 - currently undefined xxx0xxxx = mono | | |
| | | sample xxx1xxxx = stereo sample xXXxxxxx = | | |
| | | reserved 0xxxxxxx = sampledata is saved in SMPD | | |
| | | chunk 1xxxxxxx = sampledata is saved in external | | |
| | | libary | | |
| |------------+--------------------------------------------------+---------| |
| | | Library Name - library name in which the sample | | |
| | x + 11h | is stored. Fill with 0 if unused. ATTENTION: | 8 Bytes | |
| | | This field only exists in version 8 and above. | | |
| | | (With xtracker32 it's unused for now) | | |
| |------------+--------------------------------------------------+---------| |
| | x + 19h | Filler - reserved | 1 Byte | |
| |------------+--------------------------------------------------+---------| |
| | x + 1bh | CRC32 - crc32 over sampledata | 1 DWord | |
| +-------------------------------------------------------------------------+ |
+-----------------------------------------------------------------------------+
+-----------------------------------------------------------------------------+
| SMPD chunk - Sample-Data |
|-----------------------------------------------------------------------------|
| Offset | Description | Type |
|-----------------+----------------------------------------+------------------|
| 00h | Chunk ID ('SMPD') | 4 Chars |
|-----------------+----------------------------------------+------------------|
| 04h | Blocklength - (see above) | 1 dword |
|-----------------+----------------------------------------+------------------|
| | Sample data - the following structure | |
| 08h | is repeated 'Sample entries' (from | Bytes |
| | SMPI) times | |
|-----------------------------------------------------------------------------|
| +-------------------------------------------------------------------------+ |
| | Sampleoff. | Description | Type | |
| |------------+--------------------------------------------------+---------| |
| | | Sample data length - length of sample data | | |
| | | stream in bytes. This is the real length of the | | |
| | 00h | possibly compressed data. For the real final | 1 Dword | |
| | | length, see SMPI chunk. If this sample is empty | | |
| | | or saved in a library file, then this field is | | |
| | | set to 0 | | |
| |-------------------------------------------------------------------------| |
| |-------------------------------------------------------------------------| |
| | 04h | Sample data stream | x Bytes | |
| +-------------------------------------------------------------------------+ |
+-----------------------------------------------------------------------------+
+-----------------------------------------------------------------------------+
| SMPJ chunk - Sample Jump points |
| (This chunk exists from dmf version 10 and up) |
|-----------------------------------------------------------------------------|
| Offset | Description | Type |
|-----------------+-----------------------------------------+-----------------|
| 00h | Chunk ID ('SMPJ') | 4 Chars |
|-----------------+-----------------------------------------+-----------------|
| 04h | Blocklength - (see above) | 1 dword |
|-----------------+-----------------------------------------+-----------------|
| | Sample jump points - the following | |
| 08h | structure is repeated 'Sample entries' | Bytes |
| | (from SMPI) times | |
|-----------------------------------------------------------------------------|
| +-------------------------------------------------------------------------+ |
| | Offset | Description | Type | |
| |--------+---------------------------------------------------+------------| |
| | 00h | Count of jump points following. 0=No jump points | 1 Byte | |
| | | for this sample | | |
| |-------------------------------------------------------------------------| |
| |-------------------------------------------------------------------------| |
| | | Jump points. This is the sample-offset in bytes | | |
| | | (not samples!) to jump to if the JMP command is | | |
| | 01h | issued in a track. These are 32 bit signed | x Integers | |
| | | integers. A value of -1 means that a jump-point | | |
| | | is undefined. In this case the JMP command should | | |
| | | be ignored. | | |
| +-------------------------------------------------------------------------+ |
+-----------------------------------------------------------------------------+
+-----------------------------------------------------------------------------+
| ENDE chunk - end of DDMF |
|-----------------------------------------------------------------------------|
| Offset | Description | Type |
|---------------------+--------------------------------+----------------------|
| 00h | Chunk ID ('ENDE') | 4 Chars |
+-----------------------------------------------------------------------------+