media_core/
audio.rs

1use std::{
2    iter, mem,
3    num::{NonZeroU32, NonZeroU8},
4    sync::LazyLock,
5};
6
7use bitflags::bitflags;
8use smallvec::SmallVec;
9
10use crate::{
11    error::Error,
12    frame::{PlaneInformation, PlaneInformationVec},
13    invalid_param_error,
14    media::FrameDescriptor,
15    time, Result,
16};
17
18pub const SAMPLE_RATE_TELEPHONE: u32 = 8000;
19pub const SAMPLE_RATE_VOIP: u32 = 16000;
20pub const SAMPLE_RATE_CD: u32 = 44100;
21pub const SAMPLE_RATE_DVD: u32 = 48000;
22pub const SAMPLE_RATE_HIGH: u32 = 96000;
23pub const SAMPLE_RATE_ULTRA_HIGH: u32 = 192000;
24
25#[derive(Clone, Copy, Debug, Eq, PartialEq)]
26pub enum SampleFormat {
27    U8 = 0, // unsigned 8 bits
28    S16,    // signed 16 bits
29    S32,    // signed 32 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    F32P,   // float 32 bits, planar
36    F64P,   // float 64 bits, planar
37    MAX,
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::MAX as usize {
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 is_planar: bool,
61}
62
63static SAMPLE_FORMAT_DESC: [SampleFormatDescriptor; SampleFormat::MAX as usize] = [
64    // U8
65    SampleFormatDescriptor {
66        bits: 8,
67        is_planar: false,
68    },
69    // S16
70    SampleFormatDescriptor {
71        bits: 16,
72        is_planar: false,
73    },
74    // S32
75    SampleFormatDescriptor {
76        bits: 32,
77        is_planar: false,
78    },
79    // F32
80    SampleFormatDescriptor {
81        bits: 32,
82        is_planar: false,
83    },
84    // F64
85    SampleFormatDescriptor {
86        bits: 64,
87        is_planar: false,
88    },
89    // U8P
90    SampleFormatDescriptor {
91        bits: 8,
92        is_planar: true,
93    },
94    // S16P
95    SampleFormatDescriptor {
96        bits: 16,
97        is_planar: true,
98    },
99    // S32P
100    SampleFormatDescriptor {
101        bits: 32,
102        is_planar: true,
103    },
104    // F32P
105    SampleFormatDescriptor {
106        bits: 32,
107        is_planar: true,
108    },
109    // F64P
110    SampleFormatDescriptor {
111        bits: 64,
112        is_planar: true,
113    },
114];
115
116impl SampleFormat {
117    pub fn bits(&self) -> u8 {
118        SAMPLE_FORMAT_DESC[*self as usize].bits
119    }
120
121    pub fn bytes(&self) -> u8 {
122        self.bits() >> 3
123    }
124
125    pub fn is_planar(&self) -> bool {
126        SAMPLE_FORMAT_DESC[*self as usize].is_planar
127    }
128
129    pub fn stride(&self, channels: u8, samples: u32) -> usize {
130        if self.is_planar() {
131            self.bytes() as usize * samples as usize
132        } else {
133            self.bytes() as usize * channels as usize * samples as usize
134        }
135    }
136
137    pub(crate) fn calc_data(&self, channels: u8, samples: u32) -> (usize, PlaneInformationVec) {
138        let mut size = 0;
139        let mut planes = PlaneInformationVec::new();
140        let stride = self.stride(channels, samples);
141
142        if self.is_planar() {
143            planes.extend(iter::repeat_n(PlaneInformation::Audio(stride, stride), channels as usize));
144            size += stride * channels as usize;
145        } else {
146            planes.push(PlaneInformation::Audio(stride, stride));
147            size = stride;
148        }
149
150        (size, planes)
151    }
152
153    pub(crate) fn calc_actual_bytes(&self, channels: u8, samples: u32) -> usize {
154        let bytes = self.stride(channels, samples);
155        if self.is_planar() {
156            bytes * channels as usize
157        } else {
158            bytes
159        }
160    }
161}
162
163#[derive(Clone, Copy, Debug, Eq, PartialEq)]
164pub enum ChannelFormat {
165    FrontLeft,
166    FrontRight,
167    FrontCenter,
168    LowFrequency,
169    BackLeft,
170    BackRight,
171    FrontLeftOfCenter,
172    FrontRightOfCenter,
173    BackCenter,
174    SideLeft,
175    SideRight,
176    TopCenter,
177    TopFrontLeft,
178    TopFrontCenter,
179    TopFrontRight,
180    TopBackLeft,
181    TopBackCenter,
182    TopBackRight,
183}
184
185impl From<ChannelFormat> for u32 {
186    fn from(format: ChannelFormat) -> Self {
187        format as u32
188    }
189}
190
191impl From<ChannelFormat> for ChannelFormatMasks {
192    fn from(format: ChannelFormat) -> Self {
193        ChannelFormatMasks::from_bits_truncate(1u32 << format as u32)
194    }
195}
196
197macro_rules! chn_fmt_masks {
198    ($($mask:ident)|+) => {
199        0 $(| ChannelFormatMasks::$mask.bits())+
200    };
201    ($mask:ident) => {
202        ChannelFormatMasks::$mask.bits()
203    };
204}
205
206bitflags! {
207    #[repr(transparent)]
208    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
209    pub struct ChannelFormatMasks: u32 {
210        const FrontLeft             = 1u32 << ChannelFormat::FrontLeft as u32;
211        const FrontRight            = 1u32 << ChannelFormat::FrontRight as u32;
212        const FrontCenter           = 1u32 << ChannelFormat::FrontCenter as u32;
213        const LowFrequency          = 1u32 << ChannelFormat::LowFrequency as u32;
214        const BackLeft              = 1u32 << ChannelFormat::BackLeft as u32;
215        const BackRight             = 1u32 << ChannelFormat::BackRight as u32;
216        const FrontLeftOfCenter     = 1u32 << ChannelFormat::FrontLeftOfCenter as u32;
217        const FrontRightOfCenter    = 1u32 << ChannelFormat::FrontRightOfCenter as u32;
218        const BackCenter            = 1u32 << ChannelFormat::BackCenter as u32;
219        const SideLeft              = 1u32 << ChannelFormat::SideLeft as u32;
220        const SideRight             = 1u32 << ChannelFormat::SideRight as u32;
221        const TopCenter             = 1u32 << ChannelFormat::TopCenter as u32;
222        const TopFrontLeft          = 1u32 << ChannelFormat::TopFrontLeft as u32;
223        const TopFrontCenter        = 1u32 << ChannelFormat::TopFrontCenter as u32;
224        const TopFrontRight         = 1u32 << ChannelFormat::TopFrontRight as u32;
225        const TopBackLeft           = 1u32 << ChannelFormat::TopBackLeft as u32;
226        const TopBackCenter         = 1u32 << ChannelFormat::TopBackCenter as u32;
227        const TopBackRight          = 1u32 << ChannelFormat::TopBackRight as u32;
228
229        const Mono                      = chn_fmt_masks!(FrontCenter);
230        const Stereo                    = chn_fmt_masks!(FrontLeft | FrontRight);
231        const Surround_2_1              = chn_fmt_masks!(Stereo | LowFrequency);
232        const Surround                  = chn_fmt_masks!(Stereo | FrontCenter);
233        const Surround_3_0              = chn_fmt_masks!(Surround);
234        const Surround_3_0_FRONT        = chn_fmt_masks!(Surround);
235        const Surround_3_0_BACK         = chn_fmt_masks!(Stereo | BackCenter);
236        const Surround_3_1              = chn_fmt_masks!(Surround_3_0 | LowFrequency);
237        const Surround_3_1_2            = chn_fmt_masks!(Surround_3_1 | TopFrontLeft | TopFrontRight);
238        const Surround_4_0              = chn_fmt_masks!(Surround_3_0 | BackCenter);
239        const Surround_4_1              = chn_fmt_masks!(Surround_4_0 | LowFrequency);
240        const Surround_2_2              = chn_fmt_masks!(Stereo | SideLeft | SideRight);
241        const Quad                      = chn_fmt_masks!(Stereo | BackLeft | BackRight);
242        const Surround_5_0              = chn_fmt_masks!(Surround_3_0 | SideLeft | SideRight);
243        const Surround_5_1              = chn_fmt_masks!(Surround_5_0 | LowFrequency);
244        const Surround_5_0_BACK         = chn_fmt_masks!(Surround_3_0 | BackLeft | BackRight);
245        const Surround_5_1_BACK         = chn_fmt_masks!(Surround_5_0_BACK | LowFrequency);
246        const Surround_6_0              = chn_fmt_masks!(Surround_5_0 | BackCenter);
247        const Hexagonal                 = chn_fmt_masks!(Surround_5_0_BACK | BackCenter);
248        const Surround_6_1              = chn_fmt_masks!(Surround_6_0 | LowFrequency);
249        const Surround_6_0_FRONT        = chn_fmt_masks!(Surround_2_2 | FrontLeftOfCenter | FrontRightOfCenter);
250        const Surround_6_1_FRONT        = chn_fmt_masks!(Surround_6_0_FRONT | LowFrequency);
251        const Surround_6_1_BACK         = chn_fmt_masks!(Surround_5_1_BACK | BackCenter);
252        const Surround_7_0              = chn_fmt_masks!(Surround_5_0 | BackLeft | BackRight);
253        const Surround_7_1              = chn_fmt_masks!(Surround_7_0 | LowFrequency);
254        const Surround_7_0_FRONT        = chn_fmt_masks!(Surround_5_0 | FrontLeftOfCenter | FrontRightOfCenter);
255        const Surround_7_1_WIDE         = chn_fmt_masks!(Surround_5_1 | FrontLeftOfCenter | FrontRightOfCenter);
256        const Surround_7_1_WIDE_BACK    = chn_fmt_masks!(Surround_5_1_BACK | FrontLeftOfCenter | FrontRightOfCenter);
257        const Surround_5_1_2            = chn_fmt_masks!(Surround_5_1 | TopFrontLeft | TopFrontRight);
258        const Surround_5_1_2_BACK       = chn_fmt_masks!(Surround_5_1_BACK | TopFrontLeft | TopFrontRight);
259        const Octagonal                 = chn_fmt_masks!(Surround_5_0 | BackLeft | BackCenter | BackRight);
260        const Cube                      = chn_fmt_masks!(Quad | TopFrontLeft | TopFrontRight | TopBackLeft | TopBackRight);
261        const Surround_5_1_4_BACK       = chn_fmt_masks!(Surround_5_1_2 | TopBackLeft | TopBackRight);
262        const Surround_7_1_2            = chn_fmt_masks!(Surround_7_1 | TopFrontLeft | TopFrontRight);
263        const Surround_7_1_4_BACK       = chn_fmt_masks!(Surround_7_1_2 | TopBackLeft | TopBackRight);
264        const Surround_9_1_4_BACK       = chn_fmt_masks!(Surround_7_1_4_BACK | FrontLeftOfCenter | FrontRightOfCenter);
265    }
266}
267
268#[derive(Clone, Copy, Debug, Eq, PartialEq)]
269pub enum ChannelOrder {
270    Unspecified,
271    Native,
272    Custom,
273    MAX,
274}
275
276struct ChannelLayoutMap {
277    map: Vec<Option<Vec<ChannelLayout>>>,
278}
279
280macro_rules! define_channel_layout_map {
281    ( $($channel_count:literal => [$($mask:ident),*]),* $(,)? ) => {
282        static CHANNEL_LAYOUT_MAP: LazyLock<ChannelLayoutMap> = LazyLock::new(|| {
283            let mut map = vec![None; DEFAULT_MAX_CHANNELS];
284            $(
285                let channels = NonZeroU8::new($channel_count).unwrap();
286                map[($channel_count - 1) as usize] = Some(vec![
287                    $(
288                        ChannelLayout {
289                            order: ChannelOrder::Native,
290                            channels,
291                            spec: ChannelLayoutSpec::Mask(ChannelFormatMasks::$mask),
292                        }
293                    ),*
294                ]);
295            )*
296            ChannelLayoutMap { map }
297        });
298    };
299}
300
301define_channel_layout_map! {
302    1 => [Mono],
303    2 => [Stereo],
304    3 => [Surround_2_1, Surround_3_0, Surround_3_0_BACK],
305    4 => [Surround_3_1, Surround_4_0, Surround_2_2, Quad],
306    5 => [Surround_4_1, Surround_5_0, Surround_5_0_BACK],
307    6 => [Surround_5_1, Surround_5_1_BACK, Surround_6_0, Surround_6_0_FRONT, Surround_3_1_2, Hexagonal],
308    7 => [Surround_6_1, Surround_6_1_FRONT, Surround_6_1_BACK, Surround_7_0, Surround_7_0_FRONT],
309    8 => [Surround_7_1, Surround_7_1_WIDE, Surround_7_1_WIDE_BACK, Surround_5_1_2, Surround_5_1_2_BACK, Octagonal, Cube],
310   10 => [Surround_5_1_4_BACK, Surround_7_1_2],
311   12 => [Surround_7_1_4_BACK],
312   14 => [Surround_9_1_4_BACK],
313}
314
315const DEFAULT_MAX_CHANNELS: usize = 16;
316
317#[derive(Clone, Debug, Eq, PartialEq)]
318pub enum ChannelLayoutSpec {
319    Mask(ChannelFormatMasks),
320    Map(Option<SmallVec<[ChannelFormat; DEFAULT_MAX_CHANNELS]>>),
321}
322
323#[derive(Clone, Debug, Eq, PartialEq)]
324pub struct ChannelLayout {
325    pub order: ChannelOrder,
326    pub channels: NonZeroU8,
327    pub spec: ChannelLayoutSpec,
328}
329
330impl Default for ChannelLayout {
331    fn default() -> Self {
332        Self {
333            order: ChannelOrder::Unspecified,
334            channels: NonZeroU8::new(1).unwrap(),
335            spec: ChannelLayoutSpec::Mask(ChannelFormatMasks::from_bits_truncate(0)),
336        }
337    }
338}
339
340impl TryFrom<ChannelFormatMasks> for ChannelLayout {
341    type Error = Error;
342
343    fn try_from(mask: ChannelFormatMasks) -> std::result::Result<Self, Self::Error> {
344        Self::from_mask(mask)
345    }
346}
347
348impl TryFrom<u8> for ChannelLayout {
349    type Error = Error;
350
351    fn try_from(channels: u8) -> std::result::Result<Self, Self::Error> {
352        Self::default_from_channels(channels)
353    }
354}
355
356impl ChannelLayout {
357    pub fn from_mask(mask: ChannelFormatMasks) -> Result<Self> {
358        let channels = mask.bits().count_ones() as u8;
359        let spec = ChannelLayoutSpec::Mask(mask);
360
361        NonZeroU8::new(channels)
362            .map(|channels| Self {
363                order: ChannelOrder::Native,
364                channels,
365                spec,
366            })
367            .ok_or_else(|| invalid_param_error!("channel mask is empty"))
368    }
369
370    pub fn default_from_channels(channels: u8) -> Result<Self> {
371        let channels = NonZeroU8::new(channels).ok_or(invalid_param_error!(channels))?;
372
373        Ok(CHANNEL_LAYOUT_MAP
374            .map
375            .get((channels.get() - 1) as usize)
376            .and_then(|opt| opt.as_ref())
377            .and_then(|layouts| layouts.first())
378            .cloned()
379            .unwrap_or(Self {
380                order: ChannelOrder::Unspecified,
381                channels,
382                spec: ChannelLayoutSpec::Mask(ChannelFormatMasks::from_bits_truncate(0)),
383            }))
384    }
385}
386
387#[derive(Clone, Debug, Eq, PartialEq)]
388pub struct AudioFrameDescriptor {
389    pub format: SampleFormat,
390    pub samples: NonZeroU32,
391    pub sample_rate: NonZeroU32,
392    pub channel_layout: ChannelLayout,
393}
394
395impl AudioFrameDescriptor {
396    pub fn new(format: SampleFormat, channels: NonZeroU8, samples: NonZeroU32, sample_rate: NonZeroU32) -> Self {
397        Self {
398            format,
399            samples,
400            sample_rate,
401            channel_layout: ChannelLayout::default_from_channels(channels.get()).unwrap_or_default(),
402        }
403    }
404
405    pub fn try_new(format: SampleFormat, channels: u8, samples: u32, sample_rate: u32) -> Result<Self> {
406        let channels = NonZeroU8::new(channels).ok_or(invalid_param_error!(channels))?;
407        let samples = NonZeroU32::new(samples).ok_or(invalid_param_error!(samples))?;
408        let sample_rate = NonZeroU32::new(sample_rate).ok_or(invalid_param_error!(sample_rate))?;
409
410        Ok(Self::new(format, channels, samples, sample_rate))
411    }
412
413    pub fn from_channel_layout(format: SampleFormat, samples: NonZeroU32, sample_rate: NonZeroU32, channel_layout: ChannelLayout) -> Self {
414        Self {
415            format,
416            samples,
417            sample_rate,
418            channel_layout,
419        }
420    }
421
422    pub fn try_from_channel_layout(format: SampleFormat, samples: u32, sample_rate: u32, channel_layout: ChannelLayout) -> Result<Self> {
423        let samples = NonZeroU32::new(samples).ok_or(invalid_param_error!(samples))?;
424        let sample_rate = NonZeroU32::new(sample_rate).ok_or(invalid_param_error!(sample_rate))?;
425
426        Ok(Self::from_channel_layout(format, samples, sample_rate, channel_layout))
427    }
428
429    pub fn channels(&self) -> NonZeroU8 {
430        self.channel_layout.channels
431    }
432
433    pub fn duration_equal(&self, other: &AudioFrameDescriptor) -> bool {
434        let duration1 = self.samples.get() as u64 * time::MSEC_PER_SEC / self.sample_rate.get() as u64;
435        let duration2 = other.samples.get() as u64 * time::MSEC_PER_SEC / other.sample_rate.get() as u64;
436        duration1 == duration2
437    }
438}
439
440impl From<AudioFrameDescriptor> for FrameDescriptor {
441    fn from(desc: AudioFrameDescriptor) -> Self {
442        FrameDescriptor::Audio(desc)
443    }
444}