fix: different audio frame size than 10ms (#72)
This commit is contained in:
@@ -12,6 +12,7 @@ struct FrameData {
|
||||
pub sample_rate: u32,
|
||||
pub freq: f64,
|
||||
pub amplitude: f64,
|
||||
pub phase: u64,
|
||||
}
|
||||
|
||||
impl Default for FrameData {
|
||||
@@ -20,6 +21,7 @@ impl Default for FrameData {
|
||||
sample_rate: 48000,
|
||||
freq: 440.0,
|
||||
amplitude: 1.0,
|
||||
phase: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,7 +100,7 @@ impl SineTrack {
|
||||
loop {
|
||||
interval.tick().await;
|
||||
|
||||
let data = frame_options.lock();
|
||||
let mut data = frame_options.lock();
|
||||
let samples_count_10ms = (data.sample_rate / 100) as usize;
|
||||
|
||||
if samples_10ms.capacity() != samples_count_10ms {
|
||||
@@ -108,10 +110,13 @@ impl SineTrack {
|
||||
for i in 0..samples_count_10ms {
|
||||
let val = data.amplitude
|
||||
* f64::sin(
|
||||
std::f64::consts::PI * 2.0 * data.freq * i as f64
|
||||
/ samples_count_10ms as f64,
|
||||
std::f64::consts::PI
|
||||
* 2.0
|
||||
* data.freq
|
||||
* (data.phase as f64 / data.sample_rate as f64),
|
||||
);
|
||||
|
||||
data.phase += 1;
|
||||
// WebRTC uses 16-bit signed PCM
|
||||
samples_10ms[i] = (val * 32768.0) as i16;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
use crate::audio_frame::AudioFrame;
|
||||
use cxx::SharedPtr;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use webrtc_sys::media_stream as sys_ms;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct NativeAudioSource {
|
||||
sys_handle: SharedPtr<sys_ms::ffi::AudioTrackSource>,
|
||||
inner: Arc<Mutex<AudioSourceInner>>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct AudioSourceInner {
|
||||
buf: Vec<i16>,
|
||||
offset: usize,
|
||||
sample_rate: u32,
|
||||
num_channels: u32,
|
||||
}
|
||||
|
||||
impl Default for NativeAudioSource {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
sys_handle: sys_ms::ffi::new_audio_track_source(),
|
||||
inner: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,14 +32,51 @@ impl NativeAudioSource {
|
||||
}
|
||||
|
||||
pub fn capture_frame(&self, frame: &AudioFrame) {
|
||||
// TODO(theomonnom): Should we check for 10ms worth of data here?
|
||||
unsafe {
|
||||
self.sys_handle.on_captured_frame(
|
||||
frame.data.as_ptr(),
|
||||
frame.sample_rate as i32,
|
||||
frame.num_channels as usize,
|
||||
frame.samples_per_channel as usize,
|
||||
)
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
let samples_10ms = (frame.sample_rate / 100 * frame.num_channels) as usize;
|
||||
if inner.sample_rate != frame.sample_rate || inner.num_channels != frame.num_channels {
|
||||
inner.buf.resize(samples_10ms as usize, 0);
|
||||
inner.offset = 0;
|
||||
}
|
||||
|
||||
// Split the frame into 10ms chunks
|
||||
let mut i = 0;
|
||||
loop {
|
||||
let buf_offset = inner.offset;
|
||||
let remaining_data = frame.data.len() - i; // Remaining data to read inside the frame
|
||||
let needed_data = samples_10ms - buf_offset; // Needed data of "frame.data" to make a complete 10ms from inner.buf
|
||||
if remaining_data < needed_data {
|
||||
if remaining_data > 0 {
|
||||
// Not enough data to make a complete 10ms frame, store the remaining data inside inner.buf
|
||||
// It'll be used on the next capture.
|
||||
inner.buf[buf_offset..buf_offset + remaining_data]
|
||||
.copy_from_slice(&frame.data[i..]);
|
||||
inner.offset += remaining_data;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
let data = if inner.offset != 0 {
|
||||
// Use the data from the previous capture
|
||||
let data = &mut inner.buf[buf_offset..];
|
||||
data.copy_from_slice(&frame.data[i..i + needed_data]);
|
||||
inner.offset = 0;
|
||||
&inner.buf
|
||||
} else {
|
||||
&frame.data[i..i + samples_10ms]
|
||||
};
|
||||
|
||||
unsafe {
|
||||
self.sys_handle.on_captured_frame(
|
||||
data.as_ptr(),
|
||||
frame.sample_rate as i32,
|
||||
frame.num_channels as usize,
|
||||
samples_10ms,
|
||||
)
|
||||
}
|
||||
|
||||
i += needed_data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user