Sounds
All audio files live in the assets/sounds/ directory, organized into categorized subdirectories. All sound files use the .wav format. SDL2_mixer handles both short sound effects (Mix_Chunk via Mix_LoadWAV) and streaming music (Mix_Music via Mix_LoadMUS).
Currently Used Sounds
Player — assets/sounds/player/
| File |
Type |
GameState Field |
Description |
player_jump.wav |
Mix_Chunk |
gs->audio.jump |
Played on Space press when on_ground == 1 |
player_hit.wav |
Mix_Chunk |
gs->audio.hit |
Played when the player takes damage |
Collectibles — assets/sounds/collectibles/
| File |
Type |
GameState Field |
Description |
coin.wav |
Mix_Chunk |
gs->audio.coin |
Played when the player collects a coin |
Entities — assets/sounds/entities/
| File |
Type |
GameState Field |
Description |
bird.wav |
Mix_Chunk |
gs->audio.flap |
Played for bird enemy wing flap |
spider.wav |
Mix_Chunk |
gs->audio.spider_attack |
Played for spider enemy attack |
fish.wav |
Mix_Chunk |
gs->audio.dive |
Played for fish enemy dive |
Hazards — assets/sounds/hazards/
| File |
Type |
GameState Field |
Description |
axe_trap.wav |
Mix_Chunk |
gs->audio.axe |
Played for axe trap swing |
Surfaces — assets/sounds/surfaces/
| File |
Type |
GameState Field |
Description |
bouncepad.wav |
Mix_Chunk |
gs->audio.spring |
Played when the player lands on a bouncepad |
Screens — assets/sounds/screens/
| File |
Type |
GameState Field |
Description |
confirm_ui.wav |
Mix_Chunk |
menu->snd_confirm |
Played on menu confirmation |
Levels — assets/sounds/levels/
| File |
Type |
GameState Field |
Description |
water.wav |
Mix_Music |
gs->audio.music |
Background music for water-themed levels, loaded via Mix_LoadMUS (streaming) |
lava.wav |
Mix_Music |
gs->audio.music |
Background music for lava-themed levels, loaded via Mix_LoadMUS (streaming) |
winds.wav |
Mix_Music |
gs->audio.music |
Background music for wind-themed levels, loaded via Mix_LoadMUS (streaming) |
Unused Sounds
The following sounds are stored in assets/sounds/unused/ and are not loaded by the game. They are available as reserves for future use.
| File |
Description |
fireball.wav |
Projectile / fireball effect |
saw.wav |
Circular saw spinning |
Audio Configuration
SDL2_mixer is opened in main.c with:
Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048);
| Parameter |
Value |
Meaning |
| Frequency |
44100 Hz |
CD quality |
| Format |
MIX_DEFAULT_FORMAT |
16-bit signed samples |
| Channels |
2 |
Stereo |
| Chunk size |
2048 samples |
~46 ms buffer at 44100 Hz |
Sound Effects vs. Music
| Aspect |
Mix_Chunk (sound effects) |
Mix_Music (background music) |
| API |
Mix_LoadWAV, Mix_PlayChannel |
Mix_LoadMUS, Mix_PlayMusic |
| Loading |
Fully decoded into RAM |
Streamed from disk |
| Best for |
Short, triggered sounds |
Long looping tracks |
| Simultaneous |
Multiple channels |
One at a time |
| Volume |
Mix_VolumeChunk |
Mix_VolumeMusic |
All sound effects use Mix_LoadWAV and are fully loaded into memory. The background music tracks (water.wav, lava.wav, winds.wav) use Mix_LoadMUS which streams from disk, keeping memory usage low. Music is assigned per level via the TOML level definition’s music_path field.
Adding a New Sound Effect
- Place the
.wav file in the appropriate assets/sounds/<category>/ subdirectory.
- Add a
Mix_Chunk *<name> field to AudioResources in game.h.
- Load it in
game_init:
gs->audio.<name> = Mix_LoadWAV("assets/sounds/<category>/<name>.wav");
if (!gs->audio.<name>) {
fprintf(stderr, "Warning: failed to load <name>.wav: %s\n", Mix_GetError());
/* Non-fatal — game continues without this sound */
}
- Free it in
game_cleanup (before SDL_DestroyRenderer):
FREE_CHUNK(gs->audio.<name>);
- Play it wherever the event occurs:
if (gs->audio.<name>) Mix_PlayChannel(-1, gs->audio.<name>, 0);
The if guard is important: if the WAV fails to load for any reason, the game continues without crashing.
Adding a New Music Track
// Load (streaming — not fully decoded into RAM)
gs->audio.music = Mix_LoadMUS("assets/sounds/levels/new_track.wav");
if (!gs->audio.music) { /* handle error */ }
// Start (loop forever)
Mix_PlayMusic(gs->audio.music, -1);
// Volume (0-128)
Mix_VolumeMusic(64); // 50%
// Stop and free
Mix_HaltMusic();
Mix_FreeMusic(gs->audio.music);
gs->audio.music = NULL;
Mix_Music streams from disk; it does not load the entire file into RAM. This keeps memory usage low for large audio files.