endian conversion
This commit is contained in:
parent
5ec6da3aad
commit
b0b0484d4b
|
@ -11,6 +11,7 @@ keywords = ["audio", "sound"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
failure = "0.1.5"
|
failure = "0.1.5"
|
||||||
lazy_static = "1.3"
|
lazy_static = "1.3"
|
||||||
|
num-traits = "0.2.6"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hound = "3.4"
|
hound = "3.4"
|
||||||
|
|
|
@ -62,9 +62,9 @@ impl Device {
|
||||||
let sample_rate = SampleRate(self.drivers.get_sample_rate().rate);
|
let sample_rate = SampleRate(self.drivers.get_sample_rate().rate);
|
||||||
match self.drivers.get_data_type() {
|
match self.drivers.get_data_type() {
|
||||||
Ok(sys::AsioSampleType::ASIOSTInt16MSB) => Ok(SampleFormat::I16),
|
Ok(sys::AsioSampleType::ASIOSTInt16MSB) => Ok(SampleFormat::I16),
|
||||||
|
Ok(sys::AsioSampleType::ASIOSTInt32MSB) => Ok(SampleFormat::I16),
|
||||||
Ok(sys::AsioSampleType::ASIOSTFloat32MSB) => Ok(SampleFormat::F32),
|
Ok(sys::AsioSampleType::ASIOSTFloat32MSB) => Ok(SampleFormat::F32),
|
||||||
Ok(sys::AsioSampleType::ASIOSTInt16LSB) => Ok(SampleFormat::I16),
|
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::ASIOSTInt32LSB) => Ok(SampleFormat::I16),
|
||||||
Ok(sys::AsioSampleType::ASIOSTFloat32LSB) => Ok(SampleFormat::F32),
|
Ok(sys::AsioSampleType::ASIOSTFloat32LSB) => Ok(SampleFormat::F32),
|
||||||
_ => Err(DefaultFormatError::StreamTypeNotSupported),
|
_ => Err(DefaultFormatError::StreamTypeNotSupported),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
extern crate asio_sys as sys;
|
extern crate asio_sys as sys;
|
||||||
|
extern crate num_traits;
|
||||||
|
|
||||||
use std;
|
use std;
|
||||||
use Format;
|
use Format;
|
||||||
|
@ -13,6 +13,7 @@ use std::mem;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use SampleFormat;
|
use SampleFormat;
|
||||||
use super::asio_utils as au;
|
use super::asio_utils as au;
|
||||||
|
use self::num_traits::PrimInt;
|
||||||
|
|
||||||
pub struct EventLoop {
|
pub struct EventLoop {
|
||||||
asio_streams: Arc<Mutex<sys::AsioStreams>>,
|
asio_streams: Arc<Mutex<sys::AsioStreams>>,
|
||||||
|
@ -56,6 +57,11 @@ struct Buffers {
|
||||||
f32_buff: F32Buffer,
|
f32_buff: F32Buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Endian {
|
||||||
|
Little,
|
||||||
|
Big,
|
||||||
|
}
|
||||||
|
|
||||||
impl EventLoop {
|
impl EventLoop {
|
||||||
pub fn new() -> EventLoop {
|
pub fn new() -> EventLoop {
|
||||||
EventLoop {
|
EventLoop {
|
||||||
|
@ -199,9 +205,12 @@ impl EventLoop {
|
||||||
$AsioTypeIdent:ident,
|
$AsioTypeIdent:ident,
|
||||||
$Buffers:expr,
|
$Buffers:expr,
|
||||||
$BuffersType:ty,
|
$BuffersType:ty,
|
||||||
$BuffersTypeIdent:ident
|
$BuffersTypeIdent:ident,
|
||||||
|
$Endianness:expr,
|
||||||
|
$ConvertEndian:expr
|
||||||
) => {
|
) => {
|
||||||
|
|
||||||
|
|
||||||
// For each channel write the cpal data to
|
// For each channel write the cpal data to
|
||||||
// the asio buffer
|
// the asio buffer
|
||||||
// Also need to check for Endian
|
// Also need to check for Endian
|
||||||
|
@ -215,9 +224,10 @@ impl EventLoop {
|
||||||
buff_ptr,
|
buff_ptr,
|
||||||
asio_stream.buffer_size as usize);
|
asio_stream.buffer_size as usize);
|
||||||
for asio_s in asio_buffer.iter(){
|
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::$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 {
|
match stream_type {
|
||||||
sys::AsioSampleType::ASIOSTInt32LSB => {
|
sys::AsioSampleType::ASIOSTInt32LSB => {
|
||||||
try_callback!(I16, i16, i16, i32, i32,
|
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 => {
|
sys::AsioSampleType::ASIOSTInt16LSB => {
|
||||||
try_callback!(I16, i16, i16, i16, i16,
|
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 => {
|
sys::AsioSampleType::ASIOSTFloat32LSB => {
|
||||||
try_callback!(F32, f32, f32, f32, f32,
|
try_callback!(F32, f32, f32, f32, f32,
|
||||||
buffers.f32_buff, F32Buffer, F32Buffer);
|
buffers.f32_buff, F32Buffer, F32Buffer,
|
||||||
|
Endian::Little, |a, _| a);
|
||||||
}
|
}
|
||||||
sys::AsioSampleType::ASIOSTFloat64LSB => {
|
sys::AsioSampleType::ASIOSTFloat64LSB => {
|
||||||
try_callback!(F32, f32, f32, f64, f64,
|
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),
|
_ => println!("unsupported format {:?}", stream_type),
|
||||||
}
|
}
|
||||||
|
@ -363,7 +397,9 @@ pub fn build_output_stream(
|
||||||
$AsioTypeIdent:ident,
|
$AsioTypeIdent:ident,
|
||||||
$Buffers:expr,
|
$Buffers:expr,
|
||||||
$BuffersType:ty,
|
$BuffersType:ty,
|
||||||
$BuffersTypeIdent:ident
|
$BuffersTypeIdent:ident,
|
||||||
|
$Endianness:expr,
|
||||||
|
$ConvertEndian:expr
|
||||||
) => {
|
) => {
|
||||||
let mut my_buffers = $Buffers;
|
let mut my_buffers = $Buffers;
|
||||||
{
|
{
|
||||||
|
@ -422,9 +458,10 @@ pub fn build_output_stream(
|
||||||
for (asio_s, cpal_s) in asio_buffer.iter_mut()
|
for (asio_s, cpal_s) in asio_buffer.iter_mut()
|
||||||
.zip(channel){
|
.zip(channel){
|
||||||
if silence { *asio_s = 0.0 as $AsioType; }
|
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::$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 {
|
match stream_type {
|
||||||
sys::AsioSampleType::ASIOSTInt32LSB => {
|
sys::AsioSampleType::ASIOSTInt32LSB => {
|
||||||
try_callback!(I16, i16, i16, i32, i32,
|
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 => {
|
sys::AsioSampleType::ASIOSTInt16LSB => {
|
||||||
try_callback!(I16, i16, i16, i16, i16,
|
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 => {
|
sys::AsioSampleType::ASIOSTFloat32LSB => {
|
||||||
try_callback!(F32, f32, f32, f32, f32,
|
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 => {
|
sys::AsioSampleType::ASIOSTFloat64LSB => {
|
||||||
try_callback!(F32, f32, f32, f64, f64,
|
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),
|
_ => println!("unsupported format {:?}", stream_type),
|
||||||
}
|
}
|
||||||
|
@ -539,3 +600,17 @@ impl<'a, T> OutputBuffer<'a, T> {
|
||||||
|
|
||||||
pub fn finish(self) {}
|
pub fn finish(self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn convert_endian_to<T: PrimInt>(sample: T, endian: Endian) -> T {
|
||||||
|
match endian {
|
||||||
|
Endian::Big => sample.to_be(),
|
||||||
|
Endian::Little => sample.to_le(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_endian_from<T: PrimInt>(sample: T, endian: Endian) -> T {
|
||||||
|
match endian {
|
||||||
|
Endian::Big => T::from_be(sample),
|
||||||
|
Endian::Little => T::from_le(sample),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue