back the audio cap off to opt-in: 7-23 already fixed the complaint, and the cap is a governor
Correcting my own framing in7e57816. The dropout players actually reported was fixed on 2026-07-23 bya999e5c, and nobody has complained since. I read the leftover ACQUIRE FAILED lines in the night-5 logs as the same live bug and raised the ceiling by default. They are not the same bug. What is still in the logs is transient exhaustion, not a leak: the census sits at 45-60 live, spikes during a firefight, and drains straight back (226 -> 42), which is the priority steal loop working. A voice dropped in that window is competing with ~256 already sounding, so it is very likely sub-perceptual -- which is consistent with the thing nobody is reporting. And raising the cap is not free. The 256 ceiling doubles as a governor: the steal loop only steals when the incoming source outranks a running one, so a higher cap means many more voices mixing simultaneously, and with EFX reverb and the lowpass chains live that is real CPU -- spent precisely during heavy combat, when the frame budget is already tightest. I verified the ceiling moves. I never measured frame time under a real firefight, and a solo bench cannot produce one. Shipping that to testers tonight would be gambling their framerate against a complaint nobody is making. So the knob stays and the default does not move. BT_AUDIO_SOURCES=<n> raises it with no rebuild if dropouts are ever reported again -- measure frame time while you do. Unset reports `granted mono=255 stereo=1`, exactly what testers have been running. Keeping the diagnostic read-back either way, since it earned its keep: asking for 64 grants 240, because OpenAL Soft has a floor of its own, which is also why the NULL default lands on 256. A request is not a promise. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
7e57816d39
commit
1af2dfc769
+18
-14
@@ -16,21 +16,25 @@ on top of it. Full detail: `docs/PROGRESS_LOG.md §5b, §8`.
|
||||
## What WinTesla already did (do NOT rebuild)
|
||||
- **Renderer bypass: DONE** — `MUNGA_L4/L4D3D.cpp` + `DXUtils` replace libDPL / the IG board with
|
||||
Direct3D9. No `libdpl.lib` in the tree. (The early from-scratch D3D9 viewer was retired and removed.) [T1]
|
||||
- **Audio SOURCE BUDGET — dropouts in heavy combat, FIXED 2026-07-28** [T2]. Field report "audio
|
||||
cutting in and out toward the end of the match"; night-5 logs carried **2017 `ACQUIRE FAILED` lines in
|
||||
a single match, every one at `live=256`**. It is **NOT a leak** — the census sits at a healthy 45-60
|
||||
live, spikes during firefights, and drains straight back, so the engine's priority steal loop
|
||||
- **Audio SOURCE BUDGET — the dropout complaint was fixed 2026-07-23; the leftover is NOT the same
|
||||
bug** [T2, 2026-07-28]. **The reported bug is closed**: `a999e5c` (per-source delete instead of the
|
||||
spec-atomic bulk `alDeleteSources`) stopped the pool leaking, and there have been **no field
|
||||
complaints since**. Night-5 logs still show 2017 `ACQUIRE FAILED` lines in a match, all at
|
||||
`live=256` — but that is **transient exhaustion, not a leak**: the census sits at 45-60 live, spikes
|
||||
during firefights, and drains straight back (226→42), i.e. the engine's priority steal loop
|
||||
(`AudioSourceStop`/`SuspendMaintenance` → `ReleaseChannels` → `ReleaseSourceSet` →
|
||||
`alDeleteSources`) works. The cause: `L4AudioRenderer` called `alcCreateContext(device, NULL)` with
|
||||
**no attribute list**, so OpenAL Soft applied its DEFAULT budget of 256 mono sources — an OpenAL
|
||||
default, unrelated to the 1995 audio hardware. A busy match logs ~7200 explosions × 3
|
||||
`DPLIndependantEffect` voices each; while the pool is pinned every acquire fails and that sound is
|
||||
dropped outright. FIX: pass `ALC_MONO_SOURCES` (default **1024**, `BT_AUDIO_SOURCES` overrides) and
|
||||
**read back what was granted** — a request is not a promise. Measured: 1024→1024, 2048→2048, and
|
||||
64→**240** (OpenAL Soft's own floor, which is why the NULL default landed at 256). Observed bursts
|
||||
peaked at 226 against the old 256 cap, i.e. they were clipping the ceiling. Note the earlier
|
||||
2026-07-23 fix (`a999e5c`, per-source delete instead of the spec-atomic bulk `alDeleteSources`) was
|
||||
real and is still needed — it is what makes the pool drain; it just was not the ceiling problem.
|
||||
`alDeleteSources`) is working. A dropped voice there competes with ~256 already sounding, so it is
|
||||
very likely sub-perceptual — treat the log noise as a symptom to watch, **not** as the old bug.
|
||||
Mechanism if it ever does matter: `alcCreateContext(device, NULL)` passes no attribute list, so
|
||||
OpenAL Soft applies its DEFAULT 256 mono sources (an OpenAL default, unrelated to the 1995 audio
|
||||
hardware), while a busy match logs ~7200 explosions × 3 `DPLIndependantEffect` voices.
|
||||
⚠ **Raising the cap is deliberately OPT-IN (`BT_AUDIO_SOURCES=<n>`, no rebuild needed)** — the 256
|
||||
ceiling doubles as a **governor**. The steal loop only steals when the incoming source outranks a
|
||||
running one, so a higher cap means far more voices mixing at once, and with EFX reverb + lowpass
|
||||
chains live that is real CPU spent exactly during heavy combat. **Measure frame time before making
|
||||
it default.** Granted values measured: 1024→1024, 2048→2048, 64→**240** (OpenAL Soft's own floor,
|
||||
which is also why the NULL default lands on 256) — always read back what was granted, a request is
|
||||
not a promise.
|
||||
- **Audio: BACKEND now REAL + soundbank loaded; only game-triggering remains** [T2, updated
|
||||
2026-07-15]. OpenAL replaces the HMI "SOS" engine and the renderer→device→buffer→source→play chain
|
||||
IS all implemented (`L4AUDRND`/`L4AUDRES`/`L4AUDLVL`; `PatchLevelOfDetail::PlayNote` really calls
|
||||
|
||||
@@ -395,29 +395,51 @@ void
|
||||
// DPLIndependantEffect voices, and while the pool is pinned every new
|
||||
// acquire fails outright and that sound is silently dropped.
|
||||
//
|
||||
// Ask for a budget that fits the content. OpenAL Soft mixes in software,
|
||||
// so this costs mixing headroom, not hardware voices, and it clamps to what
|
||||
// it can honour -- hence the read-back below rather than an assumption.
|
||||
// BT_AUDIO_SOURCES overrides for A/B testing.
|
||||
ALCint monoWanted = 1024;
|
||||
// ⚠ OFF BY DEFAULT, DELIBERATELY. Raising the cap is NOT a free win, and
|
||||
// the reported dropout was already fixed on 2026-07-23 by a999e5c (the
|
||||
// atomic-delete leak) -- no field complaints since. What remains in the
|
||||
// night-5 logs is transient exhaustion at the peak of a firefight, where
|
||||
// a dropped voice competes with ~256 already sounding, so it is very
|
||||
// likely sub-perceptual. Against that: the 256 ceiling also acts as a
|
||||
// GOVERNOR. The steal loop only steals when the incoming source outranks
|
||||
// a running one, so a higher cap means many more voices mixing at once --
|
||||
// with EFX reverb + the lowpass chains live, that is real CPU, spent
|
||||
// exactly during heavy combat when the frame budget is tightest.
|
||||
//
|
||||
// So this stays opt-in: set BT_AUDIO_SOURCES=<n> to raise it (no rebuild
|
||||
// needed) if dropouts are ever reported again, and measure frame time
|
||||
// while you do. Unset = the shipped OpenAL Soft default, unchanged.
|
||||
ALCint monoWanted = 0;
|
||||
if (const char *sv = getenv("BT_AUDIO_SOURCES"))
|
||||
{
|
||||
int n = atoi(sv);
|
||||
if (n >= 64 && n <= 4096)
|
||||
monoWanted = n;
|
||||
}
|
||||
ALCint attrs[5];
|
||||
attrs[0] = ALC_MONO_SOURCES; attrs[1] = monoWanted;
|
||||
attrs[2] = ALC_STEREO_SOURCES; attrs[3] = 16;
|
||||
attrs[4] = 0;
|
||||
ALCcontext *context = alcCreateContext(device, attrs);
|
||||
ALCcontext *context;
|
||||
if (monoWanted > 0)
|
||||
{
|
||||
ALCint attrs[5];
|
||||
attrs[0] = ALC_MONO_SOURCES; attrs[1] = monoWanted;
|
||||
attrs[2] = ALC_STEREO_SOURCES; attrs[3] = 16;
|
||||
attrs[4] = 0;
|
||||
context = alcCreateContext(device, attrs);
|
||||
}
|
||||
else
|
||||
{
|
||||
context = alcCreateContext(device, NULL); // default budget (256)
|
||||
}
|
||||
alcMakeContextCurrent(context);
|
||||
// Report what the driver actually GRANTED -- a request is not a promise.
|
||||
// (Asking for 64 grants 240: OpenAL Soft has a floor of its own, which is
|
||||
// also why the NULL default lands on 256.)
|
||||
if (getenv("BT_AUDIO_LOG") || monoWanted > 0)
|
||||
{
|
||||
ALCint monoGot = 0, stereoGot = 0;
|
||||
alcGetIntegerv(device, ALC_MONO_SOURCES, 1, &monoGot);
|
||||
alcGetIntegerv(device, ALC_STEREO_SOURCES, 1, &stereoGot);
|
||||
DEBUG_STREAM << "[audio] source budget: requested mono=" << monoWanted
|
||||
DEBUG_STREAM << "[audio] source budget: requested mono="
|
||||
<< (monoWanted > 0 ? monoWanted : 0) << " (0 = driver default)"
|
||||
<< " granted mono=" << monoGot << " stereo=" << stereoGot
|
||||
<< std::endl << std::flush;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user