87509bcf99
TASKS.md is now the index (status table, open items, research pointer). 33 files: 32 task files + 1 research facts file. The full take-saga narrative and all design decisions are preserved verbatim; the catalog makes the queue readable without opening every task body. Schema and AGENTS.md updated to reflect the new layout.
2.0 KiB
2.0 KiB
TASK 12 — Master limiter on the live mix (2026-08-15)
Catalog:
TASKS.md— status and requirements live here.
Queued by the creator during the TRAX discussion: "should the soundtrack be limited to avoid squandering resources / should it cap at 20% / how do the three sound events balance?" Review conclusions (all three instincts checked out, only ONE real gap):
- File size — no guard needed.
MusicPlayerusesMediaFoundationReader, which streams from disk (progressive source): memory is flat (~a few MB) regardless of file size; CPU negligible. - 20% cap — already enforced by construction.
MusicPlayer.MusicVolume = 0.20f+ music rides the SAME WASAPI loopback (and therefore the same gain) as game audio, so music:game is always exactly 0.20:1 at any slider position — it literally cannot rise above 20% of the current desktop volume. - The gap:
AudioMixer.FillAndMixsummed mic + loopback with no output ceiling — mic 100% + loud game/music could pass 0 dBFS and clip the AAC encode.
Shipped:
- ✅
Services/Audio/MasterLimiter.cs(pure, unit-tested) — a −1 dBFS ceiling (Ceiling = 0.891), instant attack per frame (a hot frame is scaled exactly to the ceiling — no overshoot), smoothed release toward unity so loud passages don't pump; gain never exceeds 1 (no boosting). Applied at the end ofAudioMixer.FillAndMix, right before the pipe write. - ✅ Unit tests — over-ceiling frames trimmed to ≤ ceiling; sub-ceiling frames never boosted; gain recovers to unity after the loud frame ends.
- ✅ ONE integration test (
MasterLimiter_CapsTheLiveMix_OnThePipe) — real mixer + pipe harness: a 0.95 loopback bed (hotter than the ceiling) is capped to exactly 0.891 on the wire while staying audible. - ✅ Docs in the same commit —
ai.md(go-live audio section),Services/index.md(new row).
No changes to MusicPlayer, the 0.20 cap, the ducker, or the meter zones. Build 0 warnings.