Audio verify: distinguish a failed process-loopback from no-correlation

verify_stream_format ignored ProcessLoopbackCapture::start()'s bool. A failed
loopback activation then produced an empty ground-truth signal, so the result was
ok=false -- indistinguishable from "captured fine but the two paths didn't
correlate" -- after burning the whole measurement window capturing only the hook
side for nothing.

Now it checks start(): on failure it restores the ring tap, emits a clear
OutputDebugString diagnostic, and returns immediately (ok=false) instead of
wasting the window. The caller still falls back to the measured guess, but the
cause is now visible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-24 01:43:30 +02:00
parent 6bdee40219
commit 12c4fb8a07
2 changed files with 14 additions and 8 deletions

View File

@@ -114,8 +114,6 @@ From an in-depth review pass. Each item is fixed test-first (a failing test, the
as its own commit; "verify" items are confirmed real before any change, and dropped if not.
Robustness (verify, then fix if real):
- **Swallowed audio loopback `start()` failures** — surface a process-loopback activation failure
distinctly from "no correlation" in the verifier + loopback.
- **Permissive injector bitness gate** — `IsWow64Process2` failure is treated as 64-bit; fall back to
`IsWow64Process` instead of mis-injecting.
- **Ignored HRESULT/BOOL returns** — `CreateShaderResourceView`, `GetClientRect`/`ClientToScreen`,

View File

@@ -156,12 +156,20 @@ FormatVerification verify_stream_format(DWORD pid, AudioRingHeader* ring, unsign
std::vector<BYTE> loop_bytes;
ProcessLoopbackCapture loop;
const std::uint32_t loop_block = dev_wfx->nBlockAlign;
loop.start(pid, dev_wfx, [&](const BYTE* data, std::uint32_t frames, bool silent) {
if (!loop.start(pid, dev_wfx, [&](const BYTE* data, std::uint32_t frames, bool silent) {
if (!silent && data != nullptr)
{
loop_bytes.insert(loop_bytes.end(), data, data + static_cast<std::size_t>(frames) * loop_block);
}
});
}))
{
// Distinguish "couldn't activate process loopback" from "captured fine but didn't correlate":
// without the ground-truth post-mix path there's nothing to correlate against, so bail now
// (don't burn the window capturing only the hook side) and leave the diagnostic visible.
OutputDebugStringA("coop: verify_stream_format -- process-loopback activation failed; cannot verify format\n");
ring->verify_capture.store(0, std::memory_order_release);
return result;
}
// Pull the hook's pre-mix bytes out of the ring across the window.
std::vector<BYTE> hook_bytes;