pagurus/
audio.rs

1use crate::Result;
2use orfail::Failure;
3
4#[derive(Debug, Default)]
5pub struct AudioData<B = Vec<u8>> {
6    spec: AudioSpec,
7    data: B,
8}
9
10impl AudioData<Vec<u8>> {
11    pub fn new(spec: AudioSpec) -> Self {
12        Self {
13            spec,
14            data: vec![0; spec.data_samples * spec.sample_format.bytes()],
15        }
16    }
17
18    #[inline]
19    pub fn write_sample(&mut self, i: usize, sample: impl Into<Sample>) {
20        let sample = sample.into();
21        match self.spec.sample_format {
22            SampleFormat::I16Be => {
23                self.data[i * 2..][..2].copy_from_slice(&sample.to_i16().to_be_bytes());
24            }
25            SampleFormat::I16Le => {
26                self.data[i * 2..][..2].copy_from_slice(&sample.to_i16().to_le_bytes());
27            }
28            SampleFormat::F32Be => {
29                self.data[i * 4..][..4].copy_from_slice(&sample.to_f32().to_be_bytes());
30            }
31            SampleFormat::F32Le => {
32                self.data[i * 4..][..4].copy_from_slice(&sample.to_f32().to_le_bytes());
33            }
34        }
35    }
36
37    pub fn bytes_mut(&mut self) -> &mut [u8] {
38        self.data.as_mut()
39    }
40
41    pub fn as_ref(&self) -> AudioData<&[u8]> {
42        AudioData {
43            spec: self.spec,
44            data: &self.data,
45        }
46    }
47}
48
49impl<B: AsRef<[u8]>> AudioData<B> {
50    pub fn spec(&self) -> AudioSpec {
51        self.spec
52    }
53
54    pub fn samples(&self) -> Samples {
55        Samples {
56            spec: self.spec,
57            data: self.data.as_ref(),
58        }
59    }
60
61    pub fn bytes(&self) -> &[u8] {
62        self.data.as_ref()
63    }
64}
65
66#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
67#[cfg_attr(
68    feature = "serde",
69    derive(serde::Serialize, serde::Deserialize),
70    serde(rename_all = "camelCase")
71)]
72pub struct AudioSpec {
73    pub sample_format: SampleFormat,
74    pub sample_rate: u16,
75    pub data_samples: usize,
76}
77
78impl AudioSpec {
79    pub const CHANNELS: u8 = 1;
80}
81
82#[derive(Debug)]
83pub struct Samples<'a> {
84    spec: AudioSpec,
85    data: &'a [u8],
86}
87
88impl<'a> Samples<'a> {
89    pub fn len(&self) -> usize {
90        self.spec.data_samples
91    }
92
93    pub fn is_empty(&self) -> bool {
94        self.len() == 0
95    }
96}
97
98impl<'a> Iterator for Samples<'a> {
99    type Item = Sample;
100
101    fn next(&mut self) -> Option<Self::Item> {
102        if self.data.is_empty() {
103            return None;
104        }
105
106        match self.spec.sample_format {
107            SampleFormat::I16Be => {
108                let v = i16::from_be_bytes([self.data[0], self.data[1]]);
109                self.data = &self.data[2..];
110                Some(Sample::I16(v))
111            }
112            SampleFormat::I16Le => {
113                let v = i16::from_le_bytes([self.data[0], self.data[1]]);
114                self.data = &self.data[2..];
115                Some(Sample::I16(v))
116            }
117            SampleFormat::F32Be => {
118                let v =
119                    f32::from_be_bytes([self.data[0], self.data[1], self.data[2], self.data[3]]);
120                self.data = &self.data[4..];
121                Some(Sample::F32(v))
122            }
123            SampleFormat::F32Le => {
124                let v =
125                    f32::from_le_bytes([self.data[0], self.data[1], self.data[2], self.data[3]]);
126                self.data = &self.data[4..];
127                Some(Sample::F32(v))
128            }
129        }
130    }
131}
132
133#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, Hash)]
134#[cfg_attr(
135    feature = "serde",
136    derive(serde::Serialize, serde::Deserialize),
137    serde(rename_all = "UPPERCASE")
138)]
139pub enum SampleFormat {
140    #[default]
141    I16Be = 0,
142    I16Le = 1,
143    F32Be = 2,
144    F32Le = 3,
145}
146
147impl SampleFormat {
148    pub const fn bytes(self) -> usize {
149        match self {
150            SampleFormat::I16Be => 2,
151            SampleFormat::I16Le => 2,
152            SampleFormat::F32Be => 4,
153            SampleFormat::F32Le => 4,
154        }
155    }
156
157    pub const fn as_u8(self) -> u8 {
158        self as u8
159    }
160
161    pub fn from_u8(x: u8) -> Result<Self> {
162        match x {
163            0 => Ok(Self::I16Be),
164            1 => Ok(Self::I16Le),
165            2 => Ok(Self::F32Be),
166            3 => Ok(Self::F32Le),
167            _ => Err(Failure::new(format!("unknown audio sample format: {x}"))),
168        }
169    }
170}
171
172#[derive(Debug, Clone, Copy)]
173pub enum Sample {
174    I16(i16),
175    F32(f32),
176}
177
178impl Sample {
179    #[inline]
180    pub fn to_i16(self) -> i16 {
181        match self {
182            Sample::I16(v) => v,
183            Sample::F32(v) => {
184                let v = v.clamp(-1.0, 1.0);
185                if v < 0.0 {
186                    (-v * f32::from(i16::MIN)) as i16
187                } else {
188                    (v * f32::from(i16::MAX)) as i16
189                }
190            }
191        }
192    }
193
194    #[inline]
195    pub fn to_f32(self) -> f32 {
196        match self {
197            Sample::F32(v) => v,
198            Sample::I16(v) => {
199                if v < 0 {
200                    -f32::from(v) / f32::from(i16::MIN)
201                } else {
202                    f32::from(v) / f32::from(i16::MAX)
203                }
204            }
205        }
206    }
207}
208
209impl From<i16> for Sample {
210    fn from(value: i16) -> Self {
211        Self::I16(value)
212    }
213}
214
215impl From<f32> for Sample {
216    fn from(value: f32) -> Self {
217        Self::F32(value)
218    }
219}