feat(audio): Ctrl+M instant mute + inn-chatter investigation closed as server content

Two items from listening-gate round 2.

Mute: AcdreamToggleAudioMute (default Ctrl+M; bare M is selection) flips
OpenAlAudioEngine.Muted, implemented as the AL LISTENER gain - unused
since A2 moved all mixing to the CPU, so it is a free master switch that
silences already-playing voices instantly and restores them exactly,
without touching the retail mixing math, the -50 dB allocation cutoff, or
any persisted volume setting. Rebindable like every other action; console
line confirms each flip.

Inn chatter: the user hears talk-and-laughter ambience in retail inns and
not in acdream. Three installed-dat scans (pinned as conformance tests in
EnvCellSoundEmitterInventoryTests) prove the mechanism is NOT client
data: no interior static in the town landblock carries an ambient-slot
sound table, no Setup among all 5,935 in the portal dat references one,
and yet 23 sound tables carrying ONLY Ambient1..8 slots exist - pure
soundscape banks with nothing client-side pointing at them. They are
wire-bound: the server attaches one to an emitter object via
CreateObject's sound-table field and fires the slots over 0xF750 - ACE
implements exactly this (EmoteType.Sound heartbeat emotes ->
GameMessageSound broadcast). Our 0xF750 receiver (slice A3) is live and
now instrumented (ACDREAM_PROBE_SOUND_WIRE=1, via the new
AudioDiagnostics owner per Code Structure Rule 5, with per-event drop
reasons in AudioHookSink.PlayServerSound). A probed session against the
local ACE received ZERO 0xF750 events across a town walkabout: the
silence is server world-content (no emitters configured/firing), not a
client drop. The first scan's assertion originally encoded the
emitter-object hypothesis; the data refuted it, and the test now pins the
negative so the conclusion cannot silently rot.

Full Release suite green (the one failure during development was the
hypothesis-pinning assertion, corrected to pin the finding).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-09 14:09:24 +02:00
parent e5ade796ac
commit 2cf94dbcd2
10 changed files with 339 additions and 5 deletions

View file

@ -151,6 +151,7 @@ internal sealed class GameplayInputCommandController : IGameplayInputCommandTarg
private readonly IGameRuntimeView _runtimeView;
private readonly IRuntimeCombatCommands _combat;
private readonly IGameplayWindowCommands _window;
private readonly Action? _toggleAudioMute;
public GameplayInputCommandController(
IRetainedGameplayWindowCommands retained,
@ -161,7 +162,8 @@ internal sealed class GameplayInputCommandController : IGameplayInputCommandTarg
IGameplayCameraModeCommands camera,
IGameRuntimeView runtimeView,
IRuntimeCombatCommands combat,
IGameplayWindowCommands window)
IGameplayWindowCommands window,
Action? toggleAudioMute = null)
{
_retained = retained ?? throw new ArgumentNullException(nameof(retained));
_devTools = devTools ?? throw new ArgumentNullException(nameof(devTools));
@ -173,6 +175,7 @@ internal sealed class GameplayInputCommandController : IGameplayInputCommandTarg
?? throw new ArgumentNullException(nameof(runtimeView));
_combat = combat ?? throw new ArgumentNullException(nameof(combat));
_window = window ?? throw new ArgumentNullException(nameof(window));
_toggleAudioMute = toggleAudioMute;
}
public bool Handle(InputAction action)
@ -185,6 +188,9 @@ internal sealed class GameplayInputCommandController : IGameplayInputCommandTarg
case InputAction.ToggleInventoryPanel:
_retained.ToggleInventory();
return true;
case InputAction.AcdreamToggleAudioMute:
_toggleAudioMute?.Invoke();
return true;
case InputAction.AcdreamToggleDebugPanel:
_devTools.ToggleDebugPanel();
return true;