diff --git a/.changeset/audioengine-platformaudio.md b/.changeset/audioengine-platformaudio.md new file mode 100644 index 000000000..571ad9a21 --- /dev/null +++ b/.changeset/audioengine-platformaudio.md @@ -0,0 +1,9 @@ +--- +livekit: minor +webrtc-sys: minor +--- + +Use the Apple AudioEngine ADM for PlatformAudio on iOS and macOS. + +- The platform ADM on Apple platforms is now the AVAudioEngine based device with runtime switchable voice processing and device change handling. +- `PlatformAudio::configure_audio_processing` now drives the ADM's native audio processing topology: on Apple the coupled AEC+NS voice processing path is enabled when both are requested with hardware preferred, otherwise WebRTC software processing is used. diff --git a/libwebrtc/src/native/peer_connection_factory.rs b/libwebrtc/src/native/peer_connection_factory.rs index b48f2bd83..36a927cee 100644 --- a/libwebrtc/src/native/peer_connection_factory.rs +++ b/libwebrtc/src/native/peer_connection_factory.rs @@ -259,6 +259,42 @@ impl PeerConnectionFactory { self.sys_handle.audio_device().enable_builtin_ns(enable) } + /// Returns the platform audio processing topology reported by the ADM. + pub fn platform_audio_processing_topology(&self) -> i32 { + self.sys_handle.audio_device().platform_audio_processing_topology() + } + + /// Returns whether the ADM can enable a platform voice-processing path. + pub fn platform_voice_processing_path_is_available(&self) -> bool { + self.sys_handle.audio_device().platform_voice_processing_path_is_available() + } + + /// Enables or disables the platform voice-processing path when supported. + pub fn enable_platform_voice_processing_path(&self, enable: bool) -> bool { + self.sys_handle.audio_device().enable_platform_voice_processing_path(enable) + } + + /// Returns whether the platform voice-processing path is enabled. + pub fn platform_voice_processing_path_is_enabled(&self) -> bool { + self.sys_handle.audio_device().platform_voice_processing_path_is_enabled() + } + + /// Configures platform audio processing using the ADM's native topology. + pub fn configure_platform_audio_processing( + &self, + echo_cancellation: bool, + auto_gain_control: bool, + noise_suppression: bool, + prefer_hardware: bool, + ) -> bool { + self.sys_handle.audio_device().configure_platform_audio_processing( + echo_cancellation, + auto_gain_control, + noise_suppression, + prefer_hardware, + ) + } + /// Control whether ADM recording (microphone) is enabled. /// /// When disabled, WebRTC's calls to InitRecording/StartRecording will be no-ops. diff --git a/livekit/src/platform_audio/mod.rs b/livekit/src/platform_audio/mod.rs index 7af17dfc2..7cf537ec4 100644 --- a/livekit/src/platform_audio/mod.rs +++ b/livekit/src/platform_audio/mod.rs @@ -95,9 +95,9 @@ //! //! # Platform-Specific Notes //! -//! - **iOS**: Creates a VPIO (Voice Processing IO) AudioUnit. Only one VPIO -//! can exist per process. Drop all `PlatformAudio` instances to release it. -//! - **macOS**: Uses CoreAudio. Full device enumeration and selection supported. +//! - **iOS**: Uses WebRTC's Apple AudioEngine ADM with platform voice processing. +//! Drop all `PlatformAudio` instances to release active audio I/O. +//! - **macOS**: Uses WebRTC's Apple AudioEngine ADM. Full device enumeration and selection supported. //! - **Windows**: Uses WASAPI. Full device enumeration and selection supported. //! - **Linux**: Uses PulseAudio or ALSA. Full device enumeration and selection supported. //! - **Android**: Uses Java AudioRecord/AudioTrack via WebRTC's `JavaAudioDeviceModule`. @@ -399,9 +399,9 @@ impl Drop for PlatformAdmHandle { /// /// # Platform-Specific Notes /// -/// - **iOS**: Creates a VPIO AudioUnit (exclusive microphone access). +/// - **iOS**: Uses WebRTC's Apple AudioEngine ADM with platform voice processing. /// Drop all instances to allow other audio frameworks to use the mic. -/// - **macOS**: Uses CoreAudio for device management. +/// - **macOS**: Uses WebRTC's Apple AudioEngine ADM for device management. /// - **Windows**: Uses WASAPI for device management. /// - **Linux**: Uses PulseAudio or ALSA. #[derive(Clone)] @@ -484,7 +484,7 @@ impl PlatformAudio { let audio = Self { handle }; // Configure audio processing with platform-appropriate defaults: - // - iOS: prefer_hardware_processing=true (VPIO is excellent) + // - iOS: prefer_hardware_processing=true (Apple voice processing is preferred) // - Android: prefer_hardware_processing=false (hardware AEC unreliable across devices) // - Desktop: prefer_hardware_processing=false (hardware not available anyway) if let Err(e) = audio.configure_audio_processing(AudioProcessingOptions::default()) { @@ -662,7 +662,7 @@ impl PlatformAudio { /// /// **Mobile (iOS/Android):** Device selection is a no-op. Both platforms handle /// microphone selection at the system level. This method will succeed but has no effect. - /// - iOS: VPIO AudioUnit handles input selection + /// - iOS: Apple AudioEngine handles input selection /// - Android: System selects best input source based on audio mode /// /// # Arguments @@ -987,7 +987,7 @@ impl PlatformAudio { /// /// # Platform Behavior /// - /// - **iOS**: Returns `true` (VPIO provides hardware AEC) + /// - **iOS**: Returns `true` when Apple voice processing can provide AEC /// - **Android**: Returns `true` on devices with hardware AEC support /// - **Desktop**: Returns `false` (hardware AEC not available) /// @@ -1007,7 +1007,7 @@ impl PlatformAudio { /// /// # Platform Behavior /// - /// - **iOS**: Returns `true` (VPIO provides hardware AGC) + /// - **iOS**: Returns `true` when Apple voice processing can provide AGC /// - **Android**: Returns `true` on devices with hardware AGC support /// - **Desktop**: Returns `false` (hardware AGC not available) pub fn is_hardware_agc_available(&self) -> bool { @@ -1018,7 +1018,7 @@ impl PlatformAudio { /// /// # Platform Behavior /// - /// - **iOS**: Returns `true` (VPIO provides hardware NS) + /// - **iOS**: Returns `true` when Apple voice processing can provide NS /// - **Android**: Returns `true` on devices with hardware NS support /// - **Desktop**: Returns `false` (hardware NS not available) pub fn is_hardware_ns_available(&self) -> bool { @@ -1076,7 +1076,7 @@ impl PlatformAudio { /// /// # Platform Behavior /// - /// - **iOS**: `prefer_hardware_processing` is ignored (always uses VPIO) + /// - **iOS/macOS**: `prefer_hardware_processing` uses Apple voice processing when available /// - **Android**: When `prefer_hardware_processing` is `false`, hardware /// effects are disabled and WebRTC's software APM is used instead /// - **Desktop**: `prefer_hardware_processing` is ignored (hardware not available) @@ -1100,34 +1100,15 @@ impl PlatformAudio { pub fn configure_audio_processing(&self, options: AudioProcessingOptions) -> AudioResult<()> { let runtime = &self.handle.runtime; - // Configure hardware vs software processing preference - // When prefer_hardware_processing is false, we disable hardware effects - // to force WebRTC to use its software APM instead - let use_hardware = options.prefer_hardware_processing; - - // Enable/disable hardware AEC - // Note: When hardware is disabled, WebRTC automatically falls back to software - if runtime.builtin_aec_is_available() { - let enable_hw = use_hardware && options.echo_cancellation; - if !runtime.enable_builtin_aec(enable_hw) { - log::warn!("enable_builtin_aec({}) failed", enable_hw); - } - } - - // Enable/disable hardware AGC - if runtime.builtin_agc_is_available() { - let enable_hw = use_hardware && options.auto_gain_control; - if !runtime.enable_builtin_agc(enable_hw) { - log::warn!("enable_builtin_agc({}) failed", enable_hw); - } - } - - // Enable/disable hardware NS - if runtime.builtin_ns_is_available() { - let enable_hw = use_hardware && options.noise_suppression; - if !runtime.enable_builtin_ns(enable_hw) { - log::warn!("enable_builtin_ns({}) failed", enable_hw); - } + if !runtime.configure_platform_audio_processing( + options.echo_cancellation, + options.auto_gain_control, + options.noise_suppression, + options.prefer_hardware_processing, + ) { + log::warn!( + "PlatformAudio: native audio processing configuration was partially applied" + ); } log::info!( diff --git a/livekit/src/platform_audio/processing.rs b/livekit/src/platform_audio/processing.rs index 8b99ef90d..3160434a5 100644 --- a/livekit/src/platform_audio/processing.rs +++ b/livekit/src/platform_audio/processing.rs @@ -17,7 +17,7 @@ /// The type of audio processing being used. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum AudioProcessingType { - /// Hardware audio processing (iOS VPIO, Android hardware effects). + /// Platform audio processing (Apple voice processing, Android hardware effects). Hardware, /// Software audio processing (WebRTC's built-in APM). Software, @@ -35,15 +35,15 @@ impl Default for AudioProcessingType { /// /// # Platform Behavior /// -/// - **iOS**: Hardware processing via VPIO is always used and provides excellent -/// AEC/AGC/NS. The `prefer_hardware_processing` default is `true` on iOS. +/// - **iOS/macOS**: Apple voice processing can provide platform AEC/AGC/NS. +/// The `prefer_hardware_processing` default is `true` on iOS. /// /// - **Android**: Hardware AEC quality varies significantly across manufacturers /// and device models. Many devices have broken or poorly-tuned hardware AEC. /// The default is `false` to use WebRTC's reliable software processing. /// See: /// -/// - **Desktop** (macOS, Windows, Linux): Hardware processing is not available. +/// - **Desktop** (Windows, Linux): Hardware processing is not available. /// WebRTC's software Audio Processing Module (APM) is always used. /// The `prefer_hardware_processing` setting is ignored. /// @@ -96,9 +96,8 @@ pub struct AudioProcessingOptions { /// /// # Platform Defaults /// - /// - **iOS**: `true` - VPIO hardware processing is excellent and always used. - /// Apple's Voice Processing IO unit provides reliable, low-latency AEC/AGC/NS - /// that is tightly integrated with the audio hardware. + /// - **iOS**: `true` - Apple voice processing provides reliable, + /// low-latency AEC/AGC/NS that is tightly integrated with audio I/O. /// /// - **Android**: `false` - Hardware AEC is unreliable on many devices. /// Quality varies significantly across manufacturers (Samsung, Xiaomi, etc.) @@ -107,8 +106,8 @@ pub struct AudioProcessingOptions { /// Reference: Meta found hardware AEC "broken on many combinations of HW + OS" /// when supporting billions of users across thousands of device models. /// - /// - **Desktop**: `false` - Hardware processing is not available. - /// This setting is ignored; WebRTC software APM is always used. + /// - **Desktop**: `false` - Hardware processing is not available on + /// non-Apple desktop targets. WebRTC software APM is used. pub prefer_hardware_processing: bool, } @@ -118,9 +117,9 @@ impl Default for AudioProcessingOptions { echo_cancellation: true, noise_suppression: true, auto_gain_control: true, - // iOS: VPIO hardware processing is excellent and tightly integrated. + // iOS: Apple voice processing is preferred when available. // Android: Hardware AEC is unreliable across the fragmented device ecosystem. - // Desktop: Hardware processing not available, setting is ignored. + // Desktop: Hardware processing not available on non-Apple desktop targets. #[cfg(target_os = "ios")] prefer_hardware_processing: true, #[cfg(not(target_os = "ios"))] diff --git a/livekit/src/rtc_engine/lk_runtime.rs b/livekit/src/rtc_engine/lk_runtime.rs index 81ad95e70..6479b97b5 100644 --- a/livekit/src/rtc_engine/lk_runtime.rs +++ b/livekit/src/rtc_engine/lk_runtime.rs @@ -209,6 +209,47 @@ impl LkRuntime { self.pc_factory.enable_builtin_ns(enable) } + /// Returns the platform audio processing topology reported by the ADM. + #[cfg(not(target_arch = "wasm32"))] + pub(crate) fn platform_audio_processing_topology(&self) -> i32 { + self.pc_factory.platform_audio_processing_topology() + } + + /// Returns whether the ADM can enable a platform voice-processing path. + #[cfg(not(target_arch = "wasm32"))] + pub(crate) fn platform_voice_processing_path_is_available(&self) -> bool { + self.pc_factory.platform_voice_processing_path_is_available() + } + + /// Enables or disables the platform voice-processing path when supported. + #[cfg(not(target_arch = "wasm32"))] + pub(crate) fn enable_platform_voice_processing_path(&self, enable: bool) -> bool { + self.pc_factory.enable_platform_voice_processing_path(enable) + } + + /// Returns whether the platform voice-processing path is enabled. + #[cfg(not(target_arch = "wasm32"))] + pub(crate) fn platform_voice_processing_path_is_enabled(&self) -> bool { + self.pc_factory.platform_voice_processing_path_is_enabled() + } + + /// Configures platform audio processing using the ADM's native topology. + #[cfg(not(target_arch = "wasm32"))] + pub(crate) fn configure_platform_audio_processing( + &self, + echo_cancellation: bool, + auto_gain_control: bool, + noise_suppression: bool, + prefer_hardware: bool, + ) -> bool { + self.pc_factory.configure_platform_audio_processing( + echo_cancellation, + auto_gain_control, + noise_suppression, + prefer_hardware, + ) + } + /// Control whether ADM recording (microphone) is enabled. /// /// When disabled, WebRTC's calls to InitRecording/StartRecording will be no-ops. diff --git a/webrtc-sys/include/livekit/adm_proxy.h b/webrtc-sys/include/livekit/adm_proxy.h index 31555103d..7a6149940 100644 --- a/webrtc-sys/include/livekit/adm_proxy.h +++ b/webrtc-sys/include/livekit/adm_proxy.h @@ -216,6 +216,14 @@ class AdmProxy : public webrtc::AudioDeviceModule { int32_t EnableBuiltInAGC(bool enable) override; int32_t EnableBuiltInNS(bool enable) override; + // Platform voice processing (Apple's coupled AEC+NS path) + webrtc::AudioDeviceModule::PlatformAudioProcessingTopology + GetPlatformAudioProcessingTopology() const override; + bool PlatformVoiceProcessingPathIsAvailable() const override; + int32_t EnablePlatformVoiceProcessingPath(bool enable) override; + webrtc::AudioDeviceModule::PlatformAudioProcessingState + GetPlatformAudioProcessingState() const override; + #if defined(WEBRTC_IOS) int GetPlayoutAudioParameters(webrtc::AudioParameters* params) const override; int GetRecordAudioParameters(webrtc::AudioParameters* params) const override; diff --git a/webrtc-sys/include/livekit/audio_device_controller.h b/webrtc-sys/include/livekit/audio_device_controller.h index db68e9151..68ce005f7 100644 --- a/webrtc-sys/include/livekit/audio_device_controller.h +++ b/webrtc-sys/include/livekit/audio_device_controller.h @@ -64,6 +64,14 @@ class AudioDeviceController { bool enable_builtin_aec(bool enable) const; bool enable_builtin_agc(bool enable) const; bool enable_builtin_ns(bool enable) const; + int platform_audio_processing_topology() const; + bool platform_voice_processing_path_is_available() const; + bool enable_platform_voice_processing_path(bool enable) const; + bool platform_voice_processing_path_is_enabled() const; + bool configure_platform_audio_processing(bool echo_cancellation, + bool auto_gain_control, + bool noise_suppression, + bool prefer_hardware) const; // ADM recording control void set_adm_recording_enabled(bool enabled) const; diff --git a/webrtc-sys/libwebrtc/patches/external_audio_source.patch b/webrtc-sys/libwebrtc/patches/external_audio_source.patch index 088be4044..970fad6d8 100644 --- a/webrtc-sys/libwebrtc/patches/external_audio_source.patch +++ b/webrtc-sys/libwebrtc/patches/external_audio_source.patch @@ -1,11 +1,11 @@ diff --git a/api/media_stream_interface.h b/api/media_stream_interface.h -index fb1cc4e58e..85062ba60e 100644 +index 643b5f273b..7b5b568692 100644 --- a/api/media_stream_interface.h +++ b/api/media_stream_interface.h -@@ -267,6 +267,11 @@ class RTC_EXPORT AudioSourceInterface : public MediaSourceInterface { - // (for some of the settings this approach is broken, e.g. setting +@@ -270,6 +270,11 @@ class RTC_EXPORT AudioSourceInterface : public MediaSourceInterface { // audio network adaptation on the source is the wrong layer of abstraction). virtual const AudioOptions options() const; + virtual void SetOptions(const AudioOptions & /* options */) {} + + // Returns true if this source delivers audio externally (via AddSink), + // bypassing the ADM/AudioState audio distribution path. @@ -79,10 +79,10 @@ index 04a7d19dfa..9f513f3c75 100644 virtual ~AudioSource() {} }; diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc -index 762f9d584c..4ce07ddc9d 100644 +index 44ff51e439..65b32e2d74 100644 --- a/media/engine/webrtc_voice_engine.cc +++ b/media/engine/webrtc_voice_engine.cc -@@ -1017,6 +1017,14 @@ class WebRtcVoiceSendChannel::WebRtcAudioSendStream : public AudioSource::Sink { +@@ -942,6 +942,14 @@ class WebRtcVoiceSendChannel::WebRtcAudioSendStream : public AudioSource::Sink { RTC_DCHECK(source_ == source); return; } @@ -98,10 +98,10 @@ index 762f9d584c..4ce07ddc9d 100644 source_ = source; UpdateSendState(); diff --git a/pc/rtp_sender.cc b/pc/rtp_sender.cc -index d5edbbf0ed..c14ddfe868 100644 +index bd3e4a34d8..6498a4eef8 100644 --- a/pc/rtp_sender.cc +++ b/pc/rtp_sender.cc -@@ -786,6 +786,13 @@ void AudioRtpSender::SetSend() { +@@ -792,6 +792,13 @@ void AudioRtpSender::SetSend() { RTC_DCHECK_RUN_ON(signaling_thread_); RTC_DCHECK(!stopped_); RTC_DCHECK(can_send_track()); @@ -116,7 +116,7 @@ index d5edbbf0ed..c14ddfe868 100644 RTC_LOG(LS_ERROR) << "SetAudioSend: No audio channel exists."; return; diff --git a/pc/rtp_sender.h b/pc/rtp_sender.h -index eaffd4ef0f..d0489df9e7 100644 +index 516ce7de05..c6216b6b7e 100644 --- a/pc/rtp_sender.h +++ b/pc/rtp_sender.h @@ -307,6 +307,12 @@ class LocalAudioSinkAdapter : public AudioTrackSinkInterface, diff --git a/webrtc-sys/src/adm_proxy.cpp b/webrtc-sys/src/adm_proxy.cpp index 16b8ff5cf..f27945357 100644 --- a/webrtc-sys/src/adm_proxy.cpp +++ b/webrtc-sys/src/adm_proxy.cpp @@ -57,9 +57,16 @@ AdmProxy::AdmProxy(const webrtc::Environment& env, webrtc::Thread* worker_thread // 3. Deferring creation ensures JNI is ready when we actually need the ADM #if defined(__ANDROID__) // platform_adm_ stays nullptr, will be created in EnsurePlatformAdmCreated() +#else +#if defined(WEBRTC_IOS) || defined(WEBRTC_MAC) + // Use the AVAudioEngine based ADM on Apple platforms. It supports runtime + // switchable voice processing and device change handling. + platform_adm_ = webrtc::CreateAudioDeviceModule( + env_, webrtc::AudioDeviceModule::kAppleAudioEngine); #else platform_adm_ = webrtc::CreateAudioDeviceModule( env_, webrtc::AudioDeviceModule::kPlatformDefaultAudio); +#endif if (!platform_adm_) { RTC_LOG(LS_ERROR) << "AdmProxy: CreateAudioDeviceModule returned nullptr"; @@ -836,6 +843,38 @@ int32_t AdmProxy::EnableBuiltInNS(bool enable) { }); } +webrtc::AudioDeviceModule::PlatformAudioProcessingTopology +AdmProxy::GetPlatformAudioProcessingTopology() const { + return WithPlatformAdm< + webrtc::AudioDeviceModule::PlatformAudioProcessingTopology>( + webrtc::AudioDeviceModule::PlatformAudioProcessingTopology::kIndependent, + [](webrtc::AudioDeviceModule& adm) { + return adm.GetPlatformAudioProcessingTopology(); + }); +} + +bool AdmProxy::PlatformVoiceProcessingPathIsAvailable() const { + return WithPlatformAdm(false, [](webrtc::AudioDeviceModule& adm) { + return adm.PlatformVoiceProcessingPathIsAvailable(); + }); +} + +int32_t AdmProxy::EnablePlatformVoiceProcessingPath(bool enable) { + return WithPlatformAdm(-1, [enable](webrtc::AudioDeviceModule& adm) { + return adm.EnablePlatformVoiceProcessingPath(enable); + }); +} + +webrtc::AudioDeviceModule::PlatformAudioProcessingState +AdmProxy::GetPlatformAudioProcessingState() const { + return WithPlatformAdm< + webrtc::AudioDeviceModule::PlatformAudioProcessingState>( + webrtc::AudioDeviceModule::PlatformAudioProcessingState(), + [](webrtc::AudioDeviceModule& adm) { + return adm.GetPlatformAudioProcessingState(); + }); +} + #if defined(WEBRTC_IOS) int AdmProxy::GetPlayoutAudioParameters(webrtc::AudioParameters* params) const { return WithPlatformAdm(-1, [params](webrtc::AudioDeviceModule& adm) { diff --git a/webrtc-sys/src/audio_device_controller.cpp b/webrtc-sys/src/audio_device_controller.cpp index 500b6efe9..85d65569a 100644 --- a/webrtc-sys/src/audio_device_controller.cpp +++ b/webrtc-sys/src/audio_device_controller.cpp @@ -174,6 +174,87 @@ bool AudioDeviceController::enable_builtin_ns(bool enable) const { return adm_proxy_->EnableBuiltInNS(enable) == 0; } +int AudioDeviceController::platform_audio_processing_topology() const { + return static_cast(adm_proxy_->GetPlatformAudioProcessingTopology()); +} + +bool AudioDeviceController::platform_voice_processing_path_is_available() const { + return adm_proxy_->PlatformVoiceProcessingPathIsAvailable(); +} + +bool AudioDeviceController::enable_platform_voice_processing_path(bool enable) const { + return adm_proxy_->EnablePlatformVoiceProcessingPath(enable) == 0; +} + +bool AudioDeviceController::platform_voice_processing_path_is_enabled() const { + auto state = adm_proxy_->GetPlatformAudioProcessingState(); + return state.is_voice_processing_enabled_active.value_or( + state.is_voice_processing_enabled_requested.value_or(false)); +} + +bool AudioDeviceController::configure_platform_audio_processing( + bool echo_cancellation, + bool auto_gain_control, + bool noise_suppression, + bool prefer_hardware) const { + const bool use_hardware = prefer_hardware; + bool ok = true; + auto update_ok = [&ok](bool result) { + ok = result && ok; + }; + + const auto topology = adm_proxy_->GetPlatformAudioProcessingTopology(); + if (topology == webrtc::AudioDeviceModule::PlatformAudioProcessingTopology:: + kEchoCancellationAndNoiseSuppressionCoupled) { + // Apple exposes AEC and NS through one shared voice-processing path. Only + // use the platform path when both requested components can be represented. + const bool use_echo_noise_platform_path = + use_hardware && echo_cancellation && noise_suppression; + + if (!use_echo_noise_platform_path) { + if (adm_proxy_->PlatformVoiceProcessingPathIsAvailable()) { + update_ok(adm_proxy_->EnablePlatformVoiceProcessingPath(false) == 0); + } + if (adm_proxy_->BuiltInAGCIsAvailable()) { + update_ok(adm_proxy_->EnableBuiltInAGC(false) == 0); + } + return ok; + } + + if (!adm_proxy_->PlatformVoiceProcessingPathIsAvailable()) { + return false; + } + if (adm_proxy_->EnablePlatformVoiceProcessingPath(true) != 0) { + return false; + } + + const bool echo_noise_available = adm_proxy_->BuiltInAECIsAvailable() && + adm_proxy_->BuiltInNSIsAvailable(); + if (!echo_noise_available) { + adm_proxy_->EnablePlatformVoiceProcessingPath(false); + return false; + } + + update_ok(adm_proxy_->EnableBuiltInAEC(true) == 0); + update_ok(adm_proxy_->EnableBuiltInNS(true) == 0); + if (adm_proxy_->BuiltInAGCIsAvailable()) { + update_ok(adm_proxy_->EnableBuiltInAGC(auto_gain_control) == 0); + } + return ok; + } + + if (adm_proxy_->BuiltInAECIsAvailable()) { + update_ok(adm_proxy_->EnableBuiltInAEC(use_hardware && echo_cancellation) == 0); + } + if (adm_proxy_->BuiltInAGCIsAvailable()) { + update_ok(adm_proxy_->EnableBuiltInAGC(use_hardware && auto_gain_control) == 0); + } + if (adm_proxy_->BuiltInNSIsAvailable()) { + update_ok(adm_proxy_->EnableBuiltInNS(use_hardware && noise_suppression) == 0); + } + return ok; +} + void AudioDeviceController::set_adm_recording_enabled(bool enabled) const { adm_proxy_->set_recording_enabled(enabled); } diff --git a/webrtc-sys/src/audio_device_controller.rs b/webrtc-sys/src/audio_device_controller.rs index 00ce73943..ca3da1d13 100644 --- a/webrtc-sys/src/audio_device_controller.rs +++ b/webrtc-sys/src/audio_device_controller.rs @@ -55,6 +55,20 @@ pub mod ffi { fn enable_builtin_aec(self: &AudioDeviceController, enable: bool) -> bool; fn enable_builtin_agc(self: &AudioDeviceController, enable: bool) -> bool; fn enable_builtin_ns(self: &AudioDeviceController, enable: bool) -> bool; + fn platform_audio_processing_topology(self: &AudioDeviceController) -> i32; + fn platform_voice_processing_path_is_available(self: &AudioDeviceController) -> bool; + fn enable_platform_voice_processing_path( + self: &AudioDeviceController, + enable: bool, + ) -> bool; + fn platform_voice_processing_path_is_enabled(self: &AudioDeviceController) -> bool; + fn configure_platform_audio_processing( + self: &AudioDeviceController, + echo_cancellation: bool, + auto_gain_control: bool, + noise_suppression: bool, + prefer_hardware: bool, + ) -> bool; fn set_adm_recording_enabled(self: &AudioDeviceController, enabled: bool); fn adm_recording_enabled(self: &AudioDeviceController) -> bool;