feat(audio): per-stream mix controls in Windows client + vc_get_remote_stream getter

PerUserTuningDialog previously broadcast one gain/mute/NR set to *all* of a
user's streams, even though the core mixer (AudioEngine::RemoteStream) and
the C ABI (vc_set_remote_stream) were already per-stream. The UI had no
per-mix controls anywhere.

Reworks the dialog to enumerate ListUserStreams on open and render one row
per stream (kind + label + Gain + Mute + NR), each wiring only to its own
stream_id. Adds a read-back ABI counterpart, vc_get_remote_stream, so the
dialog opens at the listener's actual current per-stream settings (defaults
1.0/unmuted/NR-off) rather than always 100%. Additive ABI change only; no
existing symbols touched.

Tests: test_m3_multistream extended with getter round-trip assertions; new
C# smoke test exercises the full P/Invoke marshaling path with two clients.
Docs: voice.md §10 notes the getter. NR checkbox keeps its honest
'passthrough' label (NS DSP still unbuilt per §8).
This commit is contained in:
2026-06-18 02:06:44 +02:00
parent 1dfe3c95ed
commit d397731db9
15 changed files with 402 additions and 82 deletions

View File

@@ -123,6 +123,12 @@ vc_result vc_set_remote_stream(vc_client* c, uint32_t user_id, uint32_t stream_i
return c->set_remote_stream(user_id, stream_id, gain, muted != 0, noise_reduction != 0);
}
vc_result vc_get_remote_stream(vc_client* c, uint32_t user_id, uint32_t stream_id,
vc_remote_stream_state* out) {
if (c == nullptr) return VC_ERR_INVALID_ARG;
return c->get_remote_stream(user_id, stream_id, out);
}
vc_result vc_get_stream_audio_config(vc_client* c, uint32_t user_id, uint32_t stream_id,
vc_audio_config* out) {
if (c == nullptr || out == nullptr) return VC_ERR_INVALID_ARG;