Skip to main content

midas_audio/
lib.rs

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
9/// Returns the metadata of the provided bytes as a Result.
10pub 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}