use super::audio_format::{self, LinearPcmFlags};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum SampleFormat {
F32,
I32,
I24,
I16,
I8,
}
impl SampleFormat {
pub fn does_match_flags(&self, flags: audio_format::LinearPcmFlags) -> bool {
let is_float = flags.contains(LinearPcmFlags::IS_FLOAT);
let is_signed_integer = flags.contains(LinearPcmFlags::IS_SIGNED_INTEGER);
let is_packed = flags.contains(LinearPcmFlags::IS_PACKED);
match *self {
SampleFormat::F32 => is_float && !is_signed_integer && is_packed,
SampleFormat::I32 | SampleFormat::I16 | SampleFormat::I8 => {
is_signed_integer && !is_float && is_packed
}
SampleFormat::I24 => is_signed_integer && !is_float,
}
}
pub fn from_flags_and_bits_per_sample(
flags: audio_format::LinearPcmFlags,
bits_per_sample: u32,
) -> Option<Self> {
let packed = flags.contains(LinearPcmFlags::IS_PACKED);
let sample_format = if flags.contains(LinearPcmFlags::IS_FLOAT) {
match (bits_per_sample, packed) {
(32, true) => SampleFormat::F32,
_ => return None,
}
} else if flags.contains(LinearPcmFlags::IS_SIGNED_INTEGER) {
match (bits_per_sample, packed) {
(8, true) => SampleFormat::I8,
(16, true) => SampleFormat::I16,
(24, _) => SampleFormat::I24,
(32, true) => SampleFormat::I32,
_ => return None,
}
} else {
return None;
};
Some(sample_format)
}
pub fn size_in_bytes(&self) -> usize {
use std::mem::size_of;
match *self {
SampleFormat::F32 => size_of::<f32>(),
SampleFormat::I32 => size_of::<i32>(),
SampleFormat::I24 => 3 * size_of::<u8>(),
SampleFormat::I16 => size_of::<i16>(),
SampleFormat::I8 => size_of::<i8>(),
}
}
pub fn size_in_bits(&self) -> u32 {
match *self {
SampleFormat::F32 => 32,
SampleFormat::I32 => 32,
SampleFormat::I24 => 24,
SampleFormat::I16 => 16,
SampleFormat::I8 => 8,
}
}
}
pub trait Sample {
fn sample_format() -> SampleFormat;
}
macro_rules! impl_sample {
($($T:ident $format:ident),* $(,)*) => {
$(
impl Sample for $T {
fn sample_format() -> SampleFormat {
SampleFormat::$format
}
}
)*
}
}
impl_sample!(f32 F32, i32 I32, i16 I16, i8 I8);