1pub mod codecs;
2pub mod containers;
3pub mod dsp;
4pub mod types;
5
6use crate::codecs::adpcm::{AdpcmError, SampleType};
7use crate::types::{AudioMetadata, Channels};
8
9pub fn get_metadata(bytes: &[u8]) -> Result<AudioMetadata, AdpcmError> {
11 if bytes.len() < 12 {
12 return Err(AdpcmError::BufferTooSmall {
13 expected: 12,
14 actual: bytes.len() as u16,
15 });
16 }
17
18 if bytes[0] != 0x17 || bytes[1] != 0x42 {
19 return Err(AdpcmError::InvalidMagic);
20 }
21
22 let frame_len = u16::from_le_bytes([bytes[2], bytes[3]]) as usize;
23 let read_sum = bytes[4];
24 let type_byte = bytes[5];
25 let sample_type = SampleType::from(type_byte);
26
27 if sample_type == SampleType::None {
28 return Err(AdpcmError::UnsupportedSampleType(type_byte));
29 }
30
31 let channels = match sample_type {
32 SampleType::PcmMono8 | SampleType::PcmMono16 | SampleType::AdpcmMono => Channels::Mono,
33 SampleType::PcmStereo8 | SampleType::PcmStereo16 | SampleType::AdpcmStereo => {
34 Channels::Stereo
35 }
36 SampleType::None => return Err(AdpcmError::UnsupportedSampleType(type_byte)),
37 };
38
39 let h_size = 6 + channels.count() * 3;
40 if bytes.len() < h_size {
41 return Err(AdpcmError::BufferTooSmall {
42 expected: h_size as u16,
43 actual: bytes.len() as u16,
44 });
45 }
46
47 let mut calc_sum: u8 = 0;
48 for (i, b) in bytes.iter().take(h_size).enumerate() {
49 if i != 4 {
50 calc_sum = calc_sum.wrapping_add(*b);
51 }
52 }
53
54 if calc_sum != read_sum {
55 return Err(AdpcmError::ChecksumMismatch {
56 expected: calc_sum,
57 actual: read_sum,
58 });
59 }
60
61 Ok(AudioMetadata {
62 channels,
63 sample_type,
64 frame_length: frame_len,
65 })
66}