From 48c69e3342bb6cb8373285879acca458d8f21b6b Mon Sep 17 00:00:00 2001 From: Riccardo Zaglia Date: Sat, 21 Jun 2025 22:45:29 +1000 Subject: [PATCH] =?UTF-8?q?feat(client=5Fcore):=20=E2=9C=A8=20Move=20andro?= =?UTF-8?q?id=20to=20common=20CPAL=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 259 ++++++++++++++++------------- alvr/audio/Cargo.toml | 6 +- alvr/audio/src/lib.rs | 26 ++- alvr/client_core/Cargo.toml | 2 +- alvr/client_core/src/audio.rs | 219 ------------------------ alvr/client_core/src/connection.rs | 9 +- alvr/client_core/src/lib.rs | 3 - alvr/server_io/Cargo.toml | 2 +- 8 files changed, 165 insertions(+), 361 deletions(-) delete mode 100644 alvr/client_core/src/audio.rs diff --git a/Cargo.lock b/Cargo.lock index 19abb41ebf..0cc941f888 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ "accesskit", "accesskit_consumer", "hashbrown", - "objc2", + "objc2 0.5.2", "objc2-app-kit", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -223,9 +223,9 @@ dependencies = [ "app_dirs2", "env_logger", "mdns-sd", - "ndk 0.9.0", + "ndk", "ndk-context", - "oboe", + "ndk-sys 0.6.0+11769913", "rand 0.9.0", "serde", "serde_json", @@ -487,7 +487,7 @@ dependencies = [ "alvr_common", "jni", "local-ip-address", - "ndk 0.9.0", + "ndk", "ndk-context", "ndk-sys 0.6.0+11769913", "serde", @@ -543,7 +543,7 @@ dependencies = [ "jni-sys", "libc", "log", - "ndk 0.9.0", + "ndk", "ndk-context", "ndk-sys 0.6.0+11769913", "num_enum", @@ -697,9 +697,9 @@ dependencies = [ "core-graphics", "image", "log", - "objc2", + "objc2 0.5.2", "objc2-app-kit", - "objc2-foundation", + "objc2-foundation 0.2.2", "parking_lot", "windows-sys 0.48.0", "x11rb", @@ -1024,24 +1024,6 @@ dependencies = [ "syn 2.0.98", ] -[[package]] -name = "bindgen" -version = "0.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" -dependencies = [ - "bitflags 2.8.0", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "proc-macro2", - "quote", - "regex", - "rustc-hash 1.1.0", - "shlex", - "syn 2.0.98", -] - [[package]] name = "bindgen" version = "0.71.1" @@ -1113,7 +1095,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" dependencies = [ - "objc2", + "objc2 0.5.2", ] [[package]] @@ -1466,41 +1448,38 @@ dependencies = [ [[package]] name = "coreaudio-rs" -version = "0.11.3" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" +checksum = "1aae284fbaf7d27aa0e292f7677dfbe26503b0d555026f702940805a630eac17" dependencies = [ "bitflags 1.3.2", - "core-foundation-sys", - "coreaudio-sys", -] - -[[package]] -name = "coreaudio-sys" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b" -dependencies = [ - "bindgen 0.70.1", + "libc", + "objc2-audio-toolbox", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", ] [[package]] name = "cpal" -version = "0.15.3" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" +checksum = "cbd307f43cc2a697e2d1f8bc7a1d824b5269e052209e28883e5bc04d095aaa3f" dependencies = [ "alsa", - "core-foundation-sys", "coreaudio-rs", "dasp_sample", "jni", "js-sys", "libc", "mach2", - "ndk 0.8.0", + "ndk", "ndk-context", - "oboe", + "num-derive", + "num-traits", + "objc2-audio-toolbox", + "objc2-core-audio", + "objc2-core-audio-types", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -1704,6 +1683,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.1", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -1774,9 +1763,9 @@ dependencies = [ "image", "js-sys", "log", - "objc2", + "objc2 0.5.2", "objc2-app-kit", - "objc2-foundation", + "objc2-foundation 0.2.2", "parking_lot", "percent-encoding", "profiling", @@ -2386,9 +2375,9 @@ dependencies = [ "glutin_glx_sys", "glutin_wgl_sys", "libloading", - "objc2", + "objc2 0.5.2", "objc2-app-kit", - "objc2-foundation", + "objc2-foundation 0.2.2", "once_cell", "raw-window-handle", "wayland-sys", @@ -3482,20 +3471,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "ndk" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" -dependencies = [ - "bitflags 2.8.0", - "jni-sys", - "log", - "ndk-sys 0.5.0+25.2.9519653", - "num_enum", - "thiserror 1.0.69", -] - [[package]] name = "ndk" version = "0.9.0" @@ -3765,6 +3740,15 @@ dependencies = [ "objc2-encode", ] +[[package]] +name = "objc2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" +dependencies = [ + "objc2-encode", +] + [[package]] name = "objc2-app-kit" version = "0.2.2" @@ -3774,13 +3758,28 @@ dependencies = [ "bitflags 2.8.0", "block2", "libc", - "objc2", + "objc2 0.5.2", "objc2-core-data", "objc2-core-image", - "objc2-foundation", + "objc2-foundation 0.2.2", "objc2-quartz-core", ] +[[package]] +name = "objc2-audio-toolbox" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cbe18d879e20a4aea544f8befe38bcf52255eb63d3f23eca2842f3319e4c07" +dependencies = [ + "bitflags 2.8.0", + "libc", + "objc2 0.6.1", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-foundation 0.3.1", +] + [[package]] name = "objc2-cloud-kit" version = "0.2.2" @@ -3789,9 +3788,9 @@ checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ "bitflags 2.8.0", "block2", - "objc2", + "objc2 0.5.2", "objc2-core-location", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -3801,8 +3800,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" dependencies = [ "block2", - "objc2", - "objc2-foundation", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-audio" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca44961e888e19313b808f23497073e3f6b3c22bb485056674c8b49f3b025c82" +dependencies = [ + "dispatch2", + "objc2 0.6.1", + "objc2-core-audio-types", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-core-audio-types" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f1cc99bb07ad2ddb6527ddf83db6a15271bb036b3eb94b801cd44fdc666ee1" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.1", ] [[package]] @@ -3813,8 +3834,19 @@ checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ "bitflags 2.8.0", "block2", - "objc2", - "objc2-foundation", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +dependencies = [ + "bitflags 2.8.0", + "dispatch2", + "objc2 0.6.1", ] [[package]] @@ -3824,8 +3856,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" dependencies = [ "block2", - "objc2", - "objc2-foundation", + "objc2 0.5.2", + "objc2-foundation 0.2.2", "objc2-metal", ] @@ -3836,9 +3868,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" dependencies = [ "block2", - "objc2", + "objc2 0.5.2", "objc2-contacts", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -3857,7 +3889,16 @@ dependencies = [ "block2", "dispatch", "libc", - "objc2", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +dependencies = [ + "objc2 0.6.1", ] [[package]] @@ -3867,9 +3908,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" dependencies = [ "block2", - "objc2", + "objc2 0.5.2", "objc2-app-kit", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -3880,8 +3921,8 @@ checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ "bitflags 2.8.0", "block2", - "objc2", - "objc2-foundation", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -3892,8 +3933,8 @@ checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ "bitflags 2.8.0", "block2", - "objc2", - "objc2-foundation", + "objc2 0.5.2", + "objc2-foundation 0.2.2", "objc2-metal", ] @@ -3903,8 +3944,8 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" dependencies = [ - "objc2", - "objc2-foundation", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -3915,12 +3956,12 @@ checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ "bitflags 2.8.0", "block2", - "objc2", + "objc2 0.5.2", "objc2-cloud-kit", "objc2-core-data", "objc2-core-image", "objc2-core-location", - "objc2-foundation", + "objc2-foundation 0.2.2", "objc2-link-presentation", "objc2-quartz-core", "objc2-symbols", @@ -3935,8 +3976,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" dependencies = [ "block2", - "objc2", - "objc2-foundation", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -3947,9 +3988,9 @@ checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ "bitflags 2.8.0", "block2", - "objc2", + "objc2 0.5.2", "objc2-core-location", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -3970,29 +4011,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "oboe" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" -dependencies = [ - "jni", - "ndk 0.8.0", - "ndk-context", - "num-derive", - "num-traits", - "oboe-sys", -] - -[[package]] -name = "oboe-sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" -dependencies = [ - "cc", -] - [[package]] name = "ogg" version = "0.8.0" @@ -4774,13 +4792,14 @@ dependencies = [ [[package]] name = "rodio" version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ceb6607dd738c99bc8cb28eff249b7cd5c8ec88b9db96c0608c1480d140fb1" +source = "git+https://github.com/RustAudio/rodio#071db6df2adfccfe1032be43dd87e5681e34292c" dependencies = [ "claxon", "cpal", + "dasp_sample", "hound", "lewton", + "num-rational", "symphonia", ] @@ -6300,8 +6319,8 @@ dependencies = [ "jni", "log", "ndk-context", - "objc2", - "objc2-foundation", + "objc2 0.5.2", + "objc2-foundation 0.2.2", "url", "web-sys", ] @@ -6983,10 +7002,10 @@ dependencies = [ "js-sys", "libc", "memmap2", - "ndk 0.9.0", - "objc2", + "ndk", + "objc2 0.5.2", "objc2-app-kit", - "objc2-foundation", + "objc2-foundation 0.2.2", "objc2-ui-kit", "orbclient", "percent-encoding", diff --git a/alvr/audio/Cargo.toml b/alvr/audio/Cargo.toml index 0416847e51..ee51b07f1e 100644 --- a/alvr/audio/Cargo.toml +++ b/alvr/audio/Cargo.toml @@ -11,8 +11,8 @@ alvr_common.workspace = true alvr_session.workspace = true alvr_sockets.workspace = true -cpal = "0.15" -rodio = "0.20" +cpal = "0.16" +rodio = { git = "https://github.com/RustAudio/rodio" } serde = "1" [target.'cfg(windows)'.dependencies] @@ -28,4 +28,4 @@ windows = { version = "0.60", features = [ [target.'cfg(target_os = "linux")'.dependencies] pipewire = { version = "0.8.0", features = ["v0_3_49"] } -libspa-sys = "0.8.0" \ No newline at end of file +libspa-sys = "0.8.0" diff --git a/alvr/audio/src/lib.rs b/alvr/audio/src/lib.rs index 37a881ae8b..2e36f8c4ad 100644 --- a/alvr/audio/src/lib.rs +++ b/alvr/audio/src/lib.rs @@ -12,7 +12,7 @@ use alvr_common::{ info, once_cell::sync::Lazy, parking_lot::Mutex, - ConnectionError, ToAny, + ConnectionError, RelaxedAtomic, ToAny, }; use alvr_session::{AudioBufferingConfig, CustomAudioDeviceConfig, MicrophoneDevicesConfig}; use alvr_sockets::{StreamReceiver, StreamSender}; @@ -20,7 +20,7 @@ use cpal::{ traits::{DeviceTrait, HostTrait, StreamTrait}, BufferSize, Device, Host, Sample, SampleFormat, StreamConfig, }; -use rodio::{OutputStream, Source}; +use rodio::{OutputStreamBuilder, Source}; use std::{ collections::{HashMap, VecDeque}, sync::Arc, @@ -545,7 +545,7 @@ struct StreamingSource { } impl Source for StreamingSource { - fn current_frame_len(&self) -> Option { + fn current_span_len(&self) -> Option { None } @@ -601,19 +601,29 @@ pub fn play_audio_loop( let sample_buffer = Arc::new(Mutex::new(VecDeque::new())); - let (_stream, handle) = OutputStream::try_from_device(&device.inner)?; + let stream_has_error = Arc::new(RelaxedAtomic::new(false)); - handle.play_raw(StreamingSource { + let stream_handle = OutputStreamBuilder::from_device(device.inner.clone())? + .with_error_callback({ + let stream_has_error = Arc::clone(&stream_has_error); + move |_| { + alvr_common::error!("detected audio error!"); + stream_has_error.set(true) + } + }) + .open_stream()?; + + stream_handle.mixer().add(StreamingSource { sample_buffer: Arc::clone(&sample_buffer), current_batch: vec![], current_batch_cursor: 0, channels_count: channels_count as _, sample_rate, batch_frames_count, - })?; + }); receive_samples_loop( - is_running, + || is_running() && !stream_has_error.value(), receiver, sample_buffer, channels_count as _, @@ -622,5 +632,7 @@ pub fn play_audio_loop( ) .ok(); + alvr_common::error!("destroying playback audio stream"); + Ok(()) } diff --git a/alvr/client_core/Cargo.toml b/alvr/client_core/Cargo.toml index dbad165592..d69a85d642 100644 --- a/alvr/client_core/Cargo.toml +++ b/alvr/client_core/Cargo.toml @@ -32,7 +32,7 @@ serde_json = "1" android_logger = "0.14" ndk = { version = "0.9", features = ["api-level-26", "media"] } ndk-context = "0.1" -oboe = "0.6" # todo: remove once AudioThread shutdown crash is fixed +ndk-sys = "0.6" [target.'cfg(not(target_os = "android"))'.dependencies] env_logger = "0.11" diff --git a/alvr/client_core/src/audio.rs b/alvr/client_core/src/audio.rs deleted file mode 100644 index 18d0bfafcc..0000000000 --- a/alvr/client_core/src/audio.rs +++ /dev/null @@ -1,219 +0,0 @@ -use alvr_audio::{AudioDevice, AudioRecordState}; -use alvr_common::{ - anyhow::{bail, Result}, - parking_lot::Mutex, - ToAny, -}; -use alvr_session::AudioBufferingConfig; -use alvr_sockets::{StreamReceiver, StreamSender}; -use oboe::{ - AudioInputCallback, AudioInputStreamSafe, AudioOutputCallback, AudioOutputStreamSafe, - AudioStream, AudioStreamBuilder, DataCallbackResult, InputPreset, Mono, PerformanceMode, - SampleRateConversionQuality, Stereo, Usage, -}; -use std::{collections::VecDeque, mem, sync::Arc, thread, time::Duration}; - -struct RecorderCallback { - is_running: Arc bool + Send + Sync>, - sender: StreamSender<()>, - state: Arc>, -} - -impl AudioInputCallback for RecorderCallback { - type FrameType = (i16, Mono); - - fn on_audio_ready( - &mut self, - _: &mut dyn AudioInputStreamSafe, - frames: &[i16], - ) -> DataCallbackResult { - let mut sample_buffer = Vec::with_capacity(frames.len() * mem::size_of::()); - - for frame in frames { - sample_buffer.extend(&frame.to_ne_bytes()); - } - - if (self.is_running)() { - let mut buffer = self.sender.get_buffer(&()).unwrap(); - buffer - .get_range_mut(0, sample_buffer.len()) - .copy_from_slice(&sample_buffer); - self.sender.send(buffer).ok(); - - DataCallbackResult::Continue - } else { - *self.state.lock() = AudioRecordState::ShouldStop; - - DataCallbackResult::Stop - } - } - - fn on_error_before_close(&mut self, _: &mut dyn AudioInputStreamSafe, error: oboe::Error) { - *self.state.lock() = AudioRecordState::Err(Some(error.into())); - } - - fn on_error_after_close(&mut self, _: &mut dyn AudioInputStreamSafe, error: oboe::Error) { - *self.state.lock() = AudioRecordState::Err(Some(error.into())); - } -} - -#[allow(unused_variables)] -pub fn record_audio_blocking( - is_running: Arc bool + Send + Sync>, - sender: StreamSender<()>, - device: &AudioDevice, - channels_count: u16, - mute: bool, -) -> Result<()> { - let sample_rate = device.input_sample_rate()?; - - let state = Arc::new(Mutex::new(AudioRecordState::Recording)); - - let mut stream = AudioStreamBuilder::default() - .set_shared() - .set_performance_mode(PerformanceMode::LowLatency) - .set_sample_rate(sample_rate as _) - .set_sample_rate_conversion_quality(SampleRateConversionQuality::Fastest) - .set_mono() - .set_i16() - .set_input() - .set_usage(Usage::VoiceCommunication) - .set_input_preset(InputPreset::VoiceCommunication) - .set_callback(RecorderCallback { - is_running: Arc::clone(&is_running), - sender, - state: Arc::clone(&state), - }) - .open_stream()?; - - let mut res = stream.start().to_any(); - - if res.is_ok() { - while matches!(*state.lock(), AudioRecordState::Recording) && is_running() { - thread::sleep(Duration::from_millis(500)) - } - - if let AudioRecordState::Err(e) = &mut *state.lock() { - res = Err(e.take().unwrap()); - } - } - - stream.stop_with_timeout(0).ok(); - - res -} - -pub enum AudioPlaybackState { - Playing, - Err(oboe::Error), -} - -struct PlayerCallback { - sample_buffer: Arc>>, - state: Arc>, - batch_frames_count: usize, -} - -impl AudioOutputCallback for PlayerCallback { - type FrameType = (f32, Stereo); - - fn on_audio_ready( - &mut self, - _: &mut dyn AudioOutputStreamSafe, - out_frames: &mut [(f32, f32)], - ) -> DataCallbackResult { - assert!(self.batch_frames_count == out_frames.len()); - - let samples = alvr_audio::get_next_frame_batch( - &mut *self.sample_buffer.lock(), - 2, - self.batch_frames_count, - ); - - for f in 0..out_frames.len() { - out_frames[f] = (samples[f * 2], samples[f * 2 + 1]); - } - - DataCallbackResult::Continue - } - - fn on_error_before_close( - &mut self, - _audio_stream: &mut dyn AudioOutputStreamSafe, - error: oboe::Error, - ) { - *self.state.lock() = AudioPlaybackState::Err(error); - } - - fn on_error_after_close( - &mut self, - _audio_stream: &mut dyn AudioOutputStreamSafe, - error: oboe::Error, - ) { - *self.state.lock() = AudioPlaybackState::Err(error); - } -} - -#[allow(unused_variables)] -pub fn play_audio_loop( - is_running: impl Fn() -> bool, - device: &AudioDevice, - channels_count: u16, - sample_rate: u32, - config: AudioBufferingConfig, - receiver: &mut StreamReceiver<()>, -) -> Result<()> { - // the client sends invalid sample rates sometimes, and we crash if we try and use one - // (batch_frames_count ends up zero and the audio callback gets confused) - if sample_rate < 8000 { - bail!("Invalid audio sample rate"); - } - - let batch_frames_count = sample_rate as usize * config.batch_ms as usize / 1000; - let average_buffer_frames_count = - sample_rate as usize * config.average_buffering_ms as usize / 1000; - - let sample_buffer = Arc::new(Mutex::new(VecDeque::new())); - let state = Arc::new(Mutex::new(AudioPlaybackState::Playing)); - - let mut stream = AudioStreamBuilder::default() - .set_shared() - .set_performance_mode(PerformanceMode::LowLatency) - .set_sample_rate(sample_rate as _) - .set_sample_rate_conversion_quality(SampleRateConversionQuality::Fastest) - .set_stereo() - .set_f32() - .set_frames_per_callback(batch_frames_count as _) - .set_output() - .set_usage(Usage::Game) - .set_callback(PlayerCallback { - sample_buffer: Arc::clone(&sample_buffer), - batch_frames_count, - state: state.clone(), - }) - .open_stream()?; - - stream.start()?; - - alvr_audio::receive_samples_loop( - || is_running() && matches!(*state.lock(), AudioPlaybackState::Playing), - receiver, - sample_buffer, - 2, - batch_frames_count, - average_buffer_frames_count, - ) - .ok(); - - // If we had an error, the stream is already stopped/closed - if matches!(*state.lock(), AudioPlaybackState::Playing) { - // Note: Oboe crahes if stream.stop() is NOT called on AudioPlayer - return Ok(stream.stop_with_timeout(0)?); - } - - let result = match *state.lock() { - AudioPlaybackState::Err(error) => Err(error.into()), - AudioPlaybackState::Playing => Ok(()), - }; - result -} diff --git a/alvr/client_core/src/connection.rs b/alvr/client_core/src/connection.rs index a629682dd6..29e610983a 100644 --- a/alvr/client_core/src/connection.rs +++ b/alvr/client_core/src/connection.rs @@ -31,11 +31,6 @@ use std::{ time::{Duration, Instant}, }; -#[cfg(target_os = "android")] -use crate::audio; -#[cfg(not(target_os = "android"))] -use alvr_audio as audio; - const INITIAL_MESSAGE: &str = concat!( "Searching for streamer...\n", "Open ALVR on your PC then click \"Trust\"\n", @@ -344,7 +339,7 @@ fn connection_pipeline( let ctx = Arc::clone(&ctx); move || { while is_streaming(&ctx) { - alvr_common::show_err(audio::play_audio_loop( + alvr_common::show_err(alvr_audio::play_audio_loop( || is_streaming(&ctx), &device, 2, @@ -369,7 +364,7 @@ fn connection_pipeline( move || { while is_streaming(&ctx) { let ctx = Arc::clone(&ctx); - match audio::record_audio_blocking( + match alvr_audio::record_audio_blocking( Arc::new(move || is_streaming(&ctx)), microphone_sender.clone(), &device, diff --git a/alvr/client_core/src/lib.rs b/alvr/client_core/src/lib.rs index d36cb4f0ba..cbdb06a297 100644 --- a/alvr/client_core/src/lib.rs +++ b/alvr/client_core/src/lib.rs @@ -12,9 +12,6 @@ mod sockets; mod statistics; mod storage; -#[cfg(target_os = "android")] -mod audio; - pub mod video_decoder; use alvr_common::{ diff --git a/alvr/server_io/Cargo.toml b/alvr/server_io/Cargo.toml index 3ba728c3e8..d892f0a483 100644 --- a/alvr/server_io/Cargo.toml +++ b/alvr/server_io/Cargo.toml @@ -19,4 +19,4 @@ runas = "^1.2" # version 1.1 is broken serde_json = "1" [target.'cfg(not(target_os = "linux"))'.dependencies] -cpal = "0.15" +cpal = "0.16"