Skip to content

Commit 8e503e8

Browse files
committed
CSDK-2183 daily-python: align memory to i16
1 parent 9c534c1 commit 8e503e8

File tree

4 files changed

+53
-12
lines changed

4 files changed

+53
-12
lines changed

src/media/native_vad.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::util::memory::AlignedI16Data;
2+
13
use webrtc_daily::sys::vad::NativeWebrtcVad;
24

35
use daily_core::prelude::daily_core_context_vad_analyze;
@@ -76,26 +78,26 @@ impl PyNativeVad {
7678
/// :return: The probability (from 0 to 1.0) that speech was detected
7779
/// :rtype: float
7880
fn analyze_frames(&self, frames: &PyBytes) -> PyResult<f32> {
79-
// TODO(aleix): Should this be i16 aligned?
80-
let bytes = frames.as_bytes();
81-
82-
let bytes_length = frames.len()?;
81+
let num_bytes = frames.len()?;
8382
let bytes_per_sample = 2;
8483

8584
// libwebrtc needs 16-bit linear PCM samples
86-
if bytes_length % bytes_per_sample != 0 {
85+
if num_bytes % bytes_per_sample != 0 {
8786
return Err(exceptions::PyValueError::new_err(
8887
"frames bytestring should contain 16-bit samples",
8988
));
9089
}
9190

92-
let num_frames = (bytes_length / bytes_per_sample) / self.channels as usize;
91+
let num_frames = (num_bytes / bytes_per_sample) / self.channels as usize;
92+
93+
let bytes = frames.as_bytes();
94+
let aligned = AlignedI16Data::new(bytes);
9395

9496
let confidence = Python::with_gil(|py| {
9597
py.allow_threads(move || unsafe {
9698
daily_core_context_vad_analyze(
9799
self.webrtc_vad.as_ref().unwrap().as_ptr() as *mut _,
98-
bytes.as_ptr() as *const _,
100+
aligned.as_ptr(),
99101
num_frames,
100102
)
101103
})

src/media/virtual_microphone_device.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::sync::atomic::{AtomicU64, Ordering};
22
use std::{collections::HashMap, sync::Mutex};
33

4+
use crate::util::memory::AlignedI16Data;
45
use crate::GIL_MUTEX_HACK;
56

67
use webrtc_daily::sys::virtual_microphone_device::NativeVirtualMicrophoneDevice;
@@ -114,28 +115,28 @@ impl PyVirtualMicrophoneDevice {
114115
));
115116
}
116117

117-
let bytes_length = frames.len()?;
118+
let num_bytes = frames.len()?;
118119
let bytes_per_sample = 2;
119120

120121
// libwebrtc needs 16-bit linear PCM samples
121-
if bytes_length % bytes_per_sample != 0 {
122+
if num_bytes % bytes_per_sample != 0 {
122123
return Err(exceptions::PyValueError::new_err(
123124
"frames bytestring should contain 16-bit samples",
124125
));
125126
}
126127

127-
let num_frames = (bytes_length / bytes_per_sample) / self.channels as usize;
128+
let num_frames = (num_bytes / bytes_per_sample) / self.channels as usize;
128129

129-
// TODO(aleix): Should this be i16 aligned?
130130
let bytes = frames.as_bytes();
131+
let aligned = AlignedI16Data::new(bytes);
131132

132133
let request_id = self.maybe_register_completion(completion);
133134

134135
Python::with_gil(|py| {
135136
let frames_written = py.allow_threads(move || unsafe {
136137
daily_core_context_virtual_microphone_device_write_frames(
137138
self.audio_device.as_ref().unwrap().as_ptr() as *mut _,
138-
bytes.as_ptr() as *const _,
139+
aligned.as_ptr(),
139140
num_frames,
140141
request_id,
141142
on_write_frames,

src/util.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub(crate) mod dict;
2+
pub(crate) mod memory;

src/util/memory.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
pub(crate) enum AlignedI16Data<'a> {
2+
AlreadyAligned(&'a [u8]),
3+
Copied(Vec<i16>),
4+
}
5+
6+
impl<'a> AlignedI16Data<'a> {
7+
pub fn new(src: &'a [u8]) -> Self {
8+
let bytes_ptr = src.as_ptr();
9+
10+
// If `src`'s memory is not 16-bit aligned, create a new 16-bit aligned
11+
// memory area and copy the contents of `src` to it. Otherwise, simply
12+
// keep the original slice.
13+
if bytes_ptr as usize % 2 == 0 {
14+
AlignedI16Data::AlreadyAligned(src)
15+
} else {
16+
let num_bytes = src.len();
17+
let num_words = num_bytes / 2;
18+
19+
let mut words = Vec::<i16>::with_capacity(num_words);
20+
let words_ptr = words.as_mut_ptr() as *mut u8;
21+
22+
unsafe {
23+
std::ptr::copy_nonoverlapping(bytes_ptr, words_ptr, num_bytes);
24+
words.set_len(num_words);
25+
}
26+
27+
AlignedI16Data::Copied(words)
28+
}
29+
}
30+
31+
pub fn as_ptr(&self) -> *const i16 {
32+
match self {
33+
AlignedI16Data::AlreadyAligned(d) => d.as_ptr() as *const i16,
34+
AlignedI16Data::Copied(d) => d.as_ptr(),
35+
}
36+
}
37+
}

0 commit comments

Comments
 (0)