docs: record remaining verification checks for the audio render-hook

List the human/full-setup checks that producer-side capture can't prove on
its own: hooked audio over RPT end-to-end, the mix-format assumption for
streams that predate injection, and multi-stream games.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-19 14:58:39 +02:00
parent 365043c3da
commit 88db914914

View File

@@ -66,15 +66,34 @@ All phases below are implemented and verified.
- **Phase 2 — audio mirror. ✅** The host captures the game's audio by PID via
WASAPI process loopback and re-renders it on the default endpoint, so RPT
carries game audio to guests.
- **Audio render-hook (echo fix). ✅ (pending manual end-to-end)** The injected
hook intercepts the game's WASAPI render path (`IAudioRenderClient`), copies
the frames into a shared audio ring for the host to re-render, and releases the
game's buffer silenced — so the operator no longer hears the audio twice. The
host owns an enable flag and re-renders the game's format via `AUTOCONVERTPCM`;
if the hook doesn't publish a format in time it reverts to process loopback.
The Audio panel shows the active source and a render-stream-count debug table.
Validated in-process by `audio_hook_test`; the real-game pass is the remaining
manual step.
- **Audio render-hook (echo fix). ✅ (capture proven on a real game; full RPT
pass pending)** The injected hook intercepts the game's WASAPI render path
(`IAudioRenderClient`), copies the frames into a shared audio ring for the host
to re-render, and releases the game's buffer silenced — so the operator no
longer hears the audio twice. It hooks the render vtables *proactively* so a
game that's already playing when injected is still captured. The host owns an
enable flag and re-renders the game's format via `AUTOCONVERTPCM`; if the hook
doesn't publish a format in time it reverts to process loopback. The Audio panel
shows the active source and a render-stream-count debug table. Validated
in-process by `audio_hook_test` and against a real already-playing game
(Phantom Brave) with `coop_audio_probe`: the pre-existing render client is
detected and real, non-silent audio reaches the ring with zero overruns.
### Remaining verification
Producer-side capture is proven; these still need a human / full setup to confirm:
- **Hooked audio over RPT, end-to-end.** Run the host, inject, tick **Mirror game
audio**, and confirm **Source: Hooked (no echo)**, the game goes locally silent,
and a guest on Remote Play Together still hears it.
- **Format guess for non-mix-format games.** For a stream that already exists at
injection time the hook can't see the game's `Initialize`, so it assumes the
device **mix format**. Phantom Brave matched it exactly (48 kHz/2ch/float). A
game that initialized shared mode with a different format would come out
wrong-pitched/garbled and needs per-stream format detection — not yet handled.
- **Multi-stream games.** v1 captures only the first ("primary") render stream;
confirm the Audio panel's render-stream table makes a multi-stream game obvious
(secondary streams stay local until per-stream mixing is added).
## Roadmap