media_core/
audio.rs

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