The sm64dx audio system is a software-only N64 audio driver that schedules RSP tasks to mix PCM audio into output buffers. It is split into several cooperating C files underDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Project516/sm64dx/llms.txt
Use this file to discover all available pages before exploring further.
src/audio/: a sequence player that interprets MIDI-like sequence data, a synthesis engine that renders note layers to PCM, a heap allocator for audio memory, and load/DMA routines that stream sound banks from the ROM. The game communicates with the driver through the high-level API in external.h, which hides the internal task-queue and memory management details.
Audio subsystem files
external.c / external.h
The public-facing audio API consumed by the rest of the game. It provides The
play_sound(), play_music(), stop_background_music(), seq_player_fade_out(), sound_reset(), and the jingle helpers (play_star_fanfare(), play_course_clear(), etc.). Three sequence players are available:SEQUENCE_ARGS macro packs a priority and sequence ID into one 16-bit word passed to play_music():seqplayer.c / seqplayer.h
The sequence player interpreter. It steps through
.m64 (MIDI-like) sequence data, driving per-channel note events. Core functions:process_sequences() is called once per audio frame and advances all active players by the appropriate number of ticks.synthesis.c / synthesis.h
The PCM synthesis engine. It iterates over active note layers, applies envelope, pitch, and volume parameters, and writes interleaved 16-bit stereo samples into the output buffer. The RSP then picks up this buffer for final output mixing. The synthesis engine is paired with RSP audio microcode; it builds
OSTask structures describing the audio workload and posts them to the RSP via create_next_audio_frame_task().load.c / load.h
DMA and segment management: loading sound bank headers, instrument definitions, and sample data from ROM into audio heap.
audio_init() (declared in external.h, defined here) initialises the heap and loads the initial sound banks. Bank selection is driven by sound_reset(presetId), which switches the set of loaded banks when entering a new area.heap.c / heap.h
A simple pool allocator dedicated to audio memory. It allocates from a contiguous region reserved at startup, and provides
persistent and temporary allocation pools so that permanent bank data and per-frame scratch data can be managed separately without fragmentation.playback.c / playback.h
Manages the per-note playback state. It maintains the list of active
Note structs, handles note start/stop/release events received from the sequence player, and cooperates with the synthesis engine to drive envelope progression.data.c / data.h
Statically initialised tables: note-frequency lookup tables, envelope curves, and the global
gAudioRandom seed used by the audio driver’s internal randomisation.Shindou-specific audio files
The Shindou (SH) release uses a revised audio session layout and a different audio binary format. Three extra files handle this variant:| File | Purpose |
|---|---|
synthesis_sh.c | Shindou-specific synthesis loop with revised mixing paths |
load_sh.c | Shindou sound bank loading and DMA routines |
port_sh.c | Port-layer glue that maps Shindou audio sessions to the shared sequence player |
audio_session_presets_sh.c | Static preset tables for the Shindou audio session configurations |
shindou_debug_prints.c | Debug logging stubs present in the Shindou binary |
VERSION=sh is passed to make. They replace or supplement the base synthesis.c and load.c rather than patching them, keeping the version-specific code isolated.
Sequence IDs
Every piece of background music and event jingle is identified by an entry in theSeqId enum declared in include/seq_ids.h:
SEQ_VARIATION (0x80) to request an alternate arrangement of the same track. The base ID is masked with SEQ_BASE_ID (0x7F) when indexing into the sequence table. The game starts music via:
Sound effects
Sound effects are encoded as 32-bit words ininclude/sounds.h. Each word packs four fields:
| Constant | Bank | Contents |
|---|---|---|
SOUND_BANK_ACTION | 0 | Jumps, landings, punches |
SOUND_BANK_MOVING | 1 | Footsteps, sliding |
SOUND_BANK_VOICE | 2 | Mario’s voice clips |
SOUND_BANK_GENERAL | 3 | General game sounds |
SOUND_BANK_ENV | 4 | Environmental ambience |
SOUND_BANK_OBJ | 5 | Object sounds |
SOUND_BANK_AIR | 6 | Wind, flying |
SOUND_BANK_MENU | 7 | Menu UI sounds |
SOUND_BANK_GENERAL2 | 8 | Additional general sounds |
SOUND_BANK_OBJ2 | 9 | Additional object sounds |
play_sound(s32 soundBits, f32 *pos), where pos is a 3-element world position used for stereo panning. Specific convenience wrappers like play_dialog_sound() and play_mario_sound() are declared in external.h.
RSP audio microcode
Thersp/ directory contains RSP assembly (.s) for the audio synthesis microcode. The RSP runs this code to mix note layers, apply volume envelopes, and write the final PCM output. Two microcode variants are present:
synthesis.c constructs OSTask structs that reference the compiled RSP audio ucode and the per-frame audio command list. The game posts these tasks to the RSP via the N64 OS task queue and waits for the SP_INTR completion interrupt before copying the PCM output to the audio DAC.
Audio sessions and presets
sound_reset(u8 presetId) is the primary way the game switches the set of loaded sound banks when transitioning between areas. The preset ID selects a configuration from a static table that specifies which sound banks to load into the audio heap and which sequences to preload. On the Shindou version, audio_session_presets_sh.c provides an extended preset table that maps to the revised bank layout used in that release.