зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1530715 - P26: Create a Resampler module. r=padenot
Using a resample struct to operate all its related operations will make the code clearer. Differential Revision: https://phabricator.services.mozilla.com/D34059 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
3481c83d49
Коммит
96aee8cca3
|
@ -3,4 +3,4 @@ git repository using the update.sh script.
|
|||
|
||||
The cubeb-coreaudio-rs git repository is: https://github.com/ChunMinChang/cubeb-coreaudio-rs
|
||||
|
||||
The git commit ID used was 5841bba86f1245190020c7c6263a4b9ee783f442 (2019-06-25 11:31:39 -0700)
|
||||
The git commit ID used was 3aa0e6afc3dacb00cf80b785e6e980e156c4f49b (2019-06-25 11:31:56 -0700)
|
||||
|
|
|
@ -13,6 +13,7 @@ mod auto_array;
|
|||
mod auto_release;
|
||||
mod owned_critical_section;
|
||||
mod property_address;
|
||||
mod resampler;
|
||||
mod utils;
|
||||
|
||||
use self::aggregate_device::*;
|
||||
|
@ -27,6 +28,7 @@ use self::coreaudio_sys_utils::string::*;
|
|||
use self::coreaudio_sys_utils::sys::*;
|
||||
use self::owned_critical_section::*;
|
||||
use self::property_address::*;
|
||||
use self::resampler::*;
|
||||
use self::utils::*;
|
||||
use atomic;
|
||||
use cubeb_backend::{
|
||||
|
@ -416,15 +418,12 @@ extern "C" fn audiounit_input_callback(
|
|||
let mut total_input_frames = (stm.input_linear_buffer.as_ref().unwrap().elements()
|
||||
/ stm.input_desc.mChannelsPerFrame as usize) as i64;
|
||||
assert!(!stm.input_linear_buffer.as_ref().unwrap().as_ptr().is_null());
|
||||
let outframes = unsafe {
|
||||
ffi::cubeb_resampler_fill(
|
||||
stm.resampler.as_mut(),
|
||||
stm.input_linear_buffer.as_mut().unwrap().as_mut_ptr(),
|
||||
&mut total_input_frames,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
)
|
||||
};
|
||||
let outframes = stm.resampler.fill(
|
||||
stm.input_linear_buffer.as_mut().unwrap().as_mut_ptr(),
|
||||
&mut total_input_frames,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
);
|
||||
if outframes < total_input_frames {
|
||||
assert_eq!(audio_output_unit_stop(stm.input_unit), NO_ERR);
|
||||
|
||||
|
@ -553,20 +552,16 @@ extern "C" fn audiounit_output_callback(
|
|||
|
||||
// Call user callback through resampler.
|
||||
assert!(!output_buffer.is_null());
|
||||
let outframes = unsafe {
|
||||
ffi::cubeb_resampler_fill(
|
||||
stm.resampler.as_mut(),
|
||||
input_buffer,
|
||||
if input_buffer.is_null() {
|
||||
ptr::null_mut()
|
||||
} else {
|
||||
&mut input_frames
|
||||
},
|
||||
output_buffer,
|
||||
i64::from(output_frames),
|
||||
)
|
||||
};
|
||||
|
||||
let outframes = stm.resampler.fill(
|
||||
input_buffer,
|
||||
if input_buffer.is_null() {
|
||||
ptr::null_mut()
|
||||
} else {
|
||||
&mut input_frames
|
||||
},
|
||||
output_buffer,
|
||||
i64::from(output_frames),
|
||||
);
|
||||
if !input_buffer.is_null() {
|
||||
// Pop from the buffer the frames used by the the resampler.
|
||||
stm.input_linear_buffer
|
||||
|
@ -2458,7 +2453,7 @@ struct AudioUnitStream<'ctx> {
|
|||
latency_frames: u32,
|
||||
current_latency_frames: AtomicU32,
|
||||
panning: atomic::Atomic<f32>,
|
||||
resampler: AutoRelease<ffi::cubeb_resampler>,
|
||||
resampler: Resampler,
|
||||
// This is true if a device change callback is currently running.
|
||||
switching_device: AtomicBool,
|
||||
// Mixer interface
|
||||
|
@ -2525,7 +2520,7 @@ impl<'ctx> AudioUnitStream<'ctx> {
|
|||
latency_frames,
|
||||
current_latency_frames: AtomicU32::new(0),
|
||||
panning: atomic::Atomic::new(0.0_f32),
|
||||
resampler: AutoRelease::new(ptr::null_mut(), ffi::cubeb_resampler_destroy),
|
||||
resampler: Resampler::default(),
|
||||
switching_device: AtomicBool::new(false),
|
||||
mixer: AutoRelease::new(ptr::null_mut(), ffi::cubeb_mixer_destroy),
|
||||
temp_buffer: Vec::new(),
|
||||
|
@ -3408,43 +3403,28 @@ impl<'ctx> AudioUnitStream<'ctx> {
|
|||
self.output_stream_params.rate()
|
||||
};
|
||||
|
||||
let mut input_unconverted_params: ffi::cubeb_stream_params =
|
||||
unsafe { ::std::mem::zeroed() };
|
||||
if self.has_input() {
|
||||
input_unconverted_params = unsafe { (*(self.input_stream_params.as_ptr())) }; // Perform copy.
|
||||
input_unconverted_params.rate = self.input_hw_rate as u32;
|
||||
}
|
||||
|
||||
let resampler_input_params = if self.has_input() {
|
||||
let mut params = unsafe { (*(self.input_stream_params.as_ptr())) };
|
||||
params.rate = self.input_hw_rate as u32;
|
||||
Some(params)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let resampler_output_params = if self.has_output() {
|
||||
let params = unsafe { (*(self.output_stream_params.as_ptr())) };
|
||||
Some(params)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let stm_ptr = self as *mut AudioUnitStream as *mut ffi::cubeb_stream;
|
||||
let stm_input_params = if self.has_input() {
|
||||
&mut input_unconverted_params
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
};
|
||||
let stm_output_params = if self.has_output() {
|
||||
self.output_stream_params.as_ptr()
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
};
|
||||
self.resampler.reset(unsafe {
|
||||
ffi::cubeb_resampler_create(
|
||||
stm_ptr,
|
||||
stm_input_params,
|
||||
stm_output_params,
|
||||
target_sample_rate,
|
||||
self.data_callback,
|
||||
self.user_ptr,
|
||||
ffi::CUBEB_RESAMPLER_QUALITY_DESKTOP,
|
||||
)
|
||||
});
|
||||
|
||||
if self.resampler.as_ptr().is_null() {
|
||||
cubeb_log!(
|
||||
"({:p}) Could not create resampler.",
|
||||
self as *const AudioUnitStream
|
||||
);
|
||||
return Err(Error::error());
|
||||
}
|
||||
self.resampler = Resampler::new(
|
||||
stm_ptr,
|
||||
resampler_input_params,
|
||||
resampler_output_params,
|
||||
target_sample_rate,
|
||||
self.data_callback,
|
||||
self.user_ptr,
|
||||
);
|
||||
|
||||
if !self.input_unit.is_null() {
|
||||
let r = audio_unit_initialize(self.input_unit);
|
||||
|
@ -3512,7 +3492,7 @@ impl<'ctx> AudioUnitStream<'ctx> {
|
|||
self.output_unit = ptr::null_mut();
|
||||
}
|
||||
|
||||
self.resampler.reset(ptr::null_mut());
|
||||
self.resampler.destroy();
|
||||
self.mixer.reset(ptr::null_mut());
|
||||
|
||||
{
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
use super::auto_release::*;
|
||||
use cubeb_backend::ffi;
|
||||
use std::os::raw::{c_long, c_uint, c_void};
|
||||
use std::ptr;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Resampler(AutoRelease<ffi::cubeb_resampler>);
|
||||
|
||||
impl Resampler {
|
||||
pub fn new(
|
||||
stream: *mut ffi::cubeb_stream,
|
||||
mut input_params: Option<ffi::cubeb_stream_params>,
|
||||
mut output_params: Option<ffi::cubeb_stream_params>,
|
||||
target_rate: c_uint,
|
||||
data_callback: ffi::cubeb_data_callback,
|
||||
user_ptr: *mut c_void,
|
||||
) -> Self {
|
||||
let raw_resampler = unsafe {
|
||||
let in_params = if input_params.is_some() {
|
||||
input_params.as_mut().unwrap() as *mut ffi::cubeb_stream_params
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
};
|
||||
let out_params = if output_params.is_some() {
|
||||
output_params.as_mut().unwrap() as *mut ffi::cubeb_stream_params
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
};
|
||||
ffi::cubeb_resampler_create(
|
||||
stream,
|
||||
in_params,
|
||||
out_params,
|
||||
target_rate,
|
||||
data_callback,
|
||||
user_ptr,
|
||||
ffi::CUBEB_RESAMPLER_QUALITY_DESKTOP,
|
||||
)
|
||||
};
|
||||
assert!(!raw_resampler.is_null(), "Failed to create resampler");
|
||||
let resampler = AutoRelease::new(raw_resampler, ffi::cubeb_resampler_destroy);
|
||||
Self(resampler)
|
||||
}
|
||||
|
||||
pub fn fill(
|
||||
&mut self,
|
||||
input_buffer: *mut c_void,
|
||||
input_frame_count: *mut c_long,
|
||||
output_buffer: *mut c_void,
|
||||
output_frames_needed: c_long,
|
||||
) -> c_long {
|
||||
unsafe {
|
||||
ffi::cubeb_resampler_fill(
|
||||
self.0.as_mut(),
|
||||
input_buffer,
|
||||
input_frame_count,
|
||||
output_buffer,
|
||||
output_frames_needed,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destroy(&mut self) {
|
||||
if !self.0.as_ptr().is_null() {
|
||||
self.0.reset(ptr::null_mut());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Resampler {
|
||||
fn drop(&mut self) {
|
||||
self.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Resampler {
|
||||
fn default() -> Self {
|
||||
Self(AutoRelease::new(
|
||||
ptr::null_mut(),
|
||||
ffi::cubeb_resampler_destroy,
|
||||
))
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче