Skip to content
ipatix edited this page Dec 6, 2015 · 4 revisions

SMD Header

Offset Type Name Description
0x00 char[4] MagicNumber SMD file magic number "smdl"
0x04 DWORD Null
0x08 uint32_t FileSize Total file size (including this header)
0x0C WORD Version number???
0x0E uint8_t InstrumentGroup Instrument group ID. Link exists to UNK_AA command.
0x0F uint8_t Unknown, maybe indicates the type of sequence? Link exists to UNK_A9 command.
0x10 QWORD Null
0x18 QWORD Bitfield?
0x20 char[16] FileName Internal filename
0x30 DWORD Unknown, almost always 0x00000001
0x34 DWORD Unknown, almost always 0x00000001
0x38 PAD 0xFF pad to align on 0x10
sizeof=0x40

Song Header

Offset Type Name Description
0x00 char[4] MagicNumber Song chunk magic number "song"
0x04 DWORD 0x00000001?
0x08 DWORD 0x10FF0000?
0x0C DWORD 0xB0FFFFFF?
0x10 DWORD 0x01003000?
0x14 WORD 0x01FF?
0x16 uint8_t TrackChunkCount Number of track chunks after the song header
0x17 uint8_t OutChannelCount Number of output channels?
0x18 QWORD 0x0000000FFFFFFFFF?
0x20 DWORD 0x00000040?
0x24 DWORD 0x00404000?
0x28 DWORD 0x00020008?
0x2C DWORD 0x00FFFFFF?
0x30 PAD 0xFF pad to align on 0x20
sizeof=0x40

Track Chunk

Offset Type Name Description
0x00 char[4] MagicNumber Track chunk magic number "trk "
0x04 DWORD 0x00000001?
0x08 DWORD 0x04FF0000?
0x0C uint32_t TrackDataSize Size of track data, after this field
0x10 uint8_t TrackID Track ID number, zero indexed
0x11 uint8_t OutputID Output ID number, zero indexed
0x12 WORD 0x0000?
0x14 EVENTS See below
???? PAD 0x98 pad to aling on 0x4

Track Events

A track is composed of a series of events, which is composed of a stream of bytes parsed by the playback engine.

NOTE_PLAY

Opcode: 0x00..0x7F

This command plays a note. There are four different forms of the command:

Form OPCODE OP+1 OP+2 OP+3 OP+4
2-byte Velocity KeyFlag
3-byte Velocity KeyFlag Length
4-byte Velocity KeyFlag LengthMSB LengthLSB
5-byte Velocity KeyFlag LengthMSB LengthMidB LengthLSB

The Velocity parameter, which ranges from 0x00..0x7F, is the opcode itself. KeyFlag indicates flags to use, and the key the note applies to

KeyFlag & 0xC0 Meaning
0x00 Use the length of the previous note (2-byte form)
0x40 Use the provided length (3-byte form)
0x80 Use the provided length (4-byte form)
0xC0 Use the provided length (5-byte form)
KeyFlag & 0x30 Meaning
0x00 Go down 2 octaves
0x10 Go down 1 octave
0x20 Don't change octave
0x30 Go up 1 octave
KeyFlag & 0x0F Meaning
0x00 C
0x01 C#
0x02 D
0x03 D#
0x04 E
0x05 F
0x06 F#
0x07 G
0x08 G#
0x09 A
0x0A A#
0x0B B
0x0C C, +1 Oct, *
0x0D C#, +1 Oct, *
0x0E D, +1 Oct, *
0x0F D#, +1 Oct, *

*) These usually do not occur but they technically work. These "higher keys" don't affect the octave to use for new notes.

The Length parameter (optional) specifies the length of time the note should play for, in 1/48 beat ticks. It can be specified in either one or two bytes

DELTA_TIME

Opcode: 0x80..0x8F

This command waits for a specific amount of time, as indicated by the opcode byte:

OPCODE Delay (ticks) Musical
80 96 1/2 note
81 72 1/4 dotted
82 64 1/2 triplet
83 48 1/4 note
84 36 1/8 dotted
85 32 1/4 triplet
86 24 1/8 note
87 18 1/16 dotted
88 16 1/8 triplet
89 12 1/16 note
8A 9 1/32 dotted
8B 8 1/16 triplet
8C 6 1/32 note
8D 4 1/32 triplet
8E 3 1/64 note
8F 2 1/64 triplet

WAIT_AGAIN

Opcode: 0x90

This command waits for the amount of time the previous WAIT_AGIAN, WAIT_ADD, WAIT_1BYTE, or WAIT_2BYTE command did.

WAIT_ADD

Opcode: 0x91 ss

This command is just like WAIT_AGAIN, but it takes a signed int8_t as a parameter, adds (or subtracts) that to the previous wait length, and waits for that amount of time.

WAIT_1BYTE

Opcode: 0x92 uu

Waits for the amount of time specified by the single-byte parameter.

WAIT_2BYTE

Opcode: 0x93 ll hh

Waits for the amount of time specified by the two-byte parameter. The LSB is first, followed by the MSB.

TRACK_END

Opcode: 0x98

Marks the end of a track. Useful as an indicator to jump to the LOOP_POINT. Ends the playback if no LOOP_POINT was previously set. Is to be set for all tracks individually.

LOOP_POINT

Opcode: 0x99

Marks the loop point of a track. Absent if the track will not loop.

SET_OCTAVE

Opcode: 0xA0 uu

Selects the octave to use. MIDI key 0 is C in octave 0.

SET_TEMPO

Opcode: 0xA4 uu

Sets the tempo. This is in BPM; there are 48 ticks per beat.

SET_SAMPLE

Opcode: 0xAC uu

Sets the instrument to use. The actual instrument is based off the file's instrument group setting.

SET_MODU

Opcode: 0xBE uu

Sets the modulation parameter. 0x00..0x7F

SET_BEND

Opcode: 0xD7 sh sl

Dynamically adjusts the tuning of the track. Two-byte signed parameter indicating the setting in cents.

SET_VOLUME

Opcode: 0xE0 uu

Changes the volume of the track. Ranges from 0x00..0x7F.

SET_XPRESS

Opcode: 0xE3 uu

Changes the expression of the track. Ranges from 0x00..0x7F.

SET_PAN

Opcode: 0xE8 uu

Sets the track panning. Ranges from 0x00..0x7F, where 0x00 is full left, 0x40 is center, and 0x7F is full right.

Table of Opcodes

Here is a list of discovered opcodes. Opcodes which don't have a known purpose are referred to as "UNK_xx", where xx is the specifier.

Opcode Add Bytes Name
0x00..0x7F 1-3 NOTE_PLAY
0x80..0x8F 0 DELTA_TIME
0x90 0 WAIT_AGAIN
0x91 1 WAIT_ADD
0x92 1 WAIT_1BYTE
0x93 2 WAIT_2BYTE
0x98 0 TRACK_END
0x99 0 LOOP_POINT
0x9C 1 UNK_9C
0x9D 0 UNK_9D
0xA0 1 SET_OCTAVE
0xA4 1 SET_TEMPO
0xA8 2 UNK_A8
0xA9 1 UNK_A9
0xAA 1 UNK_AA
0xAC 1 SET_SAMPLE
0xB2 1 UNK_B2
0xB4 2 UNK_B4
0xB5 1 UNK_B5
0xBE 1 SET_MODU
0xBF 1 UNK_BF
0xC0 0 UNK_C0
0xD0 1 UNK_D0
0xD1 1 UNK_D1
0xD2 1 UNK_D2
0xD4 3 UNK_D4
0xD6 2 UNK_D6
0xD7 2 SET_BEND
0xDB 1 UNK_DB
0xDC 5 UNK_DC
0xE0 1 SET_VOLUME
0xE2 3 UNK_E2
0xE3 1 SET_XPRESS
0xE8 1 SET_PAN
0xEA 3 UNK_EA
0xF6 2 UNK_F6