DSE SMDL Format
General Information
The SMDL format is a container for sequenced music. Its very close to the MIDI format, similarly to the SSEQ format normally used in most NDS games.
File Structure
Overview
Offset | Length | Name | Description |
---|---|---|---|
0x0 | 64 | SMDLHeader | The container's header. |
0x40 | 64 | Song Chunk | Information on the entire sequence. |
After Song Chunk | Varies | Trk Chunk | The first Track of the sequence. Its role is to set the tempo. |
..Additional tracks here.. | |||
After all Track Chunks | 16 | End of Content Chunk | This empty chunk marks the end of the SMDL container. |
SMDL Header
Offset | Length | Type | Name | Description |
---|
Song Chunk
Offset | Length | Type | Name | Description |
---|
Trk Chunk
Offset | Length | Type | Name | Description |
---|
Eoc Chunk
Offset | Length | Type | Name | Description |
---|---|---|---|---|
0x0 | 4 | - | ChunkID | The chunk ID "eoc\0x20" {0x65, 0x6F, 0x63, 0x20} |
0x4 | 4 | uint32 | Param1 | Unknown meaning, is often 0x00000001. |
0x8 | 4 | uint32 | Param2 | Unknown meaning, is often 0x04FF0000. |
0xC | 4 | uint32 | Length | Always 0, for end of content chunks. |
DSE Events
Tracks are filled with event codes, which indicates to the sequencer what to do.
- Their value ranges from 0x0 to 0xFF.
- Events from 0x0 to 0x7F are reserved for the PlayNote event.
- Events from 0x80 to 0x8F are reserved for fixed duration pause events.
- Events from 0x90 to 0xFF all have their unique meaning.
PlayNote(0x0 to 0x7F)
The play note event is special in that its format is particular.
- The event code itself is the velocity(0x0 - 0x7F) of the note to be played.
- The first parameter byte is obligatory, and it contains info on whether we modify the track's current octave, how many extra parameters are there, and what note to play.
- The second parameter is optional, and its length varies depending on the length specified in the obligatory parameter. It contains the duration the key is "held down" before being released.
Here's a breakdown of the NoteData byte:
Bits | Name | Meaning |
---|---|---|
1100 0000 | OctaveMod | A value from 0 to 3 from which 2 is subtracted. The result is a signed value that we add to the track's current octave. |
0011 0000 | NbParamBytes | A value from 0 to 3 which indicates the amount of extra parameter bytes that should be read. |
0000 1111 | Note | The Note that should be played at the track's current octave(after OctaveMod). |
Note List
Value | Note Name |
---|---|
0x0 | C |
0x1 | C# |
0x2 | D |
0x3 | D# |
0x4 | E |
0x5 | F |
0x6 | F# |
0x7 | G |
0x8 | G# |
0x9 | A |
0xA | A# |
0xB | B |
0xF | Unknown |
Example Event
Velocity | NoteData | (Opt)KeyDownDuration | ||
---|---|---|---|---|
0x7F | 0x65 | 0x20 | 0x01 | 0x10 |
This event will play the note F, at the current track octave with no modifications, and hold the note for 0x100120 ticks.
Fixed Duration Pause(0x80 to 0x8F)
The fixed duration pause is a pause event based on the duration of common musical time intervals. Its event code goes from 0x80-0x8F.
Here's a table of the possible durations:
Code | Musical Time Interval | Duration in Ticks |
---|---|---|
0x80 | Half Note | 96 |
0x81 | Dotted Quarter Note | 72 |
0x82 | 2/3 of a Half Note | 64 |
0x83 | Quarter Note | 48 |
0x84 | Dotted 8th Note | 36 |
0x85 | 2/3 of a Quarter Note | 32 |
0x86 | 8th Note | 24 |
0x87 | Dotted 16th Note | 18 |
0x88 | 2/3 of a 8th Note | 16 |
0x89 | 16th Note | 12 |
0x8A | Dotted 32nd Note | 9 |
0x8B | 2/3 of a 16th Note | 8 |
0x8C | 32nd Note | 6 |
0x8D | Dotted 64th Note | 4 |
0x8E | 2/3 of a 32nd Note | 3 |
0x8F | 64th Note | 2 |
Others(0x90 to 0xFF)
Here is a list of all known events :
Code | Parameter Length | Parameters | Name | Description |
---|---|---|---|---|
0x90 | 0 | - | RepeatLastPause | Pause the track processing for the duration of the last pause.(Includes fixed duration pauses) |
0x91 | 1 | (uint8)Duration | AddToLastPause | Pause the track processing for the duration of the last pause + the duration in ticks specified.(Includes fixed duration pauses) |
0x92 | 1 | (uint8)Duration | Pause8Bits | Pause the track processing for the duration in ticks. |
0x93 | 2 | (uint16)Duration | Pause16Bits | Pause the track processing for the duration in ticks. |
0x94 | 3 | (uint24)Duration | Pause24Bits | Pause the track processing for the duration in ticks. |
0x95 | 1 | (uint8)CheckInterval | PauseUntilRelease | Pause the track processing as long as a note is held down. Will wait for at least "CheckInterval" ticks, then checks every "CheckInterval" ticks if all notes have been released on the current track. |
0x96 | 0 | - | INVALID | Disable current track. |
0x97 | 0 | - | INVALID | Disable current track. |
0x98 | 0 | - | EndOfTrack | Marks the end of the track. Is also used as padding to align the end of the track on 4 bytes. |
0x99 | 0 | - | LoopPoint | Marks the point the track will loop to after the end of track is reached. |
0x9A | 0 | - | INVALID | Disable current track. |
0x9B | 0 | - | INVALID | Disable current track. |
0x9C | 1 | ?? | ?? | ?? |
0x9D | 0 | ?? | ?? | ?? |
0x9E | 0 | ?? | ?? | ?? |
0x9F | 0 | - | INVALID | Disable current track. |
0xA0 | 1 | (uint8)Octave | SetTrackOctave | Sets the current track's octave to the value specified. Valid range is 0 - 9. |
0xA1 | 1 | (uint8)Octave | AddToTrackOctave | Adds the value specified to the current track octave. |
0xA2 | 0 | - | INVALID | Disable current track. |
0xA3 | 0 | - | INVALID | Disable current track. |
0xA4 | 1 | (uint8)TempoBPM | SetTempo | Sets the track's tempo in beats per minute. |
0xA5 | 1 | (uint8)TempoBPM | SetTempo | Sets the track's tempo in beats per minute? (The code is identical to 0xA4) |
0xA6 | 0 | - | INVALID | Disable current track. |
0xA7 | 0 | - | INVALID | Disable current track. |
0xA8 | 2 | ?? | ?? | ?? |
0xA9 | 1 | ?? | ?? | ?? |
0xAA | 1 | ?? | ?? | ?? |
0xAB | 0 | - | SkipNextByte | Skips processing the next byte. |
0xAC | 1 | (uint8)ProgramID | SetProgram | Change the track's program(Instrument Preset) to the one specified. |
0xAD | 0 | - | INVALID | Disable current track. |
0xAE | 0 | - | INVALID | Disable current track. |
0xAF | 3 | ?? | ?? | ?? |
0xB0 | 0 | ?? | ?? | ?? |
0xB1 | 1 | ?? | ?? | ?? |
0xB2 | 1 | ?? | ?? | ?? |
0xB3 | 1 | ?? | ?? | ?? |
0xB4 | 2 | ?? | ?? | ?? |
0xB5 | 1 | ?? | ?? | ?? |
0xB6 | 1 | ?? | ?? | ?? |
0xB7 | 0 | - | INVALID | Disable current track. |
0xB8 | 0 | - | INVALID | Disable current track. |
0xB9 | 0 | - | INVALID | Disable current track. |
0xBA | 0 | - | INVALID | Disable current track. |
0xBB | 0 | - | INVALID | Disable current track. |
0xBC | 1 | ?? | ?? | ?? |
0xBD | 0 | - | INVALID | Disable current track. |
0xBE | 1 | ?? | ?? | ?? |
0xBF | 1 | ?? | ?? | ?? |
0xC0 | 1 | ?? | ?? | ?? |
0xC1 | 0 | - | INVALID | Disable current track. |
0xC2 | 0 | - | INVALID | Disable current track. |
0xC3 | 1 | ?? | ?? | ?? |
0xC4 | 0 | - | INVALID | Disable current track. |
0xC5 | 0 | - | INVALID | Disable current track. |
0xC6 | 0 | - | INVALID | Disable current track. |
0xC7 | 0 | - | INVALID | Disable current track. |
0xC8 | 0 | - | INVALID | Disable current track. |
0xC9 | 0 | - | INVALID | Disable current track. |
0xCA | 0 | - | INVALID | Disable current track. |
0xCB | 2 | - | SkipNext2Bytes | Skip processing the next 2 bytes. |
0xCC | 0 | - | INVALID | Disable current track. |
0xCD | 0 | - | INVALID | Disable current track. |
0xCE | 0 | - | INVALID | Disable current track. |
0xCF | 0 | - | INVALID | Disable current track. |
0xD0 | 1 | ?? | ?? | ?? |
0xD1 | 1 | ?? | ?? | ?? |
0xD2 | 1 | ?? | ?? | ?? |
0xD3 | 2 | ?? | ?? | ?? |
0xD4 | 3 | ?? | ?? | ?? |
0xD5 | 2 | ?? | ?? | ?? |
0xD6 | 2 | ?? | ?? | ?? |
0xD7 | 2 | (uint16)Bend | PitchBend | Bend the pitch of the note. |
0xD8 | 2 | ?? | ?? | ?? |
0xD9 | 0 | - | INVALID | Disable current track. |
0xDA | 0 | - | INVALID | Disable current track. |
0xDB | 1 | ?? | ?? | ?? |
0xDC | 5 | ?? | ?? | ?? |
0xDC | 4 | ?? | ?? | ?? |
0xDE | 0 | - | INVALID | Disable current track. |
0xDF | 1 | ?? | ?? | ?? |
0xE0 | 1 | (int8)TrackVolume | SetTrackVolume | Change the track's volume to the value specified. (0x0-0x7F) |
0xE1 | 1 | ?? | ?? | ?? |
0xE2 | 3 | ?? | ?? | ?? |
0xE3 | 1 | (int8)TrackExpression | SetTrackExpression | Change the track's expression(secondary volume) to the value specified. (0x0-0x7F) |
0xE4 | 5 | ?? | ?? | ?? |
0xE5 | 4 | ?? | ?? | ?? |
0xE6 | 0 | - | INVALID | Disable current track. |
0xE7 | 1 | ?? | ?? | ?? |
0xE8 | 1 | (int8)Pan | SetTrackPan | Change the track's pan to the value specified. (0x0-0x7F. 0x40 is middle, 0x0 full left, and 0x7F full right ) |
0xE9 | 1 | ?? | ?? | ?? |
0xEA | 3 | ?? | ?? | ?? |
0xEB | 0 | - | INVALID | Disable current track. |
0xEC | 5 | ?? | ?? | ?? |
0xED | 4 | ?? | ?? | ?? |
0xEE | 0 | - | INVALID | Disable current track. |
0xEF | 1 | ?? | ?? | ?? |
0xF0 | 5 | ?? | ?? | ?? |
0xF1 | 4 | ?? | ?? | ?? |
0xF2 | 2 | ?? | ?? | ?? |
0xF3 | 3 | ?? | ?? | ?? |
0xF4 | 0 | - | INVALID | Disable current track. |
0xF5 | 0 | - | INVALID | Disable current track. |
0xF6 | 1 | ?? | ?? | ?? |
0xF7 | 0 | - | INVALID | Disable current track. |
0xF8 | 2 | ?? | ?? | ?? |
0xF9 | 0 | - | INVALID | Disable current track. |
0xFA | 0 | - | INVALID | Disable current track. |
0xFB | 0 | - | INVALID | Disable current track. |
0xFC | 0 | - | INVALID | Disable current track. |
0xFD | 0 | - | INVALID | Disable current track. |
0xFE | 0 | - | INVALID | Disable current track. |
0xFF | 0 | - | INVALID | Disable current track. |
Credits
- TruePikachu for some of the details on the SMDL format! [1]