Audio: show echo state honestly for guessed hooked streams

Since guessed streams are now captured-but-not-silenced (the over-write fix),
the hooked path is only no-echo for an exact/override format. The panel
inferred "Hooked (no echo)" unconditionally, which was misleading. Show
"Hooked (echo -- guessed format)" (amber) for a guessed primary stream and
"Hooked (no echo)" (green) only for exact/override; drop the unconditional
"no echo" from source_name() and the mirror status string.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 05:34:40 +02:00
parent e608c6fb38
commit 5796d5af39
3 changed files with 16 additions and 3 deletions

View File

@@ -496,7 +496,7 @@ AudioMirror::HookedResult AudioMirror::run_hooked(AudioRingHeader* const* rings)
} }
char st[96]; char st[96];
std::snprintf(st, sizeof(st), "Mirroring (hooked, no echo): %u Hz %u ch %u-bit", rate, channels, bits); std::snprintf(st, sizeof(st), "Mirroring (hooked): %u Hz %u ch %u-bit", rate, channels, bits);
set_status(st); set_status(st);
source_.store(Source::Hooked, std::memory_order_relaxed); source_.store(Source::Hooked, std::memory_order_relaxed);
running_.store(true, std::memory_order_release); running_.store(true, std::memory_order_release);

View File

@@ -86,7 +86,7 @@ public:
switch (source()) switch (source())
{ {
case Source::Hooked: case Source::Hooked:
return "Hooked (no echo)"; return "Hooked"; // echo depends on the format provenance; the panel shows it
case Source::Loopback: case Source::Loopback:
return "Loopback (echo)"; return "Loopback (echo)";
default: default:

View File

@@ -213,7 +213,20 @@ void AudioPanel::draw_ui(const HookStatusView& status, bool debug_details)
ImGui::TextColored(kGreen, "Mirroring %u Hz, %u ch", mirror_.sample_rate(), mirror_.channels()); ImGui::TextColored(kGreen, "Mirroring %u Hz, %u ch", mirror_.sample_rate(), mirror_.channels());
ImGui::Text("Source:"); ImGui::Text("Source:");
ImGui::SameLine(); ImGui::SameLine();
ImGui::TextColored(hooked ? kGreen : kAmber, "%s", mirror_.source_name()); if (hooked)
{
// The hooked path only silences (no echo) an EXACT / override format, whose frame
// size is known. A guessed stream is captured but not silenced (silencing a guessed
// buffer could over-write it), so the game stays audible -- an echo. Make that clear.
const std::uint32_t st = status.audio_streams[0].format_state;
const bool no_echo = (st == AudioFormat_Exact || st == AudioFormat_Override);
ImGui::TextColored(no_echo ? kGreen : kAmber, "Hooked (%s)",
no_echo ? "no echo" : "echo -- guessed format");
}
else
{
ImGui::TextColored(kAmber, "%s", mirror_.source_name());
}
// Where the rendered format came from -- so it's clear the playback pitch is right. // Where the rendered format came from -- so it's clear the playback pitch is right.
// Hooked: the primary stream's provenance (exact / measured). Loopback: the audio is // Hooked: the primary stream's provenance (exact / measured). Loopback: the audio is