#[derive(
Debug, Clone, Copy, PartialEq, Eq, Default, derive_more::Display, derive_more::IsVariant,
)]
#[display("{}", self.as_str())]
pub enum SampleFormat {
#[default]
F32,
I16,
U16,
}
impl SampleFormat {
pub const fn as_str(&self) -> &'static str {
match self {
Self::F32 => "f32",
Self::I16 => "i16",
Self::U16 => "u16",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, derive_more::IsVariant)]
pub enum ChannelLayout {
#[default]
Mono,
Stereo,
Channels(u16),
}
impl ChannelLayout {
#[inline(always)]
#[must_use]
pub fn count(self) -> u16 {
match self {
Self::Mono => 1,
Self::Stereo => 2,
Self::Channels(n) => n,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct PlaybackConfig {
sample_rate: u32,
channels: ChannelLayout,
sample_format: SampleFormat,
buffer_size_frames: Option<u32>,
queue_capacity_frames: usize,
}
impl Default for PlaybackConfig {
fn default() -> Self {
Self::new(24_000, ChannelLayout::Mono, SampleFormat::F32)
}
}
impl PlaybackConfig {
#[must_use]
pub fn new(sample_rate: u32, channels: ChannelLayout, sample_format: SampleFormat) -> Self {
Self {
sample_rate,
channels,
sample_format,
buffer_size_frames: None,
queue_capacity_frames: (sample_rate as usize) * 4,
}
}
#[must_use]
pub fn with_buffer_size_frames(mut self, frames: u32) -> Self {
self.buffer_size_frames = Some(frames);
self
}
#[must_use]
pub fn with_queue_capacity_frames(mut self, frames: usize) -> Self {
self.queue_capacity_frames = frames;
self
}
#[must_use]
pub fn mono(sample_rate: u32) -> Self {
Self::new(sample_rate, ChannelLayout::Mono, SampleFormat::F32)
}
#[must_use]
pub fn stereo(sample_rate: u32) -> Self {
Self::new(sample_rate, ChannelLayout::Stereo, SampleFormat::F32)
}
#[inline(always)]
pub fn sample_rate(&self) -> u32 {
self.sample_rate
}
#[inline(always)]
pub fn channels(&self) -> ChannelLayout {
self.channels
}
#[inline(always)]
pub fn sample_format(&self) -> SampleFormat {
self.sample_format
}
#[inline(always)]
pub fn buffer_size_frames(&self) -> Option<u32> {
self.buffer_size_frames
}
#[inline(always)]
pub fn queue_capacity_frames(&self) -> usize {
self.queue_capacity_frames
}
pub fn cpal_config(&self) -> crate::error::Result<cpal::StreamConfig> {
let channels = self.channels.count();
if channels == 0 {
return Err(crate::error::Error::InvariantViolation(
crate::error::InvariantViolationPayload::new(
"PlaybackConfig::cpal_config",
"channel count must be >= 1",
),
));
}
let buffer_size = match self.buffer_size_frames {
Some(n) => cpal::BufferSize::Fixed(n),
None => cpal::BufferSize::Default,
};
Ok(cpal::StreamConfig {
channels,
sample_rate: self.sample_rate,
buffer_size,
})
}
}