Skip to content

Apply perceptual curve to volume sliders#4272

Merged
evanpelle merged 1 commit into
mainfrom
sound
Jun 14, 2026
Merged

Apply perceptual curve to volume sliders#4272
evanpelle merged 1 commit into
mainfrom
sound

Conversation

@evanpelle

Copy link
Copy Markdown
Collaborator

Problem

Players reported having to turn the volume slider down to ~20% before noticing any change in loudness.

The sliders fed their linear 0–1 position straight to Howler's volume(), which is linear amplitude gain. Human loudness perception is roughly logarithmic, so the top ~80% of the slider all sounds nearly identical — the classic linear-fader problem.

Fix

Square the slider position into a perceptual (audio-taper) gain inside SoundManager. The stored setting and the displayed % remain the intuitive linear slider position; only the gain handed to Howler is curved.

Slider Old gain (linear) New gain (x²)
100% 1.00 1.00
90% 0.90 0.81
80% 0.80 0.64
50% 0.50 0.25
20% 0.20 0.04

Lowering the slider from 100→80 now produces an audible drop instead of nothing until ~20%.

Notes

  • Quadratic (x²) was chosen as a balanced, conservative taper. Cubic (x³) would make the top-end drop-off even more immediate if preferred.
  • Existing saved settings are unaffected; the same slider position will simply sound slightly quieter, which is the intended correction.

Tests

Updated SoundManager.test.ts to assert the curved gain and added a dedicated test locking in the top-of-range behavior. All 18 tests pass.

The volume sliders fed their linear 0-1 position straight to Howler as
linear amplitude gain. Because perceived loudness is roughly logarithmic,
the top ~80% of the slider sounded nearly identical and users had to drop
to ~20% before noticing any change.

Square the slider position into a perceptual gain in SoundManager so
reductions near the top of the range are audible. The stored setting and
displayed percentage remain the intuitive linear slider position.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6c25de24-3cb6-4b1d-9136-3f27da242005

📥 Commits

Reviewing files that changed from the base of the PR and between 8b9bda1 and 0de077f.

📒 Files selected for processing (2)
  • src/client/sound/SoundManager.ts
  • tests/client/sound/SoundManager.test.ts

Walkthrough

SoundManager gains a private perceptualGain(position) helper that clamps a slider value to [0, 1] and squares it. Both setBackgroundMusicVolume and setSoundEffectsVolume now use this helper instead of direct linear clamping. Tests update all volume assertions to expect squared values and add one new test for the 0.9 input case.

Changes

Perceptual gain curve for volume controls

Layer / File(s) Summary
perceptualGain helper and volume setters
src/client/sound/SoundManager.ts
Adds private perceptualGain(position) (clamp then square); both setBackgroundMusicVolume and setSoundEffectsVolume now store volume through this helper before updating Howler tracks.
Test assertions updated for squared gain
tests/client/sound/SoundManager.test.ts
Updates four existing volume assertions (background music bootstrap, lazy SFX load, SetBackgroundMusicVolumeEvent, SetSoundEffectsVolumeEvent) to expect squared values; adds one new test verifying 0.9 input produces 0.81.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🎵 The slider moves smooth, from zero to one,
But linearly loud was never much fun.
We square up the signal, a gentle taper,
Soft sounds stay soft — like delicate paper.
v * v is the law of the land,
Perceptual curves, just as ears had planned! 🎶

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and clearly describes the main change: applying a perceptual curve to volume sliders, which matches the core objective of the PR.
Description check ✅ Passed The description comprehensively explains the problem, solution, implementation details, and testing, all directly related to the volume curve changes in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed due to a network error.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@evanpelle evanpelle added this to the v32 milestone Jun 14, 2026
@evanpelle evanpelle merged commit bb5e7dc into main Jun 14, 2026
14 of 18 checks passed
@evanpelle evanpelle deleted the sound branch June 14, 2026 16:12
@github-project-automation github-project-automation Bot moved this from Triage to Complete in OpenFront Release Management Jun 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Complete

Development

Successfully merging this pull request may close these issues.

1 participant