Builder Manual Play
Builder Manual / Sounds

AUDIO / Sounds

Sounds

Audio files, categories, naming rules, and game sound reference.

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/

FileTypeGameState FieldDescription
player_jump.wavMix_Chunkgs->audio.jumpPlayed on Space press when on_ground == 1
player_hit.wavMix_Chunkgs->audio.hitPlayed when the player takes damage

Collectibles — assets/sounds/collectibles/

FileTypeGameState FieldDescription
coin.wavMix_Chunkgs->audio.coinPlayed when the player collects a coin

Entities — assets/sounds/entities/

FileTypeGameState FieldDescription
bird.wavMix_Chunkgs->audio.flapPlayed for bird enemy wing flap
spider.wavMix_Chunkgs->audio.spider_attackPlayed for spider enemy attack
fish.wavMix_Chunkgs->audio.divePlayed for fish enemy dive

Hazards — assets/sounds/hazards/

FileTypeGameState FieldDescription
axe_trap.wavMix_Chunkgs->audio.axePlayed for axe trap swing

Surfaces — assets/sounds/surfaces/

FileTypeGameState FieldDescription
bouncepad.wavMix_Chunkgs->audio.springPlayed when the player lands on a bouncepad

Screens — assets/sounds/screens/

FileTypeGameState FieldDescription
confirm_ui.wavMix_Chunkmenu->snd_confirmPlayed on menu confirmation

Levels — assets/sounds/levels/

FileTypeGameState FieldDescription
water.wavMix_Musicgs->audio.musicBackground music for water-themed levels, loaded via Mix_LoadMUS (streaming)
lava.wavMix_Musicgs->audio.musicBackground music for lava-themed levels, loaded via Mix_LoadMUS (streaming)
winds.wavMix_Musicgs->audio.musicBackground 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.

FileDescription
fireball.wavProjectile / fireball effect
saw.wavCircular saw spinning

Audio Configuration

SDL2_mixer is opened in main.c with:

Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048);
ParameterValueMeaning
Frequency44100 HzCD quality
FormatMIX_DEFAULT_FORMAT16-bit signed samples
Channels2Stereo
Chunk size2048 samples~46 ms buffer at 44100 Hz

Sound Effects vs. Music

AspectMix_Chunk (sound effects)Mix_Music (background music)
APIMix_LoadWAV, Mix_PlayChannelMix_LoadMUS, Mix_PlayMusic
LoadingFully decoded into RAMStreamed from disk
Best forShort, triggered soundsLong looping tracks
SimultaneousMultiple channelsOne at a time
VolumeMix_VolumeChunkMix_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

  1. Place the .wav file in the appropriate assets/sounds/<category>/ subdirectory.
  2. Add a Mix_Chunk *<name> field to AudioResources in game.h.
  3. 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 */
}
  1. Free it in game_cleanup (before SDL_DestroyRenderer):
FREE_CHUNK(gs->audio.<name>);
  1. 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.