Update ASIO backend for removal of `UnknownBufferType`
This commit is contained in:
parent
b5bfb8d422
commit
9e832c6eb3
|
@ -1,17 +1,19 @@
|
||||||
extern crate asio_sys as sys;
|
extern crate asio_sys as sys;
|
||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
|
|
||||||
use {
|
use crate::{
|
||||||
BuildStreamError,
|
BuildStreamError,
|
||||||
DefaultFormatError,
|
DefaultFormatError,
|
||||||
DeviceNameError,
|
DeviceNameError,
|
||||||
DevicesError,
|
DevicesError,
|
||||||
Format,
|
Format,
|
||||||
|
InputData,
|
||||||
|
OutputData,
|
||||||
PauseStreamError,
|
PauseStreamError,
|
||||||
PlayStreamError,
|
PlayStreamError,
|
||||||
SupportedFormatsError,
|
Sample,
|
||||||
StreamData,
|
|
||||||
StreamError,
|
StreamError,
|
||||||
|
SupportedFormatsError,
|
||||||
};
|
};
|
||||||
use traits::{
|
use traits::{
|
||||||
DeviceTrait,
|
DeviceTrait,
|
||||||
|
@ -89,16 +91,30 @@ impl DeviceTrait for Device {
|
||||||
Device::default_output_format(self)
|
Device::default_output_format(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_input_stream<D, E>(&self, format: &Format, data_callback: D, error_callback: E) -> Result<Self::Stream, BuildStreamError>
|
fn build_input_stream<T, D, E>(
|
||||||
|
&self,
|
||||||
|
format: &Format,
|
||||||
|
data_callback: D,
|
||||||
|
error_callback: E,
|
||||||
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(StreamData) + Send + 'static, E: FnMut(StreamError) + Send + 'static
|
T: Sample,
|
||||||
|
D: FnMut(InputData<T>) + Send + 'static,
|
||||||
|
E: FnMut(StreamError) + Send + 'static
|
||||||
{
|
{
|
||||||
Device::build_input_stream(self, format, data_callback, error_callback)
|
Device::build_input_stream(self, format, data_callback, error_callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_output_stream<D, E>(&self, format: &Format, data_callback: D, error_callback: E) -> Result<Self::Stream, BuildStreamError>
|
fn build_output_stream<T, D, E>(
|
||||||
|
&self,
|
||||||
|
format: &Format,
|
||||||
|
data_callback: D,
|
||||||
|
error_callback: E,
|
||||||
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(StreamData) + Send + 'static, E: FnMut(StreamError) + Send + 'static
|
T: Sample,
|
||||||
|
D: FnMut(OutputData<T>) + Send + 'static,
|
||||||
|
E: FnMut(StreamError) + Send + 'static
|
||||||
{
|
{
|
||||||
Device::build_output_stream(self, format, data_callback, error_callback)
|
Device::build_output_stream(self, format, data_callback, error_callback)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,12 @@ use super::parking_lot::Mutex;
|
||||||
use BackendSpecificError;
|
use BackendSpecificError;
|
||||||
use BuildStreamError;
|
use BuildStreamError;
|
||||||
use Format;
|
use Format;
|
||||||
|
use InputData;
|
||||||
|
use OutputData;
|
||||||
use PauseStreamError;
|
use PauseStreamError;
|
||||||
use PlayStreamError;
|
use PlayStreamError;
|
||||||
|
use Sample;
|
||||||
use SampleFormat;
|
use SampleFormat;
|
||||||
use StreamData;
|
|
||||||
use UnknownTypeInputBuffer;
|
|
||||||
use UnknownTypeOutputBuffer;
|
|
||||||
use StreamError;
|
use StreamError;
|
||||||
|
|
||||||
/// Sample types whose constant silent value is known.
|
/// Sample types whose constant silent value is known.
|
||||||
|
@ -23,14 +23,11 @@ trait Silence {
|
||||||
const SILENCE: Self;
|
const SILENCE: Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constraints on the interleaved sample buffer format required by the CPAL API.
|
|
||||||
trait InterleavedSample: Clone + Copy + Silence {
|
|
||||||
fn unknown_type_input_buffer(&[Self]) -> UnknownTypeInputBuffer;
|
|
||||||
fn unknown_type_output_buffer(&mut [Self]) -> UnknownTypeOutputBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constraints on the ASIO sample types.
|
/// Constraints on the ASIO sample types.
|
||||||
trait AsioSample: Clone + Copy + Silence + std::ops::Add<Self, Output = Self> {}
|
trait AsioSample: Clone + Copy + Silence + std::ops::Add<Self, Output = Self> {
|
||||||
|
fn to_cpal_sample<T: Sample>(&self) -> T;
|
||||||
|
fn from_cpal_sample<T: Sample>(&T) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
// Used to keep track of whether or not the current current asio stream buffer requires
|
// Used to keep track of whether or not the current current asio stream buffer requires
|
||||||
// being silencing before summing audio.
|
// being silencing before summing audio.
|
||||||
|
@ -61,16 +58,18 @@ impl Stream {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Device {
|
impl Device {
|
||||||
pub fn build_input_stream<D, E>(
|
pub fn build_input_stream<T, D, E>(
|
||||||
&self,
|
&self,
|
||||||
format: &Format,
|
format: &Format,
|
||||||
mut data_callback: D,
|
mut data_callback: D,
|
||||||
_error_callback: E,
|
_error_callback: E,
|
||||||
) -> Result<Stream, BuildStreamError>
|
) -> Result<Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(StreamData) + Send + 'static,
|
T: Sample,
|
||||||
E: FnMut(StreamError) + Send + 'static
|
D: FnMut(InputData<T>) + Send + 'static,
|
||||||
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
|
assert_eq!(format.data_type, T::FORMAT, "sample type does not match `format.data_type`");
|
||||||
let stream_type = self.driver.input_data_type().map_err(build_stream_err)?;
|
let stream_type = self.driver.input_data_type().map_err(build_stream_err)?;
|
||||||
|
|
||||||
// Ensure that the desired sample type is supported.
|
// Ensure that the desired sample type is supported.
|
||||||
|
@ -109,20 +108,18 @@ impl Device {
|
||||||
|
|
||||||
/// 1. Write from the ASIO buffer to the interleaved CPAL buffer.
|
/// 1. Write from the ASIO buffer to the interleaved CPAL buffer.
|
||||||
/// 2. Deliver the CPAL buffer to the user callback.
|
/// 2. Deliver the CPAL buffer to the user callback.
|
||||||
unsafe fn process_input_callback<A, B, D, F, G>(
|
unsafe fn process_input_callback<A, B, D, F>(
|
||||||
callback: &mut D,
|
callback: &mut D,
|
||||||
interleaved: &mut [u8],
|
interleaved: &mut [u8],
|
||||||
asio_stream: &sys::AsioStream,
|
asio_stream: &sys::AsioStream,
|
||||||
buffer_index: usize,
|
buffer_index: usize,
|
||||||
from_endianness: F,
|
from_endianness: F,
|
||||||
to_cpal_sample: G,
|
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
A: AsioSample,
|
A: AsioSample,
|
||||||
B: InterleavedSample,
|
B: Sample,
|
||||||
D: FnMut(StreamData) + Send + 'static,
|
D: FnMut(InputData<B>) + Send + 'static,
|
||||||
F: Fn(A) -> A,
|
F: Fn(A) -> A,
|
||||||
G: Fn(A) -> B,
|
|
||||||
{
|
{
|
||||||
// 1. Write the ASIO channels to the CPAL buffer.
|
// 1. Write the ASIO channels to the CPAL buffer.
|
||||||
let interleaved: &mut [B] = cast_slice_mut(interleaved);
|
let interleaved: &mut [B] = cast_slice_mut(interleaved);
|
||||||
|
@ -130,35 +127,32 @@ impl Device {
|
||||||
for ch_ix in 0..n_channels {
|
for ch_ix in 0..n_channels {
|
||||||
let asio_channel = asio_channel_slice::<A>(asio_stream, buffer_index, ch_ix);
|
let asio_channel = asio_channel_slice::<A>(asio_stream, buffer_index, ch_ix);
|
||||||
for (frame, s_asio) in interleaved.chunks_mut(n_channels).zip(asio_channel) {
|
for (frame, s_asio) in interleaved.chunks_mut(n_channels).zip(asio_channel) {
|
||||||
frame[ch_ix] = to_cpal_sample(from_endianness(*s_asio));
|
frame[ch_ix] = from_endianness(*s_asio).to_cpal_sample();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Deliver the interleaved buffer to the callback.
|
// 2. Deliver the interleaved buffer to the callback.
|
||||||
callback(
|
let data = InputData { buffer: interleaved };
|
||||||
StreamData::Input { buffer: B::unknown_type_input_buffer(interleaved) },
|
callback(data);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match (&stream_type, data_type) {
|
match (&stream_type, data_type) {
|
||||||
(&sys::AsioSampleType::ASIOSTInt16LSB, SampleFormat::I16) => {
|
(&sys::AsioSampleType::ASIOSTInt16LSB, SampleFormat::I16) => {
|
||||||
process_input_callback::<i16, i16, _, _, _>(
|
process_input_callback::<i16, T, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
&mut interleaved,
|
&mut interleaved,
|
||||||
asio_stream,
|
asio_stream,
|
||||||
buffer_index as usize,
|
buffer_index as usize,
|
||||||
from_le,
|
from_le,
|
||||||
std::convert::identity::<i16>,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
(&sys::AsioSampleType::ASIOSTInt16MSB, SampleFormat::I16) => {
|
(&sys::AsioSampleType::ASIOSTInt16MSB, SampleFormat::I16) => {
|
||||||
process_input_callback::<i16, i16, _, _, _>(
|
process_input_callback::<i16, T, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
&mut interleaved,
|
&mut interleaved,
|
||||||
asio_stream,
|
asio_stream,
|
||||||
buffer_index as usize,
|
buffer_index as usize,
|
||||||
from_be,
|
from_be,
|
||||||
std::convert::identity::<i16>,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,13 +160,12 @@ impl Device {
|
||||||
// trait for the `to_le` and `to_be` methods, but this does not support floats.
|
// trait for the `to_le` and `to_be` methods, but this does not support floats.
|
||||||
(&sys::AsioSampleType::ASIOSTFloat32LSB, SampleFormat::F32) |
|
(&sys::AsioSampleType::ASIOSTFloat32LSB, SampleFormat::F32) |
|
||||||
(&sys::AsioSampleType::ASIOSTFloat32MSB, SampleFormat::F32) => {
|
(&sys::AsioSampleType::ASIOSTFloat32MSB, SampleFormat::F32) => {
|
||||||
process_input_callback::<f32, f32, _, _, _>(
|
process_input_callback::<f32, T, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
&mut interleaved,
|
&mut interleaved,
|
||||||
asio_stream,
|
asio_stream,
|
||||||
buffer_index as usize,
|
buffer_index as usize,
|
||||||
std::convert::identity::<f32>,
|
std::convert::identity::<f32>,
|
||||||
std::convert::identity::<f32>,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,36 +173,33 @@ impl Device {
|
||||||
// `process_output_callback` function above by removing the unnecessary sample
|
// `process_output_callback` function above by removing the unnecessary sample
|
||||||
// conversion function.
|
// conversion function.
|
||||||
(&sys::AsioSampleType::ASIOSTInt32LSB, SampleFormat::I16) => {
|
(&sys::AsioSampleType::ASIOSTInt32LSB, SampleFormat::I16) => {
|
||||||
process_input_callback::<i32, i16, _, _, _>(
|
process_input_callback::<i32, T, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
&mut interleaved,
|
&mut interleaved,
|
||||||
asio_stream,
|
asio_stream,
|
||||||
buffer_index as usize,
|
buffer_index as usize,
|
||||||
from_le,
|
from_le,
|
||||||
|s| (s >> 16) as i16,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
(&sys::AsioSampleType::ASIOSTInt32MSB, SampleFormat::I16) => {
|
(&sys::AsioSampleType::ASIOSTInt32MSB, SampleFormat::I16) => {
|
||||||
process_input_callback::<i32, i16, _, _, _>(
|
process_input_callback::<i32, T, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
&mut interleaved,
|
&mut interleaved,
|
||||||
asio_stream,
|
asio_stream,
|
||||||
buffer_index as usize,
|
buffer_index as usize,
|
||||||
from_be,
|
from_be,
|
||||||
|s| (s >> 16) as i16,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// TODO: Handle endianness conversion for floats? We currently use the `PrimInt`
|
// TODO: Handle endianness conversion for floats? We currently use the `PrimInt`
|
||||||
// trait for the `to_le` and `to_be` methods, but this does not support floats.
|
// trait for the `to_le` and `to_be` methods, but this does not support floats.
|
||||||
(&sys::AsioSampleType::ASIOSTFloat64LSB, SampleFormat::F32) |
|
(&sys::AsioSampleType::ASIOSTFloat64LSB, SampleFormat::F32) |
|
||||||
(&sys::AsioSampleType::ASIOSTFloat64MSB, SampleFormat::F32) => {
|
(&sys::AsioSampleType::ASIOSTFloat64MSB, SampleFormat::F32) => {
|
||||||
process_input_callback::<f64, f32, _, _, _>(
|
process_input_callback::<f64, T, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
&mut interleaved,
|
&mut interleaved,
|
||||||
asio_stream,
|
asio_stream,
|
||||||
buffer_index as usize,
|
buffer_index as usize,
|
||||||
std::convert::identity::<f64>,
|
std::convert::identity::<f64>,
|
||||||
|s| s as f32,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,16 +224,18 @@ impl Device {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_output_stream<D, E>(
|
pub fn build_output_stream<T, D, E>(
|
||||||
&self,
|
&self,
|
||||||
format: &Format,
|
format: &Format,
|
||||||
mut data_callback: D,
|
mut data_callback: D,
|
||||||
_error_callback: E,
|
_error_callback: E,
|
||||||
) -> Result<Stream, BuildStreamError>
|
) -> Result<Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(StreamData) + Send + 'static,
|
T: Sample,
|
||||||
|
D: FnMut(OutputData<T>) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
|
assert_eq!(format.data_type, T::FORMAT, "sample type does not match `format.data_type`");
|
||||||
let stream_type = self.driver.output_data_type().map_err(build_stream_err)?;
|
let stream_type = self.driver.output_data_type().map_err(build_stream_err)?;
|
||||||
|
|
||||||
// Ensure that the desired sample type is supported.
|
// Ensure that the desired sample type is supported.
|
||||||
|
@ -305,26 +297,23 @@ impl Device {
|
||||||
/// 2. If required, silence the ASIO buffer.
|
/// 2. If required, silence the ASIO buffer.
|
||||||
/// 3. Finally, write the interleaved data to the non-interleaved ASIO buffer,
|
/// 3. Finally, write the interleaved data to the non-interleaved ASIO buffer,
|
||||||
/// performing endianness conversions as necessary.
|
/// performing endianness conversions as necessary.
|
||||||
unsafe fn process_output_callback<A, B, D, F, G>(
|
unsafe fn process_output_callback<A, B, D, F>(
|
||||||
callback: &mut D,
|
callback: &mut D,
|
||||||
interleaved: &mut [u8],
|
interleaved: &mut [u8],
|
||||||
silence_asio_buffer: bool,
|
silence_asio_buffer: bool,
|
||||||
asio_stream: &sys::AsioStream,
|
asio_stream: &sys::AsioStream,
|
||||||
buffer_index: usize,
|
buffer_index: usize,
|
||||||
to_asio_sample: F,
|
to_endianness: F,
|
||||||
to_endianness: G,
|
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
A: InterleavedSample,
|
A: Sample,
|
||||||
B: AsioSample,
|
B: AsioSample,
|
||||||
D: FnMut(StreamData) + Send + 'static,
|
D: FnMut(OutputData<A>) + Send + 'static,
|
||||||
F: Fn(A) -> B,
|
F: Fn(B) -> B,
|
||||||
G: Fn(B) -> B,
|
|
||||||
{
|
{
|
||||||
// 1. Render interleaved buffer from callback.
|
// 1. Render interleaved buffer from callback.
|
||||||
let interleaved: &mut [A] = cast_slice_mut(interleaved);
|
let interleaved: &mut [A] = cast_slice_mut(interleaved);
|
||||||
let buffer = A::unknown_type_output_buffer(interleaved);
|
callback(OutputData { buffer: interleaved });
|
||||||
callback(StreamData::Output { buffer });
|
|
||||||
|
|
||||||
// 2. Silence ASIO channels if necessary.
|
// 2. Silence ASIO channels if necessary.
|
||||||
let n_channels = interleaved.len() / asio_stream.buffer_size as usize;
|
let n_channels = interleaved.len() / asio_stream.buffer_size as usize;
|
||||||
|
@ -341,31 +330,29 @@ impl Device {
|
||||||
let asio_channel =
|
let asio_channel =
|
||||||
asio_channel_slice_mut::<B>(asio_stream, buffer_index, ch_ix);
|
asio_channel_slice_mut::<B>(asio_stream, buffer_index, ch_ix);
|
||||||
for (frame, s_asio) in interleaved.chunks(n_channels).zip(asio_channel) {
|
for (frame, s_asio) in interleaved.chunks(n_channels).zip(asio_channel) {
|
||||||
*s_asio = *s_asio + to_endianness(to_asio_sample(frame[ch_ix]));
|
*s_asio = *s_asio + to_endianness(B::from_cpal_sample(&frame[ch_ix]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match (data_type, &stream_type) {
|
match (data_type, &stream_type) {
|
||||||
(SampleFormat::I16, &sys::AsioSampleType::ASIOSTInt16LSB) => {
|
(SampleFormat::I16, &sys::AsioSampleType::ASIOSTInt16LSB) => {
|
||||||
process_output_callback::<i16, i16, _, _, _>(
|
process_output_callback::<T, i16, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
&mut interleaved,
|
&mut interleaved,
|
||||||
silence,
|
silence,
|
||||||
asio_stream,
|
asio_stream,
|
||||||
buffer_index as usize,
|
buffer_index as usize,
|
||||||
std::convert::identity::<i16>,
|
|
||||||
to_le,
|
to_le,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
(SampleFormat::I16, &sys::AsioSampleType::ASIOSTInt16MSB) => {
|
(SampleFormat::I16, &sys::AsioSampleType::ASIOSTInt16MSB) => {
|
||||||
process_output_callback::<i16, i16, _, _, _>(
|
process_output_callback::<T, i16, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
&mut interleaved,
|
&mut interleaved,
|
||||||
silence,
|
silence,
|
||||||
asio_stream,
|
asio_stream,
|
||||||
buffer_index as usize,
|
buffer_index as usize,
|
||||||
std::convert::identity::<i16>,
|
|
||||||
to_be,
|
to_be,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -374,14 +361,13 @@ impl Device {
|
||||||
// trait for the `to_le` and `to_be` methods, but this does not support floats.
|
// trait for the `to_le` and `to_be` methods, but this does not support floats.
|
||||||
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat32LSB) |
|
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat32LSB) |
|
||||||
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat32MSB) => {
|
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat32MSB) => {
|
||||||
process_output_callback::<f32, f32, _, _, _>(
|
process_output_callback::<T, f32, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
&mut interleaved,
|
&mut interleaved,
|
||||||
silence,
|
silence,
|
||||||
asio_stream,
|
asio_stream,
|
||||||
buffer_index as usize,
|
buffer_index as usize,
|
||||||
std::convert::identity::<f32>,
|
std::convert::identity::<f32>,
|
||||||
std::convert::identity::<f32>,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,24 +375,22 @@ impl Device {
|
||||||
// `process_output_callback` function above by removing the unnecessary sample
|
// `process_output_callback` function above by removing the unnecessary sample
|
||||||
// conversion function.
|
// conversion function.
|
||||||
(SampleFormat::I16, &sys::AsioSampleType::ASIOSTInt32LSB) => {
|
(SampleFormat::I16, &sys::AsioSampleType::ASIOSTInt32LSB) => {
|
||||||
process_output_callback::<i16, i32, _, _, _>(
|
process_output_callback::<T, i32, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
&mut interleaved,
|
&mut interleaved,
|
||||||
silence,
|
silence,
|
||||||
asio_stream,
|
asio_stream,
|
||||||
buffer_index as usize,
|
buffer_index as usize,
|
||||||
|s| (s as i32) << 16,
|
|
||||||
to_le,
|
to_le,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
(SampleFormat::I16, &sys::AsioSampleType::ASIOSTInt32MSB) => {
|
(SampleFormat::I16, &sys::AsioSampleType::ASIOSTInt32MSB) => {
|
||||||
process_output_callback::<i16, i32, _, _, _>(
|
process_output_callback::<T, i32, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
&mut interleaved,
|
&mut interleaved,
|
||||||
silence,
|
silence,
|
||||||
asio_stream,
|
asio_stream,
|
||||||
buffer_index as usize,
|
buffer_index as usize,
|
||||||
|s| (s as i32) << 16,
|
|
||||||
to_be,
|
to_be,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -414,13 +398,12 @@ impl Device {
|
||||||
// trait for the `to_le` and `to_be` methods, but this does not support floats.
|
// trait for the `to_le` and `to_be` methods, but this does not support floats.
|
||||||
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat64LSB) |
|
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat64LSB) |
|
||||||
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat64MSB) => {
|
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat64MSB) => {
|
||||||
process_output_callback::<f32, f64, _, _, _>(
|
process_output_callback::<T, f64, _, _>(
|
||||||
&mut data_callback,
|
&mut data_callback,
|
||||||
&mut interleaved,
|
&mut interleaved,
|
||||||
silence,
|
silence,
|
||||||
asio_stream,
|
asio_stream,
|
||||||
buffer_index as usize,
|
buffer_index as usize,
|
||||||
|s| s as f64,
|
|
||||||
std::convert::identity::<f64>,
|
std::convert::identity::<f64>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -549,33 +532,45 @@ impl Silence for f64 {
|
||||||
const SILENCE: Self = 0.0;
|
const SILENCE: Self = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InterleavedSample for i16 {
|
impl AsioSample for i16 {
|
||||||
fn unknown_type_input_buffer(buffer: &[Self]) -> UnknownTypeInputBuffer {
|
fn to_cpal_sample<T: Sample>(&self) -> T {
|
||||||
UnknownTypeInputBuffer::I16(::InputBuffer { buffer })
|
T::from(self)
|
||||||
}
|
}
|
||||||
|
fn from_cpal_sample<T: Sample>(t: &T) -> Self {
|
||||||
fn unknown_type_output_buffer(buffer: &mut [Self]) -> UnknownTypeOutputBuffer {
|
Sample::from(t)
|
||||||
UnknownTypeOutputBuffer::I16(::OutputBuffer { buffer })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InterleavedSample for f32 {
|
impl AsioSample for i32 {
|
||||||
fn unknown_type_input_buffer(buffer: &[Self]) -> UnknownTypeInputBuffer {
|
fn to_cpal_sample<T: Sample>(&self) -> T {
|
||||||
UnknownTypeInputBuffer::F32(::InputBuffer { buffer })
|
let s = (*self >> 16) as i16;
|
||||||
|
s.to_cpal_sample()
|
||||||
}
|
}
|
||||||
|
fn from_cpal_sample<T: Sample>(t: &T) -> Self {
|
||||||
fn unknown_type_output_buffer(buffer: &mut [Self]) -> UnknownTypeOutputBuffer {
|
let s = i16::from_cpal_sample(t);
|
||||||
UnknownTypeOutputBuffer::F32(::OutputBuffer { buffer })
|
(s as i32) << 16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsioSample for i16 {}
|
impl AsioSample for f32 {
|
||||||
|
fn to_cpal_sample<T: Sample>(&self) -> T {
|
||||||
|
T::from(self)
|
||||||
|
}
|
||||||
|
fn from_cpal_sample<T: Sample>(t: &T) -> Self {
|
||||||
|
Sample::from(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AsioSample for i32 {}
|
impl AsioSample for f64 {
|
||||||
|
fn to_cpal_sample<T: Sample>(&self) -> T {
|
||||||
impl AsioSample for f32 {}
|
let f = *self as f32;
|
||||||
|
f.to_cpal_sample()
|
||||||
impl AsioSample for f64 {}
|
}
|
||||||
|
fn from_cpal_sample<T: Sample>(t: &T) -> Self {
|
||||||
|
let f = f32::from_cpal_sample(t);
|
||||||
|
f as f64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Check whether or not the desired format is supported by the stream.
|
/// Check whether or not the desired format is supported by the stream.
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in New Issue