media_core/audio/
audio.rs

1use std::{
2    iter, mem,
3    num::{NonZeroU32, NonZeroU8},
4};
5
6use strum::EnumCount;
7
8pub use super::channel_layout::*;
9use crate::{
10    align_to,
11    audio::AudioFrame,
12    error::Error,
13    frame::{Frame, PlaneDescriptor, PlaneVec},
14    invalid_param_error, time, FrameDescriptor, FrameDescriptorSpec, MediaType, Result,
15};
16
17pub const SAMPLE_RATE_TELEPHONE: u32 = 8000;
18pub const SAMPLE_RATE_VOIP: u32 = 16000;
19pub const SAMPLE_RATE_CD: u32 = 44100;
20pub const SAMPLE_RATE_DVD: u32 = 48000;
21pub const SAMPLE_RATE_HIGH: u32 = 96000;
22pub const SAMPLE_RATE_ULTRA_HIGH: u32 = 192000;
23
24#[derive(Clone, Copy, Debug, EnumCount, Eq, PartialEq)]
25pub enum SampleFormat {
26    U8 = 0, // unsigned 8 bits
27    S16,    // signed 16 bits
28    S32,    // signed 32 bits
29    S64,    // signed 64 bits
30    F32,    // float 32 bits
31    F64,    // float 64 bits
32    U8P,    // unsigned 8 bits, planar
33    S16P,   // signed 16 bits, planar
34    S32P,   // signed 32 bits, planar
35    S64P,   // signed 64 bits, planar
36    F32P,   // float 32 bits, planar
37    F64P,   // float 64 bits, planar
38}
39
40impl From<SampleFormat> for usize {
41    fn from(value: SampleFormat) -> Self {
42        value as usize
43    }
44}
45
46impl TryFrom<usize> for SampleFormat {
47    type Error = Error;
48
49    fn try_from(value: usize) -> Result<Self> {
50        if value < SampleFormat::COUNT {
51            Ok(unsafe { mem::transmute::<u8, SampleFormat>(value as u8) })
52        } else {
53            Err(invalid_param_error!(value))
54        }
55    }
56}
57
58struct SampleFormatDescriptor {
59    pub bits: u8,
60    pub planar: bool,
61}
62
63static SAMPLE_FORMAT_DESC: [SampleFormatDescriptor; SampleFormat::COUNT] = [
64    // U8
65    SampleFormatDescriptor {
66        bits: 8,
67        planar: false,
68    },
69    // S16
70    SampleFormatDescriptor {
71        bits: 16,
72        planar: false,
73    },
74    // S32
75    SampleFormatDescriptor {
76        bits: 32,
77        planar: false,
78    },
79    // S64
80    SampleFormatDescriptor {
81        bits: 64,
82        planar: false,
83    },
84    // F32
85    SampleFormatDescriptor {
86        bits: 32,
87        planar: false,
88    },
89    // F64
90    SampleFormatDescriptor {
91        bits: 64,
92        planar: false,
93    },
94    // U8P
95    SampleFormatDescriptor {
96        bits: 8,
97        planar: true,
98    },
99    // S16P
100    SampleFormatDescriptor {
101        bits: 16,
102        planar: true,
103    },
104    // S32P
105    SampleFormatDescriptor {
106        bits: 32,
107        planar: true,
108    },
109    // S64P
110    SampleFormatDescriptor {
111        bits: 64,
112        planar: true,
113    },
114    // F32P
115    SampleFormatDescriptor {
116        bits: 32,
117        planar: true,
118    },
119    // F64P
120    SampleFormatDescriptor {
121        bits: 64,
122        planar: true,
123    },
124];
125
126impl SampleFormat {
127    pub fn bits(&self) -> u8 {
128        SAMPLE_FORMAT_DESC[*self as usize].bits
129    }
130
131    pub fn bytes(&self) -> u8 {
132        self.bits() >> 3
133    }
134
135    pub fn is_planar(&self) -> bool {
136        SAMPLE_FORMAT_DESC[*self as usize].planar
137    }
138
139    pub fn is_packed(&self) -> bool {
140        !SAMPLE_FORMAT_DESC[*self as usize].planar
141    }
142
143    pub fn planar_sample_format(&self) -> SampleFormat {
144        match *self {
145            SampleFormat::U8 | SampleFormat::U8P => SampleFormat::U8P,
146            SampleFormat::S16 | SampleFormat::S16P => SampleFormat::S16P,
147            SampleFormat::S32 | SampleFormat::S32P => SampleFormat::S32P,
148            SampleFormat::S64 | SampleFormat::S64P => SampleFormat::S64P,
149            SampleFormat::F32 | SampleFormat::F32P => SampleFormat::F32P,
150            SampleFormat::F64 | SampleFormat::F64P => SampleFormat::F64P,
151        }
152    }
153
154    pub fn packed_sample_format(&self) -> SampleFormat {
155        match *self {
156            SampleFormat::U8 | SampleFormat::U8P => SampleFormat::U8,
157            SampleFormat::S16 | SampleFormat::S16P => SampleFormat::S16,
158            SampleFormat::S32 | SampleFormat::S32P => SampleFormat::S32,
159            SampleFormat::S64 | SampleFormat::S64P => SampleFormat::S64,
160            SampleFormat::F32 | SampleFormat::F32P => SampleFormat::F32,
161            SampleFormat::F64 | SampleFormat::F64P => SampleFormat::F64,
162        }
163    }
164
165    pub(crate) fn calc_plane_size(&self, channels: u8, samples: u32) -> usize {
166        if self.is_planar() {
167            self.bytes() as usize * samples as usize
168        } else {
169            self.bytes() as usize * samples as usize * channels as usize
170        }
171    }
172
173    pub(crate) fn calc_data_size(&self, channels: u8, samples: u32, alignment: u32) -> (usize, PlaneVec<PlaneDescriptor>) {
174        let mut planes = PlaneVec::new();
175        let used_bytes = self.calc_plane_size(channels, samples);
176        let allocated_size = align_to(used_bytes, alignment as usize);
177
178        let size = if self.is_planar() {
179            planes.extend(iter::repeat_n(PlaneDescriptor::Audio(allocated_size, used_bytes), channels as usize));
180            allocated_size * channels as usize
181        } else {
182            planes.push(PlaneDescriptor::Audio(allocated_size, used_bytes));
183            allocated_size
184        };
185
186        (size, planes)
187    }
188}
189
190#[derive(Clone, Debug, Eq, PartialEq)]
191pub struct AudioFrameDescriptor {
192    pub format: SampleFormat,
193    pub samples: NonZeroU32,
194    pub sample_rate: NonZeroU32,
195    pub channel_layout: ChannelLayout,
196}
197
198impl AudioFrameDescriptor {
199    pub fn new(format: SampleFormat, channels: NonZeroU8, samples: NonZeroU32, sample_rate: NonZeroU32) -> Self {
200        Self {
201            format,
202            samples,
203            sample_rate,
204            channel_layout: ChannelLayout::default_from_channels(channels.get()).unwrap_or_default(),
205        }
206    }
207
208    pub fn try_new(format: SampleFormat, channels: u8, samples: u32, sample_rate: u32) -> Result<Self> {
209        let channels = NonZeroU8::new(channels).ok_or_else(|| invalid_param_error!(channels))?;
210        let samples = NonZeroU32::new(samples).ok_or_else(|| invalid_param_error!(samples))?;
211        let sample_rate = NonZeroU32::new(sample_rate).ok_or_else(|| invalid_param_error!(sample_rate))?;
212
213        Ok(Self::new(format, channels, samples, sample_rate))
214    }
215
216    pub fn from_channel_layout(format: SampleFormat, samples: NonZeroU32, sample_rate: NonZeroU32, channel_layout: ChannelLayout) -> Self {
217        Self {
218            format,
219            samples,
220            sample_rate,
221            channel_layout,
222        }
223    }
224
225    pub fn try_from_channel_layout(format: SampleFormat, samples: u32, sample_rate: u32, channel_layout: ChannelLayout) -> Result<Self> {
226        let samples = NonZeroU32::new(samples).ok_or_else(|| invalid_param_error!(samples))?;
227        let sample_rate = NonZeroU32::new(sample_rate).ok_or_else(|| invalid_param_error!(sample_rate))?;
228
229        Ok(Self::from_channel_layout(format, samples, sample_rate, channel_layout))
230    }
231
232    pub fn channels(&self) -> NonZeroU8 {
233        self.channel_layout.channels
234    }
235
236    pub fn duration_equal(&self, other: &AudioFrameDescriptor) -> bool {
237        let duration1 = self.samples.get() as u64 * time::MSEC_PER_SEC / self.sample_rate.get() as u64;
238        let duration2 = other.samples.get() as u64 * time::MSEC_PER_SEC / other.sample_rate.get() as u64;
239        duration1 == duration2
240    }
241}
242
243impl From<AudioFrameDescriptor> for FrameDescriptor {
244    fn from(desc: AudioFrameDescriptor) -> Self {
245        FrameDescriptor::Audio(desc)
246    }
247}
248
249impl TryFrom<FrameDescriptor> for AudioFrameDescriptor {
250    type Error = Error;
251
252    fn try_from(value: FrameDescriptor) -> Result<Self> {
253        match value {
254            FrameDescriptor::Audio(desc) => Ok(desc),
255            _ => Err(invalid_param_error!(value)),
256        }
257    }
258}
259
260impl FrameDescriptorSpec for AudioFrameDescriptor {
261    fn media_type(&self) -> crate::MediaType {
262        MediaType::Audio
263    }
264
265    fn create_frame(&self) -> Result<Frame<'static, Self>> {
266        AudioFrame::new_with_descriptor(self.clone())
267    }
268
269    fn as_audio(&self) -> Option<&AudioFrameDescriptor> {
270        Some(self)
271    }
272}