sim_lib_stream_audio/spec.rs
1use sim_kernel::{Error, Result};
2pub use sim_lib_stream_core::PcmSampleFormat;
3
4/// Audio format description for a PCM stream: channel count, sample rate, and
5/// sample encoding.
6///
7/// A `PcmSpec` is the validated, immutable contract shared by PCM buffers,
8/// sources, and sinks. It is constructed through [`PcmSpec::i16`] or
9/// [`PcmSpec::f32`], which reject a zero channel count or zero sample rate, so a
10/// constructed value is always a usable audio configuration.
11///
12/// # Examples
13///
14/// ```
15/// use sim_lib_stream_audio::{PcmSampleFormat, PcmSpec};
16///
17/// let spec = PcmSpec::f32(2, 48_000)?;
18/// assert_eq!(spec.channels(), 2);
19/// assert_eq!(spec.sample_rate_hz(), 48_000);
20/// assert_eq!(spec.sample_format(), PcmSampleFormat::F32);
21/// # Ok::<(), sim_kernel::Error>(())
22/// ```
23#[derive(Clone, Copy, Debug, PartialEq, Eq)]
24pub struct PcmSpec {
25 channels: usize,
26 sample_rate_hz: u32,
27 sample_format: PcmSampleFormat,
28}
29
30impl PcmSpec {
31 /// Builds an interleaved 16-bit signed integer ([`PcmSampleFormat::I16`])
32 /// spec.
33 ///
34 /// Returns an error when `channels` or `sample_rate_hz` is zero.
35 pub fn i16(channels: usize, sample_rate_hz: u32) -> Result<Self> {
36 if channels == 0 {
37 return Err(Error::Eval(
38 "PCM spec channel count must be greater than zero".to_owned(),
39 ));
40 }
41 if sample_rate_hz == 0 {
42 return Err(Error::Eval(
43 "PCM spec sample rate must be greater than zero".to_owned(),
44 ));
45 }
46 Ok(Self {
47 channels,
48 sample_rate_hz,
49 sample_format: PcmSampleFormat::I16,
50 })
51 }
52
53 /// Builds an interleaved 32-bit float ([`PcmSampleFormat::F32`]) spec.
54 ///
55 /// Returns an error when `channels` or `sample_rate_hz` is zero.
56 pub fn f32(channels: usize, sample_rate_hz: u32) -> Result<Self> {
57 if channels == 0 {
58 return Err(Error::Eval(
59 "PCM spec channel count must be greater than zero".to_owned(),
60 ));
61 }
62 if sample_rate_hz == 0 {
63 return Err(Error::Eval(
64 "PCM spec sample rate must be greater than zero".to_owned(),
65 ));
66 }
67 Ok(Self {
68 channels,
69 sample_rate_hz,
70 sample_format: PcmSampleFormat::F32,
71 })
72 }
73
74 /// Returns the number of interleaved audio channels.
75 pub fn channels(self) -> usize {
76 self.channels
77 }
78
79 /// Returns the sample rate in hertz (frames per second).
80 pub fn sample_rate_hz(self) -> u32 {
81 self.sample_rate_hz
82 }
83
84 /// Returns the per-sample encoding.
85 pub fn sample_format(self) -> PcmSampleFormat {
86 self.sample_format
87 }
88}