fix(ios): stereo mic + A2DP output, add vc_audio_restart ABI
Diagnosed by comparing against TeamTalk5 (Client/iTeamTalk), which achieves stereo mic + A2DP output. Five fixes: 1. configureStereoCapture now calls setPreferredInput + setInputDataSource (mirroring TeamTalk5's SoundDevicesModel). Previously omitted based on incorrect diagnosis that setPreferredInput collapsed A2DP — the real culprit was setPreferredInputNumberOfChannels(2), which neither project uses. 2. New C ABI: vc_audio_restart (full stop + re-init, unlike suspend/resume which only stop/start). Swift wrapper added. The withAudioSuspend wrapper that used it was removed after on-device testing showed it killed all audio (including VoiceOver) when switching presets — the core's set_capture_channels handles engine restart internally. 3. Bluetooth options: Voice Chat preset now includes BOTH .allowBluetoothHFP AND .allowBluetoothA2DP (matching TeamTalk5's UtilSound.swift:228). Previously HFP-only blocked A2DP headphones. 4. Capture channels now reset when switching stereo→mono via selectCaptureChannels/applyPreset. AudioSessionManager tracks activeMicStreamId (set by SessionState on join/leave voice). 5. Docs synced: voice.md, tech-stack.md, architecture.md, PROGRESS.md. Removed stale setPreferredInputNumberOfChannels(2) references. Verified: ctest --preset dev 21/21 green, iOS client builds. Stereo mic + A2DP output still needs on-device debugging — the core recipe is correct but iOS 26 route behavior requires hands-on testing with a debugger.
This commit is contained in:
@@ -399,11 +399,12 @@ VC_API vc_result vc_test_inject_capture(vc_client* c, uint32_t stream_id, const
|
||||
/* Set the capture channel count for a local MIC stream (1 = mono, 2 = stereo interleaved).
|
||||
* Must be called after vc_stream_start; takes effect on the next AudioEngine restart (e.g. when
|
||||
* joining voice, or immediately if the engine is already running — it stops and restarts the
|
||||
* capture device with the new channel count). Defaults to 1 (mono). On iOS this lets the Swift
|
||||
* AVAudioSession routing layer request stereo built-in mic capture via
|
||||
* setPreferredInputNumberOfChannels(2) and then tell the core to open the capture device in
|
||||
* stereo. VC_ERR_INVALID_ARG if stream_id is unknown, the stream is not a MIC stream, or
|
||||
* channels is not 1 or 2. */
|
||||
* capture device with the new channel count). Defaults to 1 (mono). On iOS the Swift
|
||||
* AVAudioSession routing layer enables stereo built-in mic capture by switching the built-in
|
||||
* mic's data source to the .stereo polar pattern (setPreferredDataSource +
|
||||
* setPreferredPolarPattern(.stereo) + setPreferredInput + setInputDataSource) and then calls
|
||||
* this to tell the core to open the capture device in stereo. VC_ERR_INVALID_ARG if stream_id
|
||||
* is unknown, the stream is not a MIC stream, or channels is not 1 or 2. */
|
||||
VC_API vc_result vc_set_capture_channels(vc_client* c, uint32_t stream_id, uint32_t channels);
|
||||
|
||||
/* ── Text ─────────────────────────────────────────────────────────────────── */
|
||||
@@ -484,6 +485,16 @@ VC_API vc_result vc_get_permissions(vc_client* c, vc_permissions* out);
|
||||
VC_API vc_result vc_audio_suspend(vc_client* c);
|
||||
VC_API vc_result vc_audio_resume(vc_client* c);
|
||||
|
||||
/* Full audio engine restart (iOS M6). Unlike vc_audio_suspend/resume which only stop/start
|
||||
* the existing miniaudio devices (leaving them bound to the route that was active when they
|
||||
* were opened), vc_audio_restart() uninitializes and re-initializes the capture and playback
|
||||
* devices so they pick up a new AVAudioSession route. Call this from the Swift layer AFTER
|
||||
* reconfiguring AVAudioSession (setCategory, setPreferredInput, setPreferredPolarPattern, etc.)
|
||||
* so the core's devices reopen against the new route. Mirrors TeamTalk5's
|
||||
* closeSoundDevices()/initSoundInputDevice()/initSoundOutputDevice() reconfiguration pattern.
|
||||
* Safe to call when the engine is not running (it will just start it). */
|
||||
VC_API vc_result vc_audio_restart(vc_client* c);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user