TASK 25: master limiter on the live mix (2026-08-15, queued from the TRAX discussion) — the review confirmed two of the creator's three instincts were already satisfied (MediaFoundationReader streams from disk so file size needs no guard; the MusicPlayer 0.20 bed rides the same loopback gain as the game, so music is always exactly 20% of the desktop volume by construction) and found one real gap: AudioMixer.FillAndMix summed mic + loopback with no output ceiling, so hot gains could pass 0 dBFS and clip the AAC encode. New pure Services/Audio/MasterLimiter.cs: -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. Applied at the end of FillAndMix right before the pipe write. 3 unit tests (trim-to-ceiling, never-boost, recovery) + ONE integration test (MasterLimiter_CapsTheLiveMix_OnThePipe: a 0.95 loopback bed 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, TASKS.md TASK 25 record, HANDOFF.md shipped state. Build 0 warnings, 193 tests passing (189 + 4 new)

This commit is contained in:
2026-08-15 16:10:16 -07:00
parent 24f16b2cd9
commit 92f1471ab4
7 changed files with 201 additions and 9 deletions
+30 -2
View File
@@ -8,8 +8,16 @@
## Session state (last updated: 2026-08-15)
- **Branch:** `main`, tracking `origin/main`. Working tree: the **TASK 24 polish batch** + the **game
audio bar always-visible change** (below) are committed + pushed. Local branches
`social-bar`/`webcam-validation` untouched (no secrets).
audio bar always-visible change** + **TASK 25 (master limiter)** are committed + pushed. Local
branches `social-bar`/`webcam-validation` untouched (no secrets).
- **TASK 25 — MASTER LIMITER — COMMITTED + PUSHED 2026-08-15.** Queued from the TRAX discussion: the
live mix summed mic + loopback with no ceiling, so hot gains could pass 0 dBFS and clip the AAC
encode. New pure `Services/Audio/MasterLimiter.cs` (−1 dBFS ceiling, instant attack per frame,
smoothed release) applied at the end of `AudioMixer.FillAndMix`. ONE integration test
(`MasterLimiter_CapsTheLiveMix_OnThePipe`). The review also confirmed file size needs no guard
(`MediaFoundationReader` streams) and the music **0.20 cap is already relative by construction**
(music rides the same loopback gain as the game → always exactly 20% of the desktop volume). Build
**0 warnings**, full suite green.
- **GAME AUDIO BAR ALWAYS VISIBLE — COMMITTED + PUSHED 2026-08-15.** The TASK 4 show/hide gating was a
UX bug: the desktop/game meter kept vanishing whenever no full-screen game with sound was up (or no
TRAX music played). The whole `IGameAudioDetector`/`GameAudioDetector`/`GameAudioHysteresis` stack +
@@ -84,6 +92,26 @@ sound or TRAX played, so it sat hidden during normal use. Fix = the bar is now *
- **MainWindow.xaml:** dropped the `Visibility` binding on the preview-overlay game bar; it renders
unconditionally (TRAX button + "Desktop Audio" label + meter + mute + volume unchanged).
## TASK 25 — master limiter 2026-08-15 (what changed)
Came out of the TRAX discussion (file-size guard? 20% cap? sound-event balance?). Verdict: two of the
three instincts were already satisfied, one real gap existed:
- **No file-size guard needed** — `MediaFoundationReader` streams from disk; memory is flat (~a few MB)
whatever the file size.
- **The 0.20 music cap is relative by construction** — music rides the same loopback gain as the game,
so music:game is always exactly 0.20:1 at any slider position; it cannot rise above 20% of the
current desktop volume. (Per-channel hierarchy: voice on top via the ducker −12 dB, then game, then
music at 20%.)
- **The gap:** `FillAndMix` summed mic + loopback with no ceiling — hot gains could pass 0 dBFS and
clip the AAC encode.
- **Fix:** new pure `Services/Audio/MasterLimiter.cs` — **−1 dBFS ceiling** (`Ceiling = 0.891`),
**instant attack per frame** (hot frames scaled exactly to the ceiling, no overshoot), **smoothed
release** toward unity (no pumping); gain never exceeds 1. Applied at the end of `AudioMixer.FillAndMix`.
- **ONE integration test:** `MasterLimiter_CapsTheLiveMix_OnThePipe` — real mixer + pipe harness, a
0.95 loopback bed capped to exactly 0.891 on the wire while staying audible. Plus 3 unit tests for
the pure math.
## TASK 9 audio milestone — SHIPPED 2026-08-14 (what changed)
The creator's feature review settled this as the single next branch ("all the audio issues done and