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) -> u32 {
275        if self.is_planar() {
276            self.bytes() as u32 * samples
277        } else {
278            self.bytes() as u32 * channels as u32 * samples
279        }
280    }
281
282    pub(crate) fn calc_data(&self, channels: u8, samples: u32) -> (u32, 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), channels as usize));
289            size += stride * channels as u32;
290        } else {
291            planes.push(PlaneInformation::Audio(stride));
292            size = stride;
293        }
294
295        (size, planes)
296    }
297}
298
299impl From<ChannelFormat> for u32 {
300    fn from(format: ChannelFormat) -> Self {
301        format as u32
302    }
303}
304
305impl From<ChannelFormat> for ChannelFormatMasks {
306    fn from(format: ChannelFormat) -> Self {
307        ChannelFormatMasks::from_bits_truncate(1u32 << format as u32)
308    }
309}
310
311impl Default for ChannelLayout {
312    fn default() -> Self {
313        Self {
314            order: ChannelOrder::Unspecified,
315            channels: NonZeroU8::new(1).unwrap(),
316            spec: ChannelLayoutSpec::Mask(ChannelFormatMasks::from_bits_truncate(0)),
317        }
318    }
319}
320
321impl ChannelLayout {
322    pub fn from_mask(mask: ChannelFormatMasks) -> Result<Self> {
323        let channels = mask.bits().count_ones() as u8;
324        let spec = ChannelLayoutSpec::Mask(mask);
325
326        NonZeroU8::new(channels)
327            .map(|channels| Self {
328                order: ChannelOrder::Native,
329                channels,
330                spec,
331            })
332            .ok_or_else(|| invalid_param_error!("channel mask is empty"))
333    }
334
335    pub fn default(channels: u8) -> Result<Self> {
336        let channels = NonZeroU8::new(channels).ok_or(invalid_param_error!(channels))?;
337
338        Ok(CHANNEL_LAYOUT_MAP
339            .map
340            .get((channels.get() - 1) as usize)
341            .and_then(|opt| opt.as_ref())
342            .and_then(|layouts| layouts.first())
343            .cloned()
344            .unwrap_or(Self {
345                order: ChannelOrder::Unspecified,
346                channels,
347                spec: ChannelLayoutSpec::Mask(ChannelFormatMasks::from_bits_truncate(0)),
348            }))
349    }
350}
351
352impl AudioFrameDescriptor {
353    pub fn new(format: SampleFormat, channels: NonZeroU8, samples: NonZeroU32, sample_rate: NonZeroU32) -> Self {
354        Self {
355            format,
356            samples,
357            sample_rate,
358            channel_layout: ChannelLayout::default(channels.get()).unwrap_or_default(),
359        }
360    }
361
362    pub fn try_new(format: SampleFormat, channels: u8, samples: u32, sample_rate: u32) -> Result<Self> {
363        let channels = NonZeroU8::new(channels).ok_or(invalid_param_error!(channels))?;
364        let samples = NonZeroU32::new(samples).ok_or(invalid_param_error!(samples))?;
365        let sample_rate = NonZeroU32::new(sample_rate).ok_or(invalid_param_error!(sample_rate))?;
366
367        Ok(Self::new(format, channels, samples, sample_rate))
368    }
369
370    pub fn channels(&self) -> NonZeroU8 {
371        self.channel_layout.channels
372    }
373
374    pub fn duration_equal(&self, other: &AudioFrameDescriptor) -> bool {
375        let duration1 = self.samples.get() as u64 * time::MSEC_PER_SEC / self.sample_rate.get() as u64;
376        let duration2 = other.samples.get() as u64 * time::MSEC_PER_SEC / other.sample_rate.get() as u64;
377        duration1 == duration2
378    }
379}
380
381impl From<AudioFrameDescriptor> for FrameDescriptor {
382    fn from(desc: AudioFrameDescriptor) -> Self {
383        FrameDescriptor::Audio(desc)
384    }
385}