S3M Format is used to save modules composed in ScreamTracker 3. A number of games support music in this format, however it is primarily used for composing independent songs unrelated to games.
The format is notable both for its popularity, as well as for being one of the few that support both FM/OPL and sampled instruments.
The file begins with a header.
|char||title||Song title, must be null-terminated|
|UINT8||sig1||Signature byte, always 0x1A|
|UINT8||type||Song type, always 0x10 for S3M|
|UINT16LE||orderCount||Number of entries in the order table, should be even|
|UINT16LE||instrumentCount||Number of instruments in the song|
|UINT16LE||patternPtrCount||Number of pattern parapointers in the song|
|UINT16LE||trackerVersion||upper four bits is tracker ID, lower 12 bits is tracker version|
|UINT16LE||sampleType||1=signed samples [deprecated], 2=unsigned samples|
|UINT8||initialSpeed||Frames per row, can be changed later with A command|
|UINT8||initialTempo||Frames per second, can be changed later with T command|
|UINT8||masterVolume||bit 7: 1=stereo, 0=mono, bits 6-0: volume|
|UINT8||ultraClickRemoval||Number of channels to use for click removal on real GUS hardware|
|UINT8||defaultPan||252=read pan values in header, anything else ignores pan values in header|
|BYTE||reserved||Unused, some trackers store data here|
|UINT16LE||ptrSpecial||Parapointer to additional data, if flags has bit 7 set|
|UINT8[orderCount]||orderList||Which order patterns are played in|
|UINT16LE[instrumentCount]||ptrInstruments||List of parapointers to each instrument's data|
|UINT16LE[patternPtrCount]||ptrPatterns||List of parapointers to each pattern's data|
Flags are one or more values below:
|0||1||ST2 vibrato [deprecated]|
|1||2||ST2 tempo [deprecated]|
|2||4||Amiga slides [deprecated]|
|3||8||0vol optimisations - automatically turn off looping notes when the volume is zero for more than two rows|
|4||16||Amiga limits - ignore notes beyond Amiga hardware limits (as Amiga does.) Sliding up stops at B#5. Also affects other Amiga compatibility issues.|
|5||32||Enable SoundBlaster filter/sfx [deprecated]|
|6||64||ST3.00 volume slides - perform volume slides on first row as well. Set implicitly if trackerVersion is 0x1300.|
|7||128||ptrSpecial is valid|
Known trackerVersion values are:
|0x2nyy||Imago Orpheus x.yy|
|0x3nyy||Impulse Tracker x.yy|
channelSettings is 32 values indicating the audio channel assignments for each of the 32 S3M channels. Unused channels should be set to 255.
|0 to 7||Left PCM channels 1 to 8|
|8 to 15||Right PCM channels 1 to 8|
|16 to 24||Adlib melody channel 1-9|
|25||Adlib percussion channel: bass drum|
|26||Adlib percussion channel: snare drum|
|27||Adlib percussion channel: tom tom|
|28||Adlib percussion channel: top cymbal|
|29||Adlib percussion channel: hi-hat|
|30 to 127||Unused/invalid|
|128 to 254||Unused/invalid (but channel disabled)|
orderList contains the index of each pattern to be played. The first entry in this array is the index of the first pattern to play, the second entry is the second pattern, etc. If an entry is 0xFE then it is a "marker pattern" and is skipped during playback, and an entry of 0xFF signifies the end of the song.
ptrInstruments and ptrPatterns are arrays of parapointers to the start of the instrument and pattern data. Each parapointer is an offset from the start of the file, in units of 16 bytes (a "paragraph"). To convert this into a normal byte-level file offset, multiply it by 16 (or shift-left by 4.)
By convention these blocks follow the header above, but this is not a requirement and they can occur at any point in the file.
The initialTempo and initialSpeed values are the ones to use until optionally changed during playback, with the A and T effects respectively.
The initialTempo value controls how many audio frames are generated per second. If this value is 50, then there should be 50 audio frames per second. Obviously the more audio frames per second, the shorter each frame is going to be. To calculate the length of each frame, a formula like this can be used:
frame length in seconds = 1 / initialTempo 0.02 seconds per frame = 1 / 50
The initialSpeed value controls how many audio frames comprise a single row of the song. If the value is 3, then there are three audio frames per row. For certain effects, they are updated once per frame (i.e. the effect changes between rows.)
To calculate playback speed, both these values need to be taken into account. The tempo value controls the length of each audio frame, while the speed value controls how quickly the rows are turned into those audio frames. For example, to calculate the number of rows per second:
rowsPerSecond = initialTempo / initialSpeed
At the offset given by an instrument's parapointer, the data has a header as follows:
|UINT8||type||0=empty instrument (message only), 1=PCM instrument|
|char||filename||Original instrument filename in DOS 8.3 format, no terminating null|
|0||empty instrument (message only)|
|2||Adlib melody instrument|
|3||Adlib percussive: bass drum|
|4||Adlib percussive: snare|
|5||Adlib percussive: tom tom|
|6||Adlib percussive: top cymbal|
|7||Adlib percussive: hi-hat|
The data following the header depends on whether the instrument is PCM or Adlib. What if the instrument is empty, is there any trailing data?
|UINT8||ptrDataH||Upper eight bits of parapointer to sample data, relative to start of S3M file|
|UINT16LE||ptrDataL||Lower 16 bits of parapointer to sample data, relative to start of S3M file|
|UINT32LE||length||Sample data length, in bytes. S3M is limited to 64000 and ignores upper 16 bits.|
|UINT32LE||loopStart||Offset of loop start in bytes, relative to start of sample data.|
|UINT32LE||loopEnd||Offset of loop end in bytes, relative to start of sample data.|
|UINT8||volume||Default volume of sample, 0-63 inclusive.|
|UINT8||pack||0=unpacked, 1=DP30ADPCM [deprecated]|
|UINT8||flags||Sum: 1=loop on, 2=stereo (data is length bytes for left channel then length bytes for right channel), 4=16-bit little-endian sample|
|UINT32LE||c2spd||Sample rate for middle-C note (C-4)|
|BYTE||internal||Always zero, used in-memory during playback|
|char||title||Sample title, for display to user. Must be null-terminated.|
ScreamTracker stores the above instrument structures at the start of the file, but stores the sample data at the end of the file (after the pattern data.) This is not the only way to store it though.
|UINT8||reserved||Always 0x00 0x00 0x00|
|UINT8||volume||Default volume of instrument, 0-63 inclusive.|
|UINT32LE||c2spd||Sample rate for middle-C note (C-4), see below.|
|char||title||Sample title, for display to user. Must be null-terminated.|
The oplValues are stored as follows:
|Byte index||Operator||OPL base register||Bits|
|2||Modulator||0x40||Scale level (bit 0)||Scale level (bit 1)||Output level (0=loudest, 63=silent)|
|4||Modulator||0x60||Attack rate||Decay rate|
|6||Modulator||0x80||Sustain rate||Release rate|
|11||-||-||Unused, set to 0x00|
c2spd sets the instrument tuning. It scales the note freq - the exact formula is unknown. The default value is 8363 as with PCM instruments, and increasing this by roughly 10 tunes the note up by one OPL F-num (approx 0.7Hz in OPL block 2). somehow
- The value packing is almost identical to that used in the SBI Format, just the bytes are in a different order.
- The ST3 docs say bytes 2-3 bits 5-0 are "63-volume" but this is to make the values match PCM samples. The value in the file matches the value sent to the OPL chip.
- The Scale Level bits in bytes 2-3 are swapped. The ST3 technical docs have a typo that suggest Scale Level (bit 1) actually overflows into "bit 8" of the OPL register, but testing this in ST3 shows this is not the case and the bit order is merely swapped.
- The ST3 docs say bytes 6-7 have the sustain rate stored as "15-sustain" but it seems to work better storing the exact value to send to the OPL chip.
At the offset given by a pattern's parapointer, packed data is present and will need to be unpacked. The following structure appears at the start of each pattern's data:
|UINT16LE||packed_len||Length of packed data for all 64 rows, in bytes|
|BYTE[packed_len - 2]||packed_data||Packed row data, described below|
packed_len includes its own length, so as it is two bytes long, the length of the packed data will be two bytes less than this value. The first byte in packed_data is a bitfield called what, and it is broken up as follows:
|command and info present||volume present||note and instrument present||Channel number|
If the whole byte is zero then it signals the end of the row. This byte and the ones following are further described in the following table.
|UINT8||what||0=end of row, lower five bits (what & 0x1F) are channel number|
|UINT8||note||Note number (only present if what & 0x20)|
|UINT8||instrument||Instrument number (only present if what & 0x20)|
|UINT8||volume||Volume level (only present if what & 0x40)|
|UINT8||command||Effect type (only present if what & 0x80)|
|UINT8||info||Effect value (only present if what & 0x80)|
After these bytes the process repeats with another what value. When what is 0x00 the end of the row has been reached. After the 64th row has been reached, the pattern ends and packed_len bytes will have been read.
Be aware that channel is a value between 0 and 31 inclusive, which corresponds to an entry in the channelSettings field in the header.
The volume field is 0 for silent, 64 for full volume (note this is 65 unique values), or 255 for 'ignore' (shown as ".." in the tracker.) If the value is 255 or missing entirely, the instrument's default volume is used (the volume value from the instrument settings.)
The upper four bits of note store the octave, and the lower four bits store the semitone (with 0=C, 1=C#, up to 11=B)
0x01/A: Set speed
Set speed (one of the two tempo variables.) Data byte is new speed. A value of 0 causes the event to be ignored.
0x02/B: Order jump
After the current row has finished playing, the next row is the first row in order given by the data byte. 0 means the start of the song . Confirm this
0x03/C: Jump to row
After the current row has finished playing, the next row is played from the next pattern in the order sequence. The row in this next pattern is given by the data byte, but the data byte is decimal-as-hex. So a value of 0x12 should be treated as decimal 12. These formulae will calculate the correct row (to/from the S3M value):
row = (data >> 4) * 10 + (data & 0x0f) // Read S3M into variable data = ((row / 10) << 4) | (row % 10) // Write variable to S3M
The first row in the pattern is 0. If the decoded data value is larger than 63, the effect is ignored.
The following tools are able to work with files in this format.
|Name||Platform||Play?||Create new?||Modify?||Convert/export to other?||Import from other?||Access hidden data?||Edit metadata?||Notes|
|SchismTracker||Windows/Linux||Yes||Yes||Yes||.it + more||.mod .it + more||No||Yes||Can play OPL and PCM simultaneously|
|ScreamTracker 3||DOS||Yes||Yes||Yes||.mod||.mod||No||Yes||Official tool|
Much of this information was combined from the following sites: