Skip to content

feat: separate music and sound volumes - #14

Merged
LucasAntunesdeAlmeida merged 1 commit into
masterfrom
feat/volume-channels
Sep 29, 2026
Merged

LucasAntunesdeAlmeida merged 1 commit into
masterfrom
feat/volume-channels

Conversation

@LucasAntunesdeAlmeida

Copy link
Copy Markdown
Owner

What

  • g.MusicVolume(v float64): the music's own volume, 0..1 (default 1).
  • g.SoundVolume(v float64): the sound effects' own volume, 0..1 (default 1).
  • g.Volume(v) stays the master and scales both.
  • README cheat-sheet rows; horde README section.

Design

  • Multiplied with the master. A player's level is channel volume times master volume. A mute key (Volume(0)) still silences everything, and unmuting restores each channel where the settings menu left it, with no bookkeeping in the game.
  • Same contract as Volume. Clamped to 0..1, NaN counts as 0, callable any time. Volume and MusicVolume update the playing music at once; SoundVolume applies to sounds started afterwards (fire-and-forget effects already playing finish at their old volume, as with Volume).
  • Zero skips work. A sound whose level is 0 (either volume at 0) now returns before any work: no file read, no decode, no player (before, a muted sound still decoded and cached its PCM). Music still starts silently at level 0 so raising the volume brings it back in place, as before.
  • Storage. assets.Cache keeps the three volumes in one array indexed by an internal Channel (Master, Music, Sounds) under its existing mutex; Level(ch) computes the effective value. Internal only: the public API is the three setters. No getters, as with Volume: a game's settings screen owns its values (and persists them with g.Save).
  • Headless never touches audio, unchanged: the setters only store values there.

Proof

  • volume_test.go (no audio device): each setter's default 1 and clamping (0.5, -1, 2, 0, 1, NaN, +Inf); levels multiply (0.5 master x 0.4 music = 0.2, x 0.8 sounds = 0.4) and channels keep their value under a master change; muting sounds leaves the music; a windowed game's Sound on a missing file does nothing with SoundVolume(0) or Volume(0) and panics (tries to load) once audible, proving muted sounds do no work; headless games can call all three from OnUpdate.
  • examples/horde: the pause overlay gains "4 MUSIC 100%" and "5 SOUNDS 100%" (4/5 keys, LB/RB on a pad with pad prompts, or a click), cycling 100, 50, 0%; a new sound level plays a sample hit. M still mutes everything on top.
  • Driven over MCP headless: 4 cycles the music label 100, 50, 0% (holding the key does not repeat), RB and a click cycle the sounds, and the labels switch to LB/RB once a pad is used.
  • Local gate: gofmt, vet, staticcheck, tests, js/wasm vet + build.

g.MusicVolume(v) and g.SoundVolume(v) set each kind's own volume, 0 to
1 (the default), clamped like Volume (NaN counts as 0). g.Volume stays
the master: a player plays at its channel's volume times the master's,
so a mute key still silences everything and unmuting brings each
channel back where it was. MusicVolume and Volume apply to the playing
music at once; SoundVolume applies to every sound started afterwards,
like Volume does for effects.

The asset cache keeps the three volumes by channel (Master, Music,
Sounds) and computes a player's level from them. A sound whose level
is 0, from either volume, now returns before any work: no file read,
no decoding, no player. Music still starts silently when muted, so
raising the volume brings it back.

Horde proves it: the pause menu gains "4 MUSIC 100%" and "5 SOUNDS
100%" entries (LB and RB on a pad, with pad prompts, or a click) that
cycle each channel through 100, 50 and 0%, under the M master mute.
@LucasAntunesdeAlmeida
LucasAntunesdeAlmeida merged commit fc6195f into master Sep 29, 2026
1 check passed
@LucasAntunesdeAlmeida
LucasAntunesdeAlmeida deleted the feat/volume-channels branch September 29, 2026 12:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant