use std::sync::Arc;
use std::time::Instant;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct Sample(pub i32);
impl Sample {
pub const MAX: Self = Self(8_388_607);
pub const MIN: Self = Self(-8_388_608);
pub const ZERO: Self = Self(0);
#[inline]
pub fn from_i16(s: i16) -> Self {
Self((s as i32) << 8)
}
#[inline]
pub fn from_i24_le(bytes: [u8; 3]) -> Self {
let val = (bytes[0] as i32) | ((bytes[1] as i32) << 8) | ((bytes[2] as i32) << 16);
let extended = if val & 0x00800000 != 0 {
val | 0xFF000000u32 as i32 } else {
val };
Self(extended)
}
#[inline]
pub fn from_i24_be(bytes: [u8; 3]) -> Self {
let val = ((bytes[0] as i32) << 16) | ((bytes[1] as i32) << 8) | (bytes[2] as i32);
let extended = if val & 0x00800000 != 0 {
val | 0xFF000000u32 as i32 } else {
val };
Self(extended)
}
#[inline]
pub fn to_i16(self) -> i16 {
(self.0 >> 8) as i16
}
#[inline]
pub fn to_f32(self) -> f32 {
self.0 as f32 / 8_388_608.0
}
#[inline]
pub fn clamp(self) -> Self {
Self(self.0.clamp(Self::MIN.0, Self::MAX.0))
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Codec {
Pcm,
Opus,
Flac,
Mp3,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AudioFormat {
pub codec: Codec,
pub sample_rate: u32,
pub channels: u8,
pub bit_depth: u8,
pub codec_header: Option<Vec<u8>>,
}
impl AudioFormat {
pub fn duration_us(&self, num_samples: usize) -> i64 {
debug_assert!(self.channels > 0, "AudioFormat with 0 channels");
debug_assert!(self.sample_rate > 0, "AudioFormat with 0 sample_rate");
let frames = num_samples / self.channels.max(1) as usize;
let rate = self.sample_rate.max(1) as i64;
(frames as i64 * 1_000_000 + rate / 2) / rate
}
}
pub struct AudioBuffer {
pub timestamp: i64,
pub play_at: Instant,
pub samples: Arc<[Sample]>,
pub format: AudioFormat,
}
impl AudioBuffer {
pub fn duration_us(&self) -> i64 {
self.format.duration_us(self.samples.len())
}
}