DSIK Module Format

From ModdingWiki
Jump to navigation Jump to search
DSIK Module Format
Format typeMusic
Notation typeTracked
InstrumentsPCM
Max channel count16
Max track count1
Max pattern count65,535 (only 255 playable)
Max order count128
Tags?Title, instrument names, instrument filenames
Games

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.

File format

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)
    • SONG
    • INST
    • PATT

The data in each chunk is explained below.

SONG chunk

Data type Name Description
char[28] title Song title, null-terminated
UINT16LE version File version
UINT16LE flags
UINT32LE pad
UINT16LE numOrders Number of valid entries in orders
UINT16LE numSamples
UINT16LE numPatterns
UINT16LE numChannels
UINT8 volGlobal Global volume
UINT8 volMaster Master volume
UINT8 initialSpeed
UINT8 initialBPM
UINT8[16] channelMap
UINT8[128] orders Order list. First value is index of first pattern to play, etc.

INST chunk

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:

Data type Name Description
char[13] 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[28] 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

PATT chunk

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:

Data type Name Description
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:

7 6 5 4 3 2 1 0
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.

Timing

See S3M Format#Timing for a discussion on timing using the initialBPM and initialSpeed values.

Design issues

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.

Tools

The following tools are able to work with files in this format.

Name PlatformPlay? Create new? Modify? Convert/export to other? Import from other? Access hidden data? Edit metadata? Notes
Camoto Linux/WindowsYesYesYesManyManyNoYes Minimal support for effects
Chronos Module Converter DOSNoNoNo.mod .stm .s3m .mtm .dsm .psmNoNoNo Most accurate for converting .dsm to .s3m
DSIK's conv.exe DOSNoYesNoNo.mod .stm .s3m .669 .mtmNoYes Official tool
ModPlug WindowsYesNoNoNoNoNoNo Plays at wrong tempo (no support for effect 0x0F)
OpenMPT AnyYesNoNoManyNoNoNo

External links

  • 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

Credits

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!)