From b0b0484d4b225fe4b53e7d34bd5a293d5c1df969 Mon Sep 17 00:00:00 2001 From: Tom Gowan Date: Thu, 1 Nov 2018 17:58:50 +1100 Subject: [PATCH] endian conversion --- Cargo.toml | 1 + src/platform/windows/asio/device.rs | 2 +- src/platform/windows/asio/stream.rs | 105 ++++++++++++++++++++++++---- 3 files changed, 92 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d7f234d..7b1f2dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ keywords = ["audio", "sound"] [dependencies] failure = "0.1.5" lazy_static = "1.3" +num-traits = "0.2.6" [dev-dependencies] hound = "3.4" diff --git a/src/platform/windows/asio/device.rs b/src/platform/windows/asio/device.rs index b354d57..7b03eb2 100644 --- a/src/platform/windows/asio/device.rs +++ b/src/platform/windows/asio/device.rs @@ -62,9 +62,9 @@ impl Device { let sample_rate = SampleRate(self.drivers.get_sample_rate().rate); match self.drivers.get_data_type() { Ok(sys::AsioSampleType::ASIOSTInt16MSB) => Ok(SampleFormat::I16), + Ok(sys::AsioSampleType::ASIOSTInt32MSB) => Ok(SampleFormat::I16), Ok(sys::AsioSampleType::ASIOSTFloat32MSB) => Ok(SampleFormat::F32), Ok(sys::AsioSampleType::ASIOSTInt16LSB) => Ok(SampleFormat::I16), - // TODO This should not be set to 16bit but is for testing Ok(sys::AsioSampleType::ASIOSTInt32LSB) => Ok(SampleFormat::I16), Ok(sys::AsioSampleType::ASIOSTFloat32LSB) => Ok(SampleFormat::F32), _ => Err(DefaultFormatError::StreamTypeNotSupported), diff --git a/src/platform/windows/asio/stream.rs b/src/platform/windows/asio/stream.rs index 66ca056..0920a58 100644 --- a/src/platform/windows/asio/stream.rs +++ b/src/platform/windows/asio/stream.rs @@ -1,5 +1,5 @@ extern crate asio_sys as sys; - +extern crate num_traits; use std; use Format; @@ -13,6 +13,7 @@ use std::mem; use std::sync::atomic::{AtomicUsize, Ordering}; use SampleFormat; use super::asio_utils as au; +use self::num_traits::PrimInt; pub struct EventLoop { asio_streams: Arc>, @@ -56,6 +57,11 @@ struct Buffers { f32_buff: F32Buffer, } +enum Endian { + Little, + Big, +} + impl EventLoop { pub fn new() -> EventLoop { EventLoop { @@ -199,9 +205,12 @@ impl EventLoop { $AsioTypeIdent:ident, $Buffers:expr, $BuffersType:ty, - $BuffersTypeIdent:ident + $BuffersTypeIdent:ident, + $Endianness:expr, + $ConvertEndian:expr ) => { + // For each channel write the cpal data to // the asio buffer // Also need to check for Endian @@ -215,9 +224,10 @@ impl EventLoop { buff_ptr, asio_stream.buffer_size as usize); for asio_s in asio_buffer.iter(){ - channel.push( (*asio_s as i64 * + channel.push( $ConvertEndian((*asio_s as i64 * ::std::$SampleTypeIdent::MAX as i64 / - ::std::$AsioTypeIdent::MAX as i64) as $SampleType); + ::std::$AsioTypeIdent::MAX as i64) as $SampleType, + $Endianness)); } } @@ -254,19 +264,43 @@ impl EventLoop { match stream_type { sys::AsioSampleType::ASIOSTInt32LSB => { try_callback!(I16, i16, i16, i32, i32, - buffers.i16_buff, I16Buffer, I16Buffer); + buffers.i16_buff, I16Buffer, I16Buffer, + Endian::Little, convert_endian_to); } sys::AsioSampleType::ASIOSTInt16LSB => { try_callback!(I16, i16, i16, i16, i16, - buffers.i16_buff, I16Buffer, I16Buffer); + buffers.i16_buff, I16Buffer, I16Buffer, + Endian::Little, convert_endian_to); + } + sys::AsioSampleType::ASIOSTInt32MSB => { + try_callback!(I16, i16, i16, i32, i32, + buffers.i16_buff, I16Buffer, I16Buffer, + Endian::Big, convert_endian_to); + } + sys::AsioSampleType::ASIOSTInt16MSB => { + try_callback!(I16, i16, i16, i16, i16, + buffers.i16_buff, I16Buffer, I16Buffer, + Endian::Big, convert_endian_to); } sys::AsioSampleType::ASIOSTFloat32LSB => { try_callback!(F32, f32, f32, f32, f32, - buffers.f32_buff, F32Buffer, F32Buffer); + buffers.f32_buff, F32Buffer, F32Buffer, + Endian::Little, |a, _| a); } sys::AsioSampleType::ASIOSTFloat64LSB => { try_callback!(F32, f32, f32, f64, f64, - buffers.f32_buff, F32Buffer, F32Buffer); + buffers.f32_buff, F32Buffer, F32Buffer, + Endian::Little, |a, _| a); + } + sys::AsioSampleType::ASIOSTFloat32MSB => { + try_callback!(F32, f32, f32, f32, f32, + buffers.f32_buff, F32Buffer, F32Buffer, + Endian::Big, |a, _| a); + } + sys::AsioSampleType::ASIOSTFloat64MSB => { + try_callback!(F32, f32, f32, f64, f64, + buffers.f32_buff, F32Buffer, F32Buffer, + Endian::Big, |a, _| a); } _ => println!("unsupported format {:?}", stream_type), } @@ -363,7 +397,9 @@ pub fn build_output_stream( $AsioTypeIdent:ident, $Buffers:expr, $BuffersType:ty, - $BuffersTypeIdent:ident + $BuffersTypeIdent:ident, + $Endianness:expr, + $ConvertEndian:expr ) => { let mut my_buffers = $Buffers; { @@ -422,9 +458,10 @@ pub fn build_output_stream( for (asio_s, cpal_s) in asio_buffer.iter_mut() .zip(channel){ if silence { *asio_s = 0.0 as $AsioType; } - *asio_s += (*cpal_s as i64 * + *asio_s += $ConvertEndian((*cpal_s as i64 * ::std::$AsioTypeIdent::MAX as i64 / - ::std::$SampleTypeIdent::MAX as i64) as $AsioType; + ::std::$SampleTypeIdent::MAX as i64) as $AsioType, + $Endianness); } } @@ -435,19 +472,43 @@ pub fn build_output_stream( match stream_type { sys::AsioSampleType::ASIOSTInt32LSB => { try_callback!(I16, i16, i16, i32, i32, - &mut re_buffers.i16_buff, I16Buffer, I16Buffer); + &mut re_buffers.i16_buff, I16Buffer, I16Buffer, + Endian::Little, convert_endian_from); } sys::AsioSampleType::ASIOSTInt16LSB => { try_callback!(I16, i16, i16, i16, i16, - &mut re_buffers.i16_buff, I16Buffer, I16Buffer); + &mut re_buffers.i16_buff, I16Buffer, I16Buffer, + Endian::Little, convert_endian_from); + } + sys::AsioSampleType::ASIOSTInt32MSB => { + try_callback!(I16, i16, i16, i32, i32, + &mut re_buffers.i16_buff, I16Buffer, I16Buffer, + Endian::Big, convert_endian_from); + } + sys::AsioSampleType::ASIOSTInt16MSB => { + try_callback!(I16, i16, i16, i16, i16, + &mut re_buffers.i16_buff, I16Buffer, I16Buffer, + Endian::Big, convert_endian_from); } sys::AsioSampleType::ASIOSTFloat32LSB => { try_callback!(F32, f32, f32, f32, f32, - &mut re_buffers.f32_buff, F32Buffer, F32Buffer); + &mut re_buffers.f32_buff, F32Buffer, F32Buffer, + Endian::Little, |a, _| a); } sys::AsioSampleType::ASIOSTFloat64LSB => { try_callback!(F32, f32, f32, f64, f64, - &mut re_buffers.f32_buff, F32Buffer, F32Buffer); + &mut re_buffers.f32_buff, F32Buffer, F32Buffer, + Endian::Little, |a, _| a); + } + sys::AsioSampleType::ASIOSTFloat32MSB => { + try_callback!(F32, f32, f32, f32, f32, + &mut re_buffers.f32_buff, F32Buffer, F32Buffer, + Endian::Big, |a, _| a); + } + sys::AsioSampleType::ASIOSTFloat64MSB => { + try_callback!(F32, f32, f32, f64, f64, + &mut re_buffers.f32_buff, F32Buffer, F32Buffer, + Endian::Big, |a, _| a); } _ => println!("unsupported format {:?}", stream_type), } @@ -539,3 +600,17 @@ impl<'a, T> OutputBuffer<'a, T> { pub fn finish(self) {} } + +fn convert_endian_to(sample: T, endian: Endian) -> T { + match endian { + Endian::Big => sample.to_be(), + Endian::Little => sample.to_le(), + } +} + +fn convert_endian_from(sample: T, endian: Endian) -> T { + match endian { + Endian::Big => T::from_be(sample), + Endian::Little => T::from_le(sample), + } +} \ No newline at end of file