Deathtrack Sound Effect Format

From ModdingWiki
Jump to navigation Jump to search
Deathtrack Sound Effect Format
Format typeSound
HardwarePC Speaker
Number of sounds11
Sampling rateN/A
Channel count1
Bits per sampleUnknown
Compressed?Yes
Tags?None
Games

The eleven sound effects of Deathtrack are small programs for a PC-speaker interpreter, stored in the SND: container at the start of PALS.BLK. They are not samples. Even when AdLib or MT-32 music is selected, effects play on the PC speaker; only the interpreter's tick rate differs between the devices.

The container is the resource chunk format.

File format

PALS.BLK starts with the following chunks:

Chunk Contents
SND:INF: (6 bytes) Three UINT16LE words
SND:IBM: (506 bytes) Enveloped bank, 501 bytes after decoding
SND:ITM: Optional second bank; not present in the shipped file

SND:INF:

Data type Name Description
UINT16LE unused Discarded by the loader (0x59D9)
UINT16LE count Number of effects (11)
UINT16LE reserved 0

SND:IBM: (decoded)

Data type Name Description
UINT32LE[count] offsets Offset of each effect stream from the start of the decoded block. The game adds the block's address to every non-zero entry
STREAM[count] streams Effect streams

Stream

Data type Name Description
UINT16LE type 0 in all effects
UINT16LE length Length field (see the source code for how it is used)
UINT32LE reserved 0
COMMAND[] commands Voice program, ends when a duration command with value 0 is executed

Commands

A command is a byte whose value is masked with 0x7E to give the opcode; all commands except hold are followed by a UINT16LE operand. The effect interpreter is a four-voice priority system that runs on every timer interrupt.

Opcode Name Operand
0x02 Duration UINT16LE; a value of 0 ends the voice
0x04 PIT divisor UINT16LE
0x06 Pitch slide UINT16LE (signed)
0x0A Gate UINT16LE
0x0C Gate slide UINT16LE
0x1C Phase step UINT16LE
0x1E Wave depth UINT16LE
0x20 Loop counter UINT16LE
0x2E Wave select UINT16LE
0x7A Relative call UINT16LE (relative offset)
0x7C Hold none
0x7E Relative loop UINT16LE (relative offset)

The names are those used by the port's analysis; the exact per-tick behaviour of each field is defined by the translated interpreter in src/game/sfx.js and the notes in docs/re/input-timer-sound.md.

Comparisons and wrap-around are signed or unsigned depending on the opcode, so an exact implementation should follow the translated interpreter. The wave-select command reads a table (ITM) that is missing in the shipped bank; the original reads bytes relocated from the IBM block instead.

All eleven effects end. Streams 7 and 10 have trailing unreachable bytes. The tick rate depends on the music device: PC speaker 1193182/4096 Hz, AdLib 1193182/8192 Hz, MT-32 1193182/512 Hz.

Source code

From re-deathtrack, the open-source browser port:

Credits

This file format was reverse engineered by VorticonCmdr. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)