Audio render-hook M2: render hook + in-process self-test (concept proven)
Implements the WASAPI render-hook (hook/src/audio_hook.{hpp,cpp}) and an
in-process self-test that proves COM vtable discovery and GetBuffer/ReleaseBuffer
interception with no game and no second Steam account.
- audio_hook.cpp: anchors on IMMDevice::Activate (idx 3) off our own default
endpoint (shared vtable), then hooks IAudioClient::Initialize (3) /
GetService (14) and IAudioRenderClient::GetBuffer (3) / ReleaseBuffer (4) off
live game pointers. Copies primary-stream frames into the audio ring and
releases with AUDCLNT_BUFFERFLAGS_SILENT (+ memset belt-and-suspenders), only
while the host-owned capture_enabled flag is set. Stream counting runs always;
on a ring overrun it keeps playing locally rather than going silent.
- ipc_client.hpp: publish_audio_stream / note_audio_frames /
set_audio_streams_seen write the render-stream debug fields into HookStatus.
- tests/audio_hook_test.cpp: installs the hooks, renders a tone through WASAPI
in-process, and asserts exactly one stream, frames pushed to the ring, the
ring carries the non-silent tone, and the primary was silenced. PASS:
streams_seen=1, frames_captured=32640.
- plan doc: correct GetService vtable index 13 -> 14 (SetEventHandle is 13).
coop_hook DLL wiring + host consumer/fallback come next (M3).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -65,7 +65,7 @@ hooks):
|
||||
- **Everything else is hooked off the live pointers the game received** (no further
|
||||
assumptions), install-once guarded:
|
||||
- `Activate` hook → if IID is `IAudioClient`/`2`/`3`, hook `Initialize` (idx 3)
|
||||
and `GetService` (idx 13) on that object.
|
||||
and `GetService` (idx 14) on that object.
|
||||
- `Initialize` hook → capture the `WAVEFORMATEX` (rate / channels / bits / tag).
|
||||
Fallback for games using `IAudioClient3::InitializeSharedAudioStream`: read the
|
||||
format via the original `GetMixFormat` in the `GetService` hook.
|
||||
@@ -73,7 +73,8 @@ hooks):
|
||||
its `GetBuffer` (idx 3) and `ReleaseBuffer` (idx 4).
|
||||
|
||||
Vtable indices: `IMMDevice::Activate`=3; `IAudioClient::Initialize`=3,
|
||||
`GetService`=13; `IAudioRenderClient::GetBuffer`=3, `ReleaseBuffer`=4.
|
||||
`GetService`=14 (after `SetEventHandle`=13); `IAudioRenderClient::GetBuffer`=3,
|
||||
`ReleaseBuffer`=4.
|
||||
|
||||
The worker thread `CoInitializeEx(MTA)` for the lifetime of the DLL (needed for the
|
||||
enumerator instance); installs are retried on the existing 250 ms worker tick, like
|
||||
|
||||
Reference in New Issue
Block a user