diff --git a/libs/hbb_common/src/lib.rs b/libs/hbb_common/src/lib.rs index 15ef31022..36a68550f 100644 --- a/libs/hbb_common/src/lib.rs +++ b/libs/hbb_common/src/lib.rs @@ -27,6 +27,7 @@ pub use anyhow::{self, bail}; pub use futures_util; pub mod config; pub mod fs; +pub mod mem; pub use lazy_static; #[cfg(not(any(target_os = "android", target_os = "ios")))] pub use mac_address; diff --git a/libs/hbb_common/src/mem.rs b/libs/hbb_common/src/mem.rs new file mode 100644 index 000000000..90a5d6d40 --- /dev/null +++ b/libs/hbb_common/src/mem.rs @@ -0,0 +1,14 @@ +/// SAFETY: the returned Vec must not be resized or reserverd +pub unsafe fn aligned_u8_vec(cap: usize, align: usize) -> Vec { + use std::alloc::*; + + let layout = + Layout::from_size_align(cap, align).expect("invalid aligned value, must be power of 2"); + unsafe { + let ptr = alloc(layout); + if ptr.is_null() { + panic!("failed to allocate {} bytes", cap); + } + Vec::from_raw_parts(ptr, 0, cap) + } +} diff --git a/src/server/audio_service.rs b/src/server/audio_service.rs index f227bd232..5d60abf6c 100644 --- a/src/server/audio_service.rs +++ b/src/server/audio_service.rs @@ -78,6 +78,19 @@ pub fn restart() { #[cfg(any(target_os = "linux", target_os = "android"))] mod pa_impl { use super::*; + + // SAFETY: constrains of hbb_common::mem::aligned_u8_vec must be held + unsafe fn align_to_32(data: Vec) -> Vec { + if (data.as_ptr() as usize & 3) == 0 { + return data; + } + + let mut buf = vec![]; + buf = unsafe { hbb_common::mem::aligned_u8_vec(data.len(), 4) }; + buf.extend_from_slice(data.as_ref()); + buf + } + #[tokio::main(flavor = "current_thread")] pub async fn run(sp: EmptyExtraFieldService) -> ResultType<()> { hbb_common::sleep(0.1).await; // one moment to wait for _pa ipc @@ -106,23 +119,29 @@ mod pa_impl { sps.send(create_format_msg(crate::platform::PA_SAMPLE_RATE, 2)); Ok(()) })?; + #[cfg(target_os = "linux")] if let Ok(data) = stream.next_raw().await { if data.len() == 0 { send_f32(&zero_audio_frame, &mut encoder, &sp); continue; } + if data.len() != AUDIO_DATA_SIZE_U8 { continue; } + + let data = unsafe { align_to_32(data.into()) }; let data = unsafe { std::slice::from_raw_parts::(data.as_ptr() as _, data.len() / 4) }; send_f32(data, &mut encoder, &sp); } + #[cfg(target_os = "android")] if scrap::android::ffi::get_audio_raw(&mut android_data, &mut vec![]).is_some() { let data = unsafe { + android_data = align_to_32(android_data); std::slice::from_raw_parts::( android_data.as_ptr() as _, android_data.len() / 4,