use std::io;
use byteorder::ReadBytesExt;
use bytes::Bytes;
use nutype_enum::nutype_enum;
use crate::error::FlvError;
nutype_enum! {
pub enum SoundFormat(u8) {
LinearPcmPlatformEndian = 0,
Adpcm = 1,
Mp3 = 2,
LinearPcmLittleEndian = 3,
Nellymoser16KhzMono = 4,
Nellymoser8KhzMono = 5,
Nellymoser = 6,
G711ALaw = 7,
G711MuLaw = 8,
ExHeader = 9,
Aac = 10,
Speex = 11,
Mp38Khz = 14,
DeviceSpecificSound = 15,
}
}
nutype_enum! {
pub enum SoundRate(u8) {
Hz5500 = 0,
Hz11000 = 1,
Hz22000 = 2,
Hz44000 = 3,
}
}
nutype_enum! {
pub enum SoundSize(u8) {
Bit8 = 0,
Bit16 = 1,
}
}
nutype_enum! {
pub enum SoundType(u8) {
Mono = 0,
Stereo = 1,
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct LegacyAudioTagHeader {
pub sound_format: SoundFormat,
pub sound_rate: SoundRate,
pub sound_size: SoundSize,
pub sound_type: SoundType,
}
impl LegacyAudioTagHeader {
#[allow(clippy::unusual_byte_groupings)]
pub fn demux(reader: &mut io::Cursor<Bytes>) -> Result<Self, FlvError> {
let byte = reader.read_u8()?;
let sound_format = SoundFormat::from(byte >> 4); let sound_rate = SoundRate::from((byte & 0b0000_11_0_0) >> 2);
let sound_size = SoundSize::from((byte & 0b0000_00_1_0) >> 1);
let sound_type = SoundType::from(byte & 0b0000_00_0_1);
Ok(Self {
sound_format,
sound_rate,
sound_size,
sound_type,
})
}
}
#[cfg(test)]
#[cfg_attr(all(test, coverage_nightly), coverage(off))]
mod tests {
use super::*;
#[test]
fn test_sound_format() {
let cases = [
(
0x00,
SoundFormat::LinearPcmPlatformEndian,
"SoundFormat::LinearPcmPlatformEndian",
),
(0x01, SoundFormat::Adpcm, "SoundFormat::Adpcm"),
(0x02, SoundFormat::Mp3, "SoundFormat::Mp3"),
(0x03, SoundFormat::LinearPcmLittleEndian, "SoundFormat::LinearPcmLittleEndian"),
(0x04, SoundFormat::Nellymoser16KhzMono, "SoundFormat::Nellymoser16KhzMono"),
(0x05, SoundFormat::Nellymoser8KhzMono, "SoundFormat::Nellymoser8KhzMono"),
(0x06, SoundFormat::Nellymoser, "SoundFormat::Nellymoser"),
(0x07, SoundFormat::G711ALaw, "SoundFormat::G711ALaw"),
(0x08, SoundFormat::G711MuLaw, "SoundFormat::G711MuLaw"),
(0x0A, SoundFormat::Aac, "SoundFormat::Aac"),
(0x0B, SoundFormat::Speex, "SoundFormat::Speex"),
(0x0E, SoundFormat::Mp38Khz, "SoundFormat::Mp38Khz"),
(0x0F, SoundFormat::DeviceSpecificSound, "SoundFormat::DeviceSpecificSound"),
];
for (value, expected, name) in cases {
let sound_format = SoundFormat::from(value);
assert_eq!(sound_format, expected);
assert_eq!(format!("{sound_format:?}"), name);
}
}
#[test]
fn test_sound_rate() {
let cases = [
(0x00, SoundRate::Hz5500, "SoundRate::Hz5500"),
(0x01, SoundRate::Hz11000, "SoundRate::Hz11000"),
(0x02, SoundRate::Hz22000, "SoundRate::Hz22000"),
(0x03, SoundRate::Hz44000, "SoundRate::Hz44000"),
];
for (value, expected, name) in cases {
let sound_rate = SoundRate::from(value);
assert_eq!(sound_rate, expected);
assert_eq!(format!("{sound_rate:?}"), name);
}
}
#[test]
fn test_sound_size() {
let cases = [
(0x00, SoundSize::Bit8, "SoundSize::Bit8"),
(0x01, SoundSize::Bit16, "SoundSize::Bit16"),
];
for (value, expected, name) in cases {
let sound_size = SoundSize::from(value);
assert_eq!(sound_size, expected);
assert_eq!(format!("{sound_size:?}"), name);
}
}
#[test]
fn test_sound_type() {
let cases = [
(0x00, SoundType::Mono, "SoundType::Mono"),
(0x01, SoundType::Stereo, "SoundType::Stereo"),
];
for (value, expected, name) in cases {
let sound_type = SoundType::from(value);
assert_eq!(sound_type, expected);
assert_eq!(format!("{sound_type:?}"), name);
}
}
}