Music/SMD
SMD files are Final Fantasy Tactics's music files. Each SMD file holds one song.
Contents
Header
The header consists of the following:
Width (bytes) | Type | Purpose |
---|---|---|
4 | string | SMD identifier (literal "smds") |
4 | ? | Unknown |
4 | uint | File size (in bytes) |
8 | ? | Unknown |
1 | uint | Number of channels |
9 | ? | Unknown |
2 | uint | Offset of filename |
2 | uint | Offset of data chunk |
2 | uint | Offset of channel N. The number of these will equal the number of channels read earlier. |
2 | uint | End of offsets. (Should equal 0) |
variable | string | Filename. This is a zero-terminated string. |
Channels
SMD files contain a number of channels. Each channel contains a sequence of notes and instructions, and they're all played simultaneously. To play a 3-note chord, for example, you need to have 3 channels, and each channel plays one note of the chord. Typically, channel 0 doesn't contain notes, only special instructions like tempo settings. There is some evidence that notes placed in channel 0 will not play, so notes should probably go in channels 1 and higher.
Instructions
Each instruction begins with an identifier byte and is followed by zero to 3 parameter bytes. The number of parameter bytes depends on the instruction.
Value (hex) | Parameters (bytes) | Purpose |
---|---|---|
0x00-0x7F | 1 or 2 | Play a note. 0x00 is the quietest and 0x7F is the loudest. The 1st parameter is the note's pitch and duration. (See the table below.) If the first parameter is divisible by 0x13 (19), then there will be a second parameter. |
0x80 | 1 | Rest. The parameter is the length of the rest, in 192nds of a note. A duration of 0xc0 (192) is equal to a whole note, 0x60 (96) is a half note, etc. |
0x81 | 1 | Extend previous note. The parameter is the length of the extension, in 192nds of a note. |
0x90 | 0 | End channel. Stops any more instructions from being read in this channel. |
0x91 | 0 | Loop remainder of channel indefinitely. |
0x94 | 1 | Set octave. The parameter is the octave. 0x03 is the 4th octave (the one with middle C). |
0x95 | 0 | Increment octave |
0x96 | 0 | Decrement octave |
0x97 | 2 | Set time signature, apparently. Not sure if this affects playback or is just informational. The 1st parameter is the top number, the 2nd is the bottom. |
0x98 | 1 | Begin loop. The parameter is the number of times to loop |
0x99 | 0 | End loop. |
0x9c | 3 | ? |
0xa0 | 1 | Set tempo. 0x66 (102) is the most commonly-used tempo across all files, and it appears to be 120 bpm. |
0xac | 1 | Set instrument. The parameter is the instrument number. For a full list, see: Instruments. |
0xba | 0 | Begin channel. Always found at the beginning of a channel. Can also be used in the middle of a channel as a noop. |
0xbf | 0 | ? |
0xc0 | 0 | ? |
0xc2 | 1 | Set attack rate. First parameter is the length of the attack. Higher values mean the note takes longer to fade in. |
0xc3 | 1 | ? |
0xc4 | 1 | ? Set sustain rate. First parameter is the length of time before fade-out. Higher values mean the note stays at full volume longer. |
0xc5 | 1 | ? |
0xc6 | 1 | ? Set sustain rate. Works differently than 0xc4. |
0xc7 | 2 | ? Something to do with note volume. |
0xc8 | 1 | ? |
0xc9 | 1 | ? |
0xd2 | 1 | ? |
0xd7 | 1 | ? |
0xd8 | 3 | Pitch shift. The 1st parameter is the speed, 2nd is the intensity (amount of pitch change), and 3rd is delay before pitch shift happens in each note. |
0xda | 0 | ? |
0xdb | 0 | ? |
0xe0 | 1 | Set volume. 0x00 is the quietest, 0x7f is the loudest. |
0xe3 | 1 | ? |
0xe4 | 3 | ? |
0xe6 | 0 | ? |
0xe8 | 1 | Set balance. 0x00 is left speaker, 0x7f is right speaker. |
Notes
To play a note, use a note-playing instruction (00-7f) followed by a byte from the table below. If you use a custom note length (0x00, 0x13, 0x26, etc.), then you will need a second parameter specifying the note's length, in 192nds of a note (see explanation of Rests, above). This gives you more control over exactly how long the note lasts.
C | C# | D | D# | E | F | F# | G | G# | A | A# | B | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Custom | 00 | 13 | 26 | 39 | 4c | 5f | 72 | 85 | 98 | ab | be | d1 |
whole | 01 | 14 | 27 | 3a | 4d | 60 | 73 | 86 | 99 | ac | bf | d2 |
dotted half | 02 | 15 | 28 | 3b | 4e | 61 | 74 | 87 | 9a | ad | c0 | d3 |
half | 03 | 16 | 29 | 3c | 4f | 62 | 75 | 88 | 9b | ae | c1 | d4 |
dotted quarter | 04 | 17 | 2a | 3d | 50 | 63 | 76 | 89 | 9c | af | c2 | d5 |
3rd | 05 | 18 | 2b | 3e | 51 | 64 | 77 | 8a | 9d | b0 | c3 | d6 |
quarter | 06 | 19 | 2c | 3f | 52 | 65 | 78 | 8b | 9e | b1 | c4 | d7 |
dotted 8th | 07 | 1a | 2d | 40 | 53 | 66 | 79 | 8c | 9f | b2 | c5 | d8 |
6th | 08 | 1b | 2e | 41 | 54 | 67 | 7a | 8d | a0 | b3 | c6 | d9 |
8th | 09 | 1c | 2f | 42 | 55 | 68 | 7b | 8e | a1 | b4 | c7 | da |
dotted 16th | 0a | 1d | 30 | 43 | 56 | 69 | 7c | 8f | a2 | b5 | c8 | db |
12th | 0b | 1e | 31 | 44 | 57 | 6a | 7d | 90 | a3 | b6 | c9 | dc |
16th | 0c | 1f | 32 | 45 | 58 | 6b | 7e | 91 | a4 | b7 | ca | dd |
dotted 32nd | 0d | 20 | 33 | 46 | 59 | 6c | 7f | 92 | a5 | b8 | cb | de |
24th | 0e | 21 | 34 | 47 | 5a | 6d | 80 | 93 | a6 | b9 | cc | df |
32nd | 0f | 22 | 35 | 48 | 5b | 6e | 81 | 94 | a7 | ba | cd | e0 |
48th | 10 | 23 | 36 | 49 | 5c | 6f | 82 | 95 | a8 | bb | ce | e1 |
64th | 11 | 24 | 37 | 4a | 5d | 70 | 83 | 96 | a9 | bc | cf | e2 |
96th | 12 | 25 | 38 | 4b | 5e | 71 | 84 | 97 | aa | bd | d0 | e3 |
Credit
Thanks to P.J. Barnes for figuring out the structure of the file and a few commands.