use nom::{number::streaming::be_u8, Err as NomErr, IResult, Needed};
#[derive(Clone, Debug, PartialEq)]
pub struct AudioTag<'a> {
pub header: AudioTagHeader,
pub body: AudioTagBody<'a>,
}
impl<'a> AudioTag<'a> {
pub fn parse(input: &'a [u8], size: usize) -> IResult<&'a [u8], AudioTag<'a>> {
do_parse!(
input,
header: call!(AudioTagHeader::parse, size) >>
body: call!(AudioTagBody::parse, size - 1) >>
(AudioTag { header, body })
)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct AudioTagHeader {
pub sound_format: SoundFormat,
pub sound_rate: SoundRate,
pub sound_size: SoundSize,
pub sound_type: SoundType,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SoundFormat {
PcmPlatformEndian,
ADPCM,
MP3,
PcmLittleEndian,
Nellymoser16kHzMono,
Nellymoser8kHzMono,
Nellymoser,
PcmALaw,
PcmMuLaw,
Reserved,
AAC,
Speex,
MP3_8kHz,
DeviceSpecific,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SoundRate {
_5_5KHZ,
_11KHZ,
_22KHZ,
_44KHZ,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SoundSize {
_8Bit,
_16Bit,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SoundType {
Mono,
Stereo,
}
impl AudioTagHeader {
pub fn parse(input: &[u8], size: usize) -> IResult<&[u8], AudioTagHeader> {
if size < 1 {
return Err(NomErr::Incomplete(Needed::new(1)));
}
let (remain, (sound_format, sound_rate, sound_size, sound_type)) = try_parse!(
input,
bits!(tuple!(
switch!(take_bits!(4u8),
0 => value!(SoundFormat::PcmPlatformEndian) |
1 => value!(SoundFormat::ADPCM) |
2 => value!(SoundFormat::MP3) |
3 => value!(SoundFormat::PcmLittleEndian) |
4 => value!(SoundFormat::Nellymoser16kHzMono) |
5 => value!(SoundFormat::Nellymoser8kHzMono) |
6 => value!(SoundFormat::Nellymoser) |
7 => value!(SoundFormat::PcmALaw) |
8 => value!(SoundFormat::PcmMuLaw) |
9 => value!(SoundFormat::Reserved) |
10 => value!(SoundFormat::AAC) |
11 => value!(SoundFormat::Speex) |
14 => value!(SoundFormat::MP3_8kHz) |
15 => value!(SoundFormat::DeviceSpecific)
),
switch!(take_bits!(2u8),
0 => value!(SoundRate::_5_5KHZ) |
1 => value!(SoundRate::_11KHZ) |
2 => value!(SoundRate::_22KHZ) |
3 => value!(SoundRate::_44KHZ)
),
switch!(take_bits!(1u8),
0 => value!(SoundSize::_8Bit) |
1 => value!(SoundSize::_16Bit)
),
switch!(take_bits!(1u8),
0 => value!(SoundType::Mono) |
1 => value!(SoundType::Stereo)
)
))
);
Ok((
remain,
AudioTagHeader {
sound_format,
sound_rate,
sound_size,
sound_type,
},
))
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct AudioTagBody<'a> {
pub data: &'a [u8],
}
impl<'a> AudioTagBody<'a> {
pub fn parse(input: &'a [u8], size: usize) -> IResult<&'a [u8], AudioTagBody<'a>> {
if input.len() < size {
return Err(NomErr::Incomplete(Needed::new(size)));
}
Ok((
&input[size..],
AudioTagBody {
data: &input[0..size],
},
))
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct AACAudioPacket<'a> {
pub packet_type: AACPacketType,
pub aac_data: &'a [u8],
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AACPacketType {
SequenceHeader,
Raw,
}
pub fn aac_audio_packet(input: &[u8], size: usize) -> IResult<&[u8], AACAudioPacket> {
if input.len() < size {
return Err(NomErr::Incomplete(Needed::new(size)));
}
if size < 1 {
return Err(NomErr::Incomplete(Needed::new(1)));
}
let (_, packet_type) = try_parse!(
input,
switch!(be_u8,
0 => value!(AACPacketType::SequenceHeader) |
1 => value!(AACPacketType::Raw)
)
);
Ok((
&input[size..],
AACAudioPacket {
packet_type,
aac_data: &input[1..size],
},
))
}