This tutorial covers SNES audio including the SPC700 sound chip, BRR samples, and SNESMOD tracker playback.
SNES Audio Architecture
The SNES has a dedicated SPC700 sound processor with:
- 8 audio channels
- 64KB dedicated audio RAM
- BRR (Bit Rate Reduction) sample compression
- Hardware ADSR envelopes
- Echo/reverb effects
Audio Options in OpenSNES
| Method | Best For | Size | Complexity |
| Legacy Audio | Simple SFX, tones | ~500 bytes | Low |
| SNESMOD | Music + SFX | ~5.5KB | Medium |
SNESMOD (Recommended)
SNESMOD is a tracker-based audio engine supporting Impulse Tracker (.it) modules.
Setup
- Create music in a tracker (OpenMPT recommended)
- Export as Impulse Tracker (.it) format
- Convert with smconv tool
- Link soundbank with your ROM
Makefile Configuration
# Enable SNESMOD
USE_SNESMOD := 1
USE_LIB := 1
LIB_MODULES := console sprite input
# Soundbank source files
SOUNDBANK_SRC := music/mymusic.it sfx/effects.it
Basic Music Playback
#include "soundbank.h"
while (1) {
}
return 0;
}
int main(void)
Entry point — initialize audio, display controls, run transport loop.
Definition main.c:37
void consoleInit(void)
Initialize SNES hardware.
void WaitForVBlank(void)
Wait for next VBlank period.
void setScreenOn(void)
Enable screen display.
void snesmodSetSoundbank(u8 bank)
Set the soundbank bank number.
void snesmodInit(void)
Initialize SNESMOD audio engine.
void snesmodPlay(u8 startPosition)
Start module playback.
void snesmodLoadModule(u16 moduleId)
Load a module from the soundbank.
void snesmodProcess(void)
Process audio commands.
SNESMOD - Tracker-based Audio Engine.
Sound Effects
#include "soundbank.h"
void init_audio(void) {
}
void play_jump_sound(void) {
}
void play_coin_sound(void) {
}
#define SNESMOD_PITCH_NORMAL
Definition snesmod.h:331
#define SNESMOD_PITCH_HIGH
Definition snesmod.h:332
u8 snesmodLoadEffect(u16 sfxIndex)
Load a sound effect from the soundbank.
u8 snesmodPlayEffect(u16 effectId, u8 volume, u8 pan, u16 pitch)
Play a sound effect.
Volume Control
void snesmodStop(void)
Stop module playback.
void snesmodPause(void)
Pause module playback.
void snesmodResume(void)
Resume module playback.
void snesmodSetModuleVolume(u8 volume)
Set module volume.
void snesmodFadeVolume(u8 targetVolume, u8 speed)
Fade module volume.
Creating Music with OpenMPT
- Download OpenMPT (free)
- Create new Impulse Tracker module
- Keep within SNES limits:
- Max 8 channels
- Total samples < 58KB
- 32kHz max sample rate
- Export as .it file
smconv Tool
# Convert music for soundbank
smconv -s -o soundbank -b 1 music.it effects.it
# Output files:
# - soundbank.asm (link with ROM)
# - soundbank.h (module/effect IDs)
# - soundbank.bnk (binary data)
Pitch Constants
#define SNESMOD_PITCH_LOW 4
#define SNESMOD_PITCH_NORMAL 8
#define SNESMOD_PITCH_HIGH 12
Important: Call snesmodProcess()!
You MUST call snesmodProcess() every frame! Failure to do so causes:
- Audio glitches and stuttering
- Command buffer overflow
- Desynchronization
Example: Music + SFX
#include "soundbank.h"
u16 pad, pad_prev = 0, pad_pressed;
while (1) {
pad_pressed = pad & ~pad_prev;
pad_prev = pad;
if (pad == 0xFFFF) pad_pressed = 0;
if (pad_pressed &
KEY_A) {
}
if (pad_pressed &
KEY_B) {
}
}
return 0;
}
#define REG_JOY1H
Joypad 1 data high (R)
Definition registers.h:328
#define REG_JOY1L
Joypad 1 data low (R)
Definition registers.h:325
#define REG_HVBJOY
H/V blank and joypad status (R)
Definition registers.h:301
unsigned short u16
16-bit unsigned integer (0 to 65535)
Definition types.h:52
Memory Usage
| Component | Size |
| SPC700 Driver | ~5.5KB |
| Sample Data | Up to ~58KB |
| Echo Buffer | ~4KB (at $D000-$FFFF) |
Total audio RAM: 64KB
Tips
- Keep samples small - Use lower sample rates for less important sounds
- Reuse samples - Same sample at different pitches for variety
- Test on hardware - Emulator timing may differ
- Use echo sparingly - Takes 4KB+ of audio RAM
Examples
examples/audio/snesmod_music/ - Music playback demo
examples/audio/snesmod_sfx/ - Sound effects demo
Next Steps