Capture every audio stream into its own ring and mix them on the host
Games with several concurrent WASAPI render streams (e.g. Spider-Man: Miles
Morales) only had their first ("primary") stream mirrored; the rest kept playing
locally and never reached the guest. Now the render-hook captures + silences EVERY
tracked stream into its own ring (coop_audio_<pid>[_<index>]), each published with
that stream's own detected format (Initialize when caught, else GetMixFormat -- the
per-stream format detection, now actually used per ring rather than only for the
primary). The host creates a ring per stream and mixes the same-format streams with
a soft clip (host/src/audio/audio_mix.hpp); streams whose format differs from the
primary are still silenced (no echo) but skipped from the mix (would need
resampling).
The single-stream case is byte-for-byte unchanged: when only one stream is active
the host passes it through without the mixer, so the common path has no overhead or
fidelity change.
Verified: new audio_mix_test covers the decode/sum/soft-clip/encode math (float32 +
int16); audio_hook_test (x64 + x86) still passes, guarding the primary
capture+silence path against regression; full build x64 + x86 clean; ctest x64
11/11, x86 3/3. Multi-stream mixing against a real multi-stream game needs a live
session to fully confirm.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -185,10 +185,18 @@ inline std::uint32_t audio_ring_pop(AudioRingHeader& h, void* dst, std::uint32_t
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// Build the per-pid audio ring name both sides agree on.
|
||||
inline std::wstring audio_ring_name(unsigned long target_pid)
|
||||
// Build the per-pid audio ring name both sides agree on. Stream 0 keeps the bare
|
||||
// coop_audio_<pid> name (backward compatible / the single-stream case); additional
|
||||
// streams append _<index> (coop_audio_<pid>_1, _2, ...). The host captures every
|
||||
// render stream into its own ring and mixes them.
|
||||
inline std::wstring audio_ring_name(unsigned long target_pid, unsigned index = 0)
|
||||
{
|
||||
return std::wstring(kAudioRingPrefix) + std::to_wstring(target_pid);
|
||||
std::wstring name = std::wstring(kAudioRingPrefix) + std::to_wstring(target_pid);
|
||||
if (index != 0)
|
||||
{
|
||||
name += L"_" + std::to_wstring(index);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
} // namespace coop
|
||||
|
||||
Reference in New Issue
Block a user