1#![cfg_attr(all(coverage_nightly, test), feature(coverage_attribute))]
11
12use std::io;
13
14use num_derive::FromPrimitive;
15use num_traits::FromPrimitive;
16use scuffle_bytes_util::BitReader;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24#[must_use]
25pub struct PartialAudioSpecificConfig {
26 pub audio_object_type: AudioObjectType,
28 pub sampling_frequency: u32,
30 pub channel_configuration: u8,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37#[must_use]
38pub enum AudioObjectType {
39 AacMain,
40 AacLowComplexity,
41 Unknown(u16),
42}
43
44impl AudioObjectType {
45 pub const fn as_u16(&self) -> u16 {
47 match self {
48 AudioObjectType::AacMain => 1,
49 AudioObjectType::AacLowComplexity => 2,
50 AudioObjectType::Unknown(value) => *value,
51 }
52 }
53
54 pub const fn from_u16(value: u16) -> Self {
56 match value {
57 1 => AudioObjectType::AacMain,
58 2 => AudioObjectType::AacLowComplexity,
59 _ => AudioObjectType::Unknown(value),
60 }
61 }
62}
63
64impl From<u16> for AudioObjectType {
65 fn from(value: u16) -> Self {
66 Self::from_u16(value)
67 }
68}
69
70impl From<AudioObjectType> for u16 {
71 fn from(value: AudioObjectType) -> Self {
72 value.as_u16()
73 }
74}
75
76#[derive(FromPrimitive, Debug, Clone, PartialEq, Copy, Eq, PartialOrd, Ord)]
84#[repr(u8)]
85#[must_use]
86pub enum SampleFrequencyIndex {
87 Freq96000 = 0x0,
89 Freq88200 = 0x1,
91 Freq64000 = 0x2,
93 Freq48000 = 0x3,
95 Freq44100 = 0x4,
97 Freq32000 = 0x5,
99 Freq24000 = 0x6,
101 Freq22050 = 0x7,
103 Freq16000 = 0x8,
105 Freq12000 = 0x9,
107 Freq11025 = 0xA,
109 Freq8000 = 0xB,
111 Freq7350 = 0xC,
113 FreqReserved = 0xD,
115 FreqReserved2 = 0xE,
117 FreqEscape = 0xF,
120}
121
122impl SampleFrequencyIndex {
123 pub const fn to_freq(&self) -> Option<u32> {
125 match self {
126 SampleFrequencyIndex::Freq96000 => Some(96000),
127 SampleFrequencyIndex::Freq88200 => Some(88200),
128 SampleFrequencyIndex::Freq64000 => Some(64000),
129 SampleFrequencyIndex::Freq48000 => Some(48000),
130 SampleFrequencyIndex::Freq44100 => Some(44100),
131 SampleFrequencyIndex::Freq32000 => Some(32000),
132 SampleFrequencyIndex::Freq24000 => Some(24000),
133 SampleFrequencyIndex::Freq22050 => Some(22050),
134 SampleFrequencyIndex::Freq16000 => Some(16000),
135 SampleFrequencyIndex::Freq12000 => Some(12000),
136 SampleFrequencyIndex::Freq11025 => Some(11025),
137 SampleFrequencyIndex::Freq8000 => Some(8000),
138 SampleFrequencyIndex::Freq7350 => Some(7350),
139 SampleFrequencyIndex::FreqReserved => None,
140 SampleFrequencyIndex::FreqReserved2 => None,
141 SampleFrequencyIndex::FreqEscape => None,
142 }
143 }
144}
145
146impl PartialAudioSpecificConfig {
147 pub fn parse(data: &[u8]) -> io::Result<Self> {
155 let mut bitreader = BitReader::new_from_slice(data);
156
157 let mut audio_object_type = bitreader.read_bits(5)? as u16;
159 if audio_object_type == 31 {
160 audio_object_type = 32 + bitreader.read_bits(6)? as u16;
161 }
162
163 let sampling_frequency_index = SampleFrequencyIndex::from_u8(bitreader.read_bits(4)? as u8)
166 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Invalid sampling frequency index"))?;
167
168 let sampling_frequency = match sampling_frequency_index {
169 SampleFrequencyIndex::FreqEscape => bitreader.read_bits(24)? as u32,
171 _ => sampling_frequency_index
172 .to_freq()
173 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Invalid sampling frequency index"))?,
174 };
175
176 let channel_configuration = bitreader.read_bits(4)? as u8;
178
179 Ok(Self {
180 audio_object_type: audio_object_type.into(),
181 sampling_frequency,
182 channel_configuration,
183 })
184 }
185}
186
187#[cfg(test)]
188#[cfg_attr(all(test, coverage_nightly), coverage(off))]
189mod tests {
190 use super::*;
191
192 #[test]
193 fn test_aac_config_parse() {
194 let data = [
195 0x12, 0x10, 0x56, 0xe5, 0x00, 0x2d, 0x96, 0x01, 0x80, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00,
196 ];
197
198 let config = PartialAudioSpecificConfig::parse(&data).unwrap();
199 assert_eq!(config.audio_object_type, AudioObjectType::AacLowComplexity);
200 assert_eq!(config.sampling_frequency, 44100);
201 assert_eq!(config.channel_configuration, 2);
202 }
203
204 #[test]
205 fn test_idx_to_freq() {
206 let cases = [
207 (SampleFrequencyIndex::FreqEscape, None),
208 (SampleFrequencyIndex::FreqReserved2, None),
209 (SampleFrequencyIndex::FreqReserved, None),
210 (SampleFrequencyIndex::Freq7350, Some(7350)),
211 (SampleFrequencyIndex::Freq8000, Some(8000)),
212 (SampleFrequencyIndex::Freq11025, Some(11025)),
213 (SampleFrequencyIndex::Freq12000, Some(12000)),
214 (SampleFrequencyIndex::Freq16000, Some(16000)),
215 (SampleFrequencyIndex::Freq22050, Some(22050)),
216 (SampleFrequencyIndex::Freq24000, Some(24000)),
217 (SampleFrequencyIndex::Freq32000, Some(32000)),
218 (SampleFrequencyIndex::Freq44100, Some(44100)),
219 (SampleFrequencyIndex::Freq48000, Some(48000)),
220 (SampleFrequencyIndex::Freq64000, Some(64000)),
221 (SampleFrequencyIndex::Freq88200, Some(88200)),
222 (SampleFrequencyIndex::Freq96000, Some(96000)),
223 ];
224
225 for (idx, freq) in cases {
226 assert_eq!(freq, idx.to_freq(), "Expected frequency for {:?}", idx);
227 }
228 }
229}