use crate::{_impl_init, AudioChannels, PcmSample, impl_trait};
#[doc = crate::_tags!(audio)]
#[doc = crate::_doc_meta!{
location("media/audio"),
test_size_of(PcmSpec = 8|64),
}]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PcmSpec {
pub sample: PcmSample,
pub channels: AudioChannels,
pub sample_rate: u32,
}
_impl_init![Self::new(PcmSample::INIT, AudioChannels::INIT, 0) => PcmSpec];
impl_trait![fmt::Display for PcmSpec |self, f| {
write!(f, "{}/{}@{}Hz", self.sample, self.channels, self.sample_rate)
}];
impl PcmSpec {
#[must_use]
pub const fn new(sample: PcmSample, channels: AudioChannels, sample_rate: u32) -> Self {
Self { sample, channels, sample_rate }
}
#[must_use]
pub const fn channel_count(self) -> usize {
self.channels.channels() as usize
}
#[must_use]
pub const fn frame_bytes(self) -> usize {
self.sample.bytes() * self.channel_count()
}
#[must_use]
pub const fn has_valid_rate(self) -> bool {
self.sample_rate != 0
}
#[must_use]
pub const fn is_valid(self) -> bool {
self.channel_count() != 0 && self.sample_rate != 0 && self.frame_bytes() != 0
}
pub const fn frames_for_data_len(self, data_len: usize) -> Option<usize> {
let frame_bytes = self.frame_bytes();
if frame_bytes == 0 || !data_len.is_multiple_of(frame_bytes) {
None
} else {
Some(data_len / frame_bytes)
}
}
#[must_use]
pub const fn has_complete_frames_for_data_len(self, data_len: usize) -> bool {
self.frames_for_data_len(data_len).is_some()
}
}