DSIK Module Format
|Max channel count||16|
|Max track count||1|
|Max pattern count||65,535 (only 255 playable)|
|Max order count||128|
|Tags?||Title, instrument names, instrument filenames|
The DSIK Module Format is the music format used by the Digital Sound Interface Kit by Carlos Hasan. This was a C and Pascal library for game authors to simplify sound card programming.
The file is a non-standard Resource Interchange File Format (RIFF) structure. It is exactly the same as a standard RIFF file, except that the padding bytes between chunks have been omitted. So if the length of a chunk is an odd number, the padding byte should not be included and the following chunk will not start on a word boundary.
The files are composed of the following chunks:
- RIFF (type: DSMF)
The data in each chunk is explained below.
|char||title||Song title, null-terminated|
|UINT16LE||numOrders||Number of valid entries in orders|
|UINT8||orders||Order list. First value is index of first pattern to play, etc.|
This chunk stores all the instruments in the song. There are multiple INST chunks in the file, one per instrument. The data in each chunk is as follows:
|char||filename||Instrument filename, null-terminated|
|UINT16LE||flags||Zero or more of: 1=loop active, 2=signed PCM, 4=packed PCM, 64=delta PCM|
|UINT8||volume||Default volume of the sample if not volume is given when a note is played. The range is from 0 (silent) to 64 (loudest), note this is 65 different values.|
|UINT32LE||length||Length of the sample data, in bytes.|
|UINT32LE||loopStart||Position of the loop start point, in bytes, relative to the start of the sample data.|
|UINT32LE||loopEnd||Position of the loop end point, in bytes, relative to the start of the sample data.|
|UINT32LE||address_ptr||Used internally for holding in-memory address of sample data, ignore when reading and write as zero.|
|UINT16LE||midCRate||Default is 8363|
|UINT16LE||period||Default for middle-C is 428|
|char||title||Sample name, null-terminated|
|BYTE[length]||data||Sample data, 8-bit mono PCM|
Sample data must be 8-bit mono PCM, signed or unsigned based on flags ! Confirm that signed PCM actually works. Other formats are rejected by the DSIK library. Some samples appear to be truncated .wav files and still have the 'data' fourcc visible, however this is not part of the format and these bytes will be played as audio data, causing an audible click at the start of playback.
The period is calculated from a sample rate (in Hertz) as
period = 8363 * 428 / Hertz
This chunk stores all the patterns in the song. There are multiple PATT chunks in the file, one per pattern. The data in each chunk is as follows:
|UINT16LE||length||Length of pattern data, in bytes, including this length field also|
|UINT8[length - 2]||data||Pattern data, see below|
The pattern data is comprised of a flag byte, followed by a variable number of data bytes depending on the value of the flag. This is very similar to S3M Format but the bit fields are different. The flag byte is broken down as follows:
|Note present||Instrument present||Volume present||Command present||Channel number|
- If the entire value is zero, the row number is incremented and the next flag is read. Otherwise:
- If the flag indicates a note is present, the next byte is the note. Note numbers are semitones, with note 49 being middle C, note 50 being C#4, note 51 being D4, etc. Adding 11 to the note number will turn them into standard MIDI note numbers.
- If an instrument is present, the next byte is the zero-based index of the instrument to use.
- If a volume is present, the next byte is the volume for this note/channel. The range is from 0 (silent) to 64 (loudest), note this is 65 different values.
- If a command is present, the next two bytes are the command and value respectively. Standard .mod commands appear to be used ! Confirm
After these bytes have been read, the next flag byte is read. Once 64 rows have been read, the end of the pattern data should have been reached.
If the instrument is read but it is zero, then the previous instrument on that channel should be used instead (same as S3M).
Effects 0x00 through 0x0F are the same as in MOD files. The OpenMPT code references effect IDs greater than 0x0F but no such commands have been found in the wild.
Effect 0x08 is 7-bit panning (0x00 = left, 0x80 = right) with parameter 0xA4 enabling surround. DSIK is quite possibly the origin of this panning scheme which was later adopted by other S3M players.
See S3M Format#Timing for a discussion on timing using the initialBPM and initialSpeed values.
The file format suffers from a number of design inconsistencies:
- The DSMF format should have been registered with Microsoft as it is in uppercase, however this does not appear to have been done
- The INST and PATT chunks should have been placed inside LIST chunks, in the spirit of the RIFF format
- The instrument chunk includes a length field for the sample data, however this is redundant as the chunk itself already has a length. The two length fields do make it possible to store additional data between the end of the sample data and the end of the chunk, which would normally be ignored, however it seems simpler to just define a new chunk type if new data needs to be stored without breaking backwards compatibility.
- The instrument chunk stores an address field even though this is only used during playback and does not need to be stored in the file.
- The pattern chunk also has an extra field to store the length of the pattern data. However the value in this field includes the length of the field itself, making the value identical to the RIFF chunk's length field. The result is that the identical value is written twice, once as a 32-bit value for the RIFF PATT chunk and then immediately again as a 16-bit value.
- The number of instruments and patterns is stored in the SONG chunk, however this is redundant as the values can be calculated from the number of INST and PATT chunks respectively.
- There is a 16-bit value for the number of orders, allowing up to 65,535 orders in the song, yet there is a fixed-length array allowing only 128 orders.
- The pattern count is 16-bit allowing up to 65,536 patterns in the song, but the order list is made up of 8-bit values, meaning only the first 256 patterns can be played.
The following tools are able to work with files in this format.
|Name||Platform||Play?||Create new?||Modify?||Convert/export to other?||Import from other?||Access hidden data?||Edit metadata?||Notes|
|Camoto||Linux/Windows||Yes||Yes||Yes||Many||Many||No||Yes||Minimal support for effects|
|Chronos Module Converter||DOS||No||No||No||.mod .stm .s3m .mtm .dsm .psm||No||No||No||Most accurate for converting .dsm to .s3m|
|DSIK's conv.exe||DOS||No||Yes||No||No||.mod .stm .s3m .669 .mtm||No||Yes||Official tool|
|ModPlug||Windows||Yes||No||No||No||No||No||No||Plays at wrong tempo (no support for effect 0x0F)|
- The original Digital Sound Interface Kit library is available as dsik_c.zip or dsik_pas.zip for the C and Pascal versions respectively, from various FTP sites such as lanet.lv
This file format was documented by Malvineous by reading the DSIK sample code, with the pattern data documented from reading the OpenMPT source code. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)