-
Notifications
You must be signed in to change notification settings - Fork 2
SMD_Format
| 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 |
| 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 |
| 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
|
A track is composed of a series of events, which is composed of a stream of bytes parsed by the playback engine.
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
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 |
Opcode: 0x90
This command waits for the amount of time the previous WAIT_AGIAN, WAIT_ADD, WAIT_1BYTE, or WAIT_2BYTE command did.
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.
Opcode: 0x92 uu
Waits for the amount of time specified by the single-byte parameter.
Opcode: 0x93 ll hh
Waits for the amount of time specified by the two-byte parameter. The LSB is first, followed by the MSB.
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.
Opcode: 0x99
Marks the loop point of a track. Absent if the track will not loop.
Opcode: 0xA0 uu
Selects the octave to use. MIDI key 0 is C in octave 0.
Opcode: 0xA4 uu
Sets the tempo. This is in BPM; there are 48 ticks per beat.
Opcode: 0xAC uu
Sets the instrument to use. The actual instrument is based off the file's instrument group setting.
Opcode: 0xBE uu
Sets the modulation parameter. 0x00..0x7F
Opcode: 0xD7 sh sl
Dynamically adjusts the tuning of the track. Two-byte signed parameter indicating the setting in cents.
Opcode: 0xE0 uu
Changes the volume of the track. Ranges from 0x00..0x7F.
Opcode: 0xE3 uu
Changes the expression of the track. Ranges from 0x00..0x7F.
Opcode: 0xE8 uu
Sets the track panning. Ranges from 0x00..0x7F, where 0x00 is full left, 0x40 is center, and 0x7F is full right.
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 |