D322: prefer DirectSound over SDL2's WASAPI backend on Windows

Four simultaneous drain monitors on the same USB interface: WASAPI (512 and
2048 samples) fell to 81-88% drain for ~30-50 s every ~317 s and lost 1.4% of
playback, while DirectSound stayed at exact real time. Each WASAPI shortfall
overflowed the audio queue and dropped blocks (the periodic garbled bursts).
audioInit() now hints directsound,wasapi; SDL_AUDIODRIVER still overrides.
Golden gate 3/3; 60 s GE_D204 run clean after load.
This commit is contained in:
James Dansereau committed 2026-09-25 22:25:13 -04:00
1 parent 2a20a93318
commit edddf87429
4 files changed
+33 -4

No files matched your search

+14 -1
View File
@@ -608,7 +608,7 @@ covers D24–D69; the log continues in §H (D32 procedure, D70–D121).
| D319 | **Frame cap slider was mostly a dead zone; replaced with a plain 30/60 toggle (user ask, 2026-09-18).** — full `## D319` entry at file tail | FIXED — new `ROW_FPSCAP` cycle (30/60 only) in `port/src/optionsoverlay.c`; default changed to 60 in `port/src/video.c`. Root cause was D186 (sim tick ceiling + low-cap guard); this just fixes the menu's exposure of it. Build-verified; interactive confirmation owed. |
| D320 | **D318-class sweep: aim-hold → `_update` AI lists in 8 levels carry the same as-authored softlock race (static analysis, 2026-09-20).** — full `## D320` entry at file tail | OPEN — re-classified 2026-09-23 by D329 (tick-granularity divergence at 1 tick/frame, not a platform-invariant lock); fix decision pending, watchdog stays shipped. Earlier resolution text kept in the full entry. |
| D321 | **D318 trigger chain fully mapped: tanks → combat bit is an authored ~3.5 s gas-cascade delay (chr 254 script); derail lands same-tick; PC behavior confirmed faithful to N64 (probe captures, 2026-09-20).** — full `## D321` entry at file tail | OPEN — re-classified 2026-09-23 by D329 (tick-granularity divergence at 1 tick/frame, not a platform-invariant lock); fix decision pending, watchdog stays shipped. Earlier resolution text kept in the full entry. |
| D322 | **Long-session audio degradation: full campaign on v0.3.0 — audio progressively worsens from Silo, by Caverns/Cradle the OST is inaudible and SFX "come and go"; restarting the game restores it (issue #87, user report, 2026-09-20).** — full `## D322` entry at file tail | OPEN — 2026-09-25: pools healthy (voice-leak hypothesis REFUTED). The maintainer-machine "garbled" bursts (periodic SDL queue overflow, ~314 s) are the HOST AUDIO DEVICE, not the port: a no-game SDL drain monitor (`tools_pc/sdl_drain_monitor.c`) shows the Focusrite USB interface draining at 88–95 % for ~15 s every ~312 s. Remaining port-side item: SFX drop-outs in firefights = 8-voice soft cap (D207/D241). #87's progressive campaign-long decay is not reproduced here. |
| D322 | **Long-session audio degradation: full campaign on v0.3.0 — audio progressively worsens from Silo, by Caverns/Cradle the OST is inaudible and SFX "come and go"; restarting the game restores it (issue #87, user report, 2026-09-20).** — full `## D322` entry at file tail | FIXED (Windows) for the periodic "garbled" bursts — root cause SDL2's WASAPI backend, not the device: side-by-side monitor runs on the same USB interface show WASAPI draining 81–88 % for ~30–50 s every ~317 s (1.4 % playback lost overall) while DirectSound stays at exact real time. `port/src/audio.c` now prefers `directsound,wasapi` (SDL_AUDIODRIVER env still overrides). Remaining: SFX drop-outs in firefights, if still heard after this fix (8-voice cap, D207/D241); #87 progressive decay not reproduced here. |
| D323 | **G_TL_LOD bindings of explicit-LOD textures: PC samples driver mips from LOD0, N64 samples the authored mip chain (static census, 2026-09-21).** — full `## D323` entry at file tail | OPEN / parked — mechanism confirmed in code; census (`tools_pc/bg_lod_audit.py`) shows 15 levels with explicit-LOD textures bound under TEXTLOD-on classes (stat 378, azt 806 binds heaviest); overwhelmingly CI8/IA8 (subtle), the only RGBA5551 cut-outs are the D236 set (already fixed). No reported artifact; fix path documented (upload GL mip chains for TEXTLOD-on bindings) but not worth doing speculatively. Also documents GE's OMH field-write encoding (op 0xBA, value at absolute bit position in w1). |
| D324 | **GE's <stdlib.h> stub declares nothing, so TUs that include it get NO CRT prototypes — implicit `int f()` declarations silently corrupt non-int returns: `atof` garbage in every float ini parse (D38 class).** — full `## D324` entry at file tail | FIXED (2026-09-22) — proven impact: `Game.ScreenShakeIntensity` (the only float ini option) silently parsed to garbage whenever a user set it; caught via the D294 `GE_ROOMPOOL` hook. Fix: `port/shim/stdlib.h` now declares atof/strtod/strtol/atexit/getenv unconditionally (K&R form); pc_protos.h gains atof/strtod for game TUs; glass2.c PORT block uses `__builtin_memset`. Residual harmless implicit decls (atoi/floorf/sqrtf/memset builtins, lround) documented. |
| D325 | **ROM-mod (xdelta) compatibility: relocating/total-conversion mods cannot work while the file table is compiled in; in-place data-only mods are one sidecar-staleness fix away (Goldfinger 64 probe, 2026-09-22).** — full `## D325` entry at file tail | CLOSED as a question — mechanism measured (GF64 relocates 797/803 vanilla file slices; 12→24 MB expanded ROM; `d43_emit` dies on a vanilla-offset zlib slice). ASM mods never work; relocating mods need a runtime-parsed file table (rule-2 collision for added levels); in-place data-only mods need only a ROM-identity stamp in `manifest.csv` (`port/src/romconvert.c`). |
@@ -12709,6 +12709,19 @@ Full campaign (or at minimum Silo → Caverns/Cradle) with **`GE_D322=1 GE_D204=
- **Port impact:** none to fix for this mechanism. A bigger `Audio.QueueLimit` would only trade drops for up to ~2 s of latency during a dip. Suggested user-side checks: Focusrite Control sample rate = the Windows device format; driver update; A/B on onboard audio.
- **Still open under D322:** (a) the 8-voice SFX cap starving gunshots in firefights (D207/D241, N64-configured cap: is it faithful to the N64's audible behaviour?); (b) #87's own report of *progressive* campaign-long decay, which this machine does not show. The reporter's hardware may have its own periodic device dips; the monitor tool is the first thing to run there.
**2026-09-25 (fix): it is SDL's WASAPI backend, not the device. Correction to the entry above.** Four copies of the monitor ran simultaneously on the same Focusrite for 700 s (WASAPI and DirectSound, 512 and 2048 samples each):
| backend | buffer | dips (5 s mean) | long-run drain |
|---|---|---|---|
| WASAPI | 512 | 236–269 s (88 %), 553–605 s (82 %) | 21,730 f/s |
| WASAPI | 2048 | same windows (81–88 %) | 21,733 f/s |
| DirectSound | 512 | none | 22,048.5 f/s |
| DirectSound | 2048 | none | 22,048.5 f/s |
The same device at the same moment drains at exactly real time through DirectSound, so the periodic shortfall is SDL 2.32's WASAPI path with this USB interface. Buffer size makes no difference. The earlier "host device, nothing to fix" conclusion is withdrawn.
**Fix:** `audioInit()` sets `SDL_HINT_AUDIODRIVER = "directsound,wasapi"` on Windows before `SDL_InitSubSystem(SDL_INIT_AUDIO)` (the only audio init in the port); `SDL_AUDIODRIVER` in the environment still overrides it (normal-priority hint). The init log line now names the driver. **Verified:** golden gate 3/3; Bunker 1 60 s with `GE_D204=1`: driver `directsound`, rt 0.997–0.999, q 240–624, one drop during the level load (pre-existing) and none after. **Owed:** a long play session on the maintainer's machine (the bursts came every ~5 min), expect `drop=` flat after the load. Then re-assess the firefight SFX drop-outs; D207's measurements found no sounds actually dropped by the 8-voice cap, so they were most likely this same block loss.
## D323 — G_TL_LOD bindings of explicit-LOD textures: PC samples driver mips from LOD0; N64 samples the authored mip chain (static census, 2026-09-21)
**Context.** D107 established that GE's room DLs emit `G_TL_LOD` and that the port folds every LOD draw to tile 0 (driver-generated GL mips from the finest level). D236 then found + fixed the one case where that folding was *visibly* wrong for a type-1 (DETAIL) binding of an RGBA5551 cut-out. This entry closes the loop on the rest of the surface: how often do LOD-on draw classes bind textures that actually carry **authored** mip levels, and does the N64 hardware behavior differ from the port's?