mpeg4_audio_const/
lib.rs

1//! Definitions of types and constants for values defined by
2//! [ISO/IEC 14496 part 3 (Audio)](https://en.wikipedia.org/wiki/MPEG-4_Part_3).
3//!
4//! Currently supported,
5//!
6//!  - [`AudioObjectType`](struct.AudioObjectType.html)
7
8use std::convert::TryFrom;
9use std::fmt;
10
11/// Represents an error converting a `u8` into an `AudioObjectType`
12#[derive(PartialEq, Debug)]
13pub enum AudioObjectTypeError {
14    /// Tried to convert the 'escape value', `31`, into an `AudioObjectType` (this is not a legitimate
15    /// AOT value but instead is used as part of encoding the field value.
16    EscapeValue,
17    /// Only values 95 and under can be legitimate Audio Object Types.
18    TooLarge(u8),
19}
20
21/// Represents an
22/// [audio object type](https://en.wikipedia.org/wiki/MPEG-4_Part_3#MPEG-4_Audio_Object_Types)
23/// indicator value.
24///
25/// This type can be constructed from a `u8`,
26///
27/// ```rust
28/// # use mpeg4_audio_const::*;
29/// # use std::convert::TryFrom;
30/// assert_eq!(AudioObjectType::AAC_LC, AudioObjectType::try_from(2).unwrap());
31/// assert_eq!(2u8, AudioObjectType::AAC_LC.into());
32/// ```
33///
34/// and will accept values that are 'reserved' in the spec,
35///
36/// ```rust
37/// # use mpeg4_audio_const::*;
38/// # use std::convert::TryFrom;
39/// assert_eq!("RESERVED(95)", format!("{:?}", AudioObjectType::try_from(95).unwrap()));
40/// ```
41///
42/// but disallows values that can't legitimately be represented because they are too large
43/// (the maximum representable a-o-t value is `96`) and also disallows the 'escape value' (value
44/// `31` see [`AOT_ESCAPE_VALUE`](constant.ESCAPE_VALUE.html)) which is used as part of the
45/// encoding scheme for the a-o-t field rather than as a distinct field value.
46///
47/// ```rust
48/// # use mpeg4_audio_const::*;
49/// # use std::convert::TryFrom;
50/// assert_eq!(Err(AudioObjectTypeError::EscapeValue), AudioObjectType::try_from(31));
51/// assert_eq!(Err(AudioObjectTypeError::TooLarge(97)), AudioObjectType::try_from(97));
52/// ```
53#[derive(Eq, PartialEq, Copy, Clone)]
54pub struct AudioObjectType(u8);
55
56/// This value, `31`, is not used as an _audio object type_, but is instead used in the encoding of
57/// any _audio object type_ value greater than or equal to `32`.
58pub const AOT_ESCAPE_VALUE: u8 = 0b_11111;
59
60impl From<AudioObjectType> for u8 {
61    fn from(v: AudioObjectType) -> Self {
62        v.0
63    }
64}
65impl TryFrom<u8> for AudioObjectType {
66    type Error = AudioObjectTypeError;
67
68    fn try_from(value: u8) -> Result<Self, Self::Error> {
69        match value {
70            AOT_ESCAPE_VALUE => Err(AudioObjectTypeError::EscapeValue),
71            96..=255 => Err(AudioObjectTypeError::TooLarge(value)),
72            _ => Ok(AudioObjectType(value)),
73        }
74    }
75}
76
77macro_rules! implement_aot {
78    (
79        $( $tag:literal $id:ident $desc:literal ),* ,
80    ) => {
81
82        impl AudioObjectType {
83            $(
84                #[doc=$desc]
85                pub const $id: AudioObjectType = AudioObjectType($tag);
86            )*
87        }
88
89        impl fmt::Debug for AudioObjectType {
90            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91                match self.0 {
92                    $(
93                        $tag => write!(f, "{}({})", stringify!($id), $tag)
94                    ),* ,
95                    _ => write!(f, "RESERVED({})", self.0),
96                }
97            }
98        }
99    }
100}
101
102implement_aot! {
103    0 NULL "Null",
104    1 AAC_MAIN "AAC main",
105    3 AAC_SSR "AAC SSR",
106    4 AAC_LTP "AAC LTP",
107    7 TWIN_VQ "TwinVQ",
108    8 CELP "CELP",
109    9 HVXC "HVXC",
110    5 SBR "SBR",
111    6 AAC_SCALABLE "AAC Scalable",
112    2 AAC_LC "AAC LC",
113    12 TTSI "TTSI",
114    13 MAIN_SYNTHETIC "Main synthetic",
115    14 WAVETABLE_SYNTHESIS "Wavetable synthesis",
116    15 GENERAL_MIDI "General MIDI",
117    16 ALGORITHMIC_SYNTHESIS_AND_AUDIO_FX "Algorithmic Synthesis and Audio FX",
118    17 ER_AAC_LC "ER AAC LC",
119    19 ER_AAC_LTP "ER AAC LTP",
120    20 ER_AAC_SCALABLE "ER AAC Scalable",
121    21 ER_TWIN_VQ "ER TwinVQ",
122    22 ER_BSAC "ER BSAC",
123    23 ER_AAC_LD "ER AAC LD",
124    24 ER_CELP "ER CELP",
125    25 ER_HVXC "ER HVXC",
126    26 ER_HILN "ER HILN",
127    27 ER_PARAMETRIC "ER Parametric",
128    28 SSC "SSC",
129    29 PS "PS",
130    30 MPEG_SURROUND "MPEG Surround",
131    // 31 - 'escape' - deliberately skipped
132    32 LAYER1 "Layer-1",
133    34 LAYER3 "Layer-3",
134    35 DST "DST",
135    36 ALS "ALS",
136    37 SLS "SLS",
137    38 SLS_NON_CORE "SLS non-core",
138    39 ER_AAC_ELD "ER AAC ELD",
139    40 SMR_SIMPLE "SMR Simple",
140    41 SMR_MAIN "SMR Main",
141    42 USAC "Unified Speech and Audio Coding",
142    43 SAOC "Spatial Audio Object Coding",
143    44 LD_MPEG_SURROUND "Low Delay MPEG Surround",
144    45 SAOC_DE "Spatial Audio Object Coding Dialogue Enhancement",
145    46 AUDIO_SYNC "Audio synchronization tool",
146}
147
148#[cfg(test)]
149mod tests {
150    use super::*;
151    use std::convert::TryFrom;
152
153    #[test]
154    fn escape_value() {
155        assert_eq!(
156            Err(AudioObjectTypeError::EscapeValue),
157            AudioObjectType::try_from(AOT_ESCAPE_VALUE)
158        );
159    }
160}