use std::time::Duration;
use crate::{utils::XING_BUFFER_SIZE, AudioFrame, Error, Result};
use super::{
types::{
BitRate, ChannelMode, Emphasis, ModeExtension, MpegLayer, MpegVersion, SampleRate,
XingHeader, XingHeaderFlags,
},
AudioFrameHeader,
};
pub fn decode_version(byte: u8) -> Result<MpegVersion> {
let version = match byte & 0b0001_1000 {
0b0000_0000 => MpegVersion::Mpeg2_5,
0b0000_1000 => return Err(Error::ForbiddenMpegVersion),
0b0001_0000 => MpegVersion::Mpeg2,
0b0001_1000 => MpegVersion::Mpeg1,
_ => unreachable!(),
};
Ok(version)
}
pub fn decode_layer(byte: u8) -> Result<MpegLayer> {
let layer = match byte & 0b110 {
0b000 => return Err(Error::ForbiddenMpegLayer),
0b010 => MpegLayer::Layer3,
0b100 => MpegLayer::Layer2,
0b110 => MpegLayer::Layer1,
_ => unreachable!(),
};
Ok(layer)
}
pub fn decode_protected(byte: u8) -> bool {
byte & 0b1 == 0b0
}
pub fn decode_padding(byte: u8) -> u8 {
if byte & 0b10 == 0b10 {
1
} else {
0
}
}
pub fn decode_private(byte: u8) -> bool {
byte & 0b1 == 0b1
}
pub fn decode_bitrate(byte: u8, version: MpegVersion, layer: MpegLayer) -> Result<BitRate> {
let bitrate = match (byte & 0b1111_0000, version, layer) {
(0b0001_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps32,
(0b0010_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps64,
(0b0011_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps96,
(0b0100_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps128,
(0b0101_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps160,
(0b0110_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps192,
(0b0111_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps224,
(0b1000_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps256,
(0b1001_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps288,
(0b1010_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps320,
(0b1011_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps352,
(0b1100_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps384,
(0b1101_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps416,
(0b1110_0000, MpegVersion::Mpeg1, MpegLayer::Layer1) => BitRate::Kbps448,
(0b0001_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps32,
(0b0010_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps48,
(0b0011_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps56,
(0b0100_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps64,
(0b0101_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps80,
(0b0110_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps96,
(0b0111_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps112,
(0b1000_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps128,
(0b1001_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps160,
(0b1010_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps192,
(0b1011_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps224,
(0b1100_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps256,
(0b1101_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps320,
(0b1110_0000, MpegVersion::Mpeg1, MpegLayer::Layer2) => BitRate::Kbps284,
(0b0001_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps32,
(0b0010_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps40,
(0b0011_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps48,
(0b0100_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps65,
(0b0101_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps64,
(0b0110_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps80,
(0b0111_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps96,
(0b1000_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps112,
(0b1001_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps128,
(0b1010_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps160,
(0b1011_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps192,
(0b1100_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps224,
(0b1101_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps256,
(0b1110_0000, MpegVersion::Mpeg1, MpegLayer::Layer3) => BitRate::Kbps320,
(0b0001_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps32,
(0b0010_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps48,
(0b0011_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps56,
(0b0100_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps64,
(0b0101_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps80,
(0b0110_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps96,
(0b0111_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps112,
(0b1000_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps128,
(0b1001_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps144,
(0b1010_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps160,
(0b1011_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps176,
(0b1100_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps192,
(0b1101_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps224,
(0b1110_0000, MpegVersion::Mpeg2, MpegLayer::Layer1) => BitRate::Kbps284,
(0b0001_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps32,
(0b0010_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps48,
(0b0011_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps56,
(0b0100_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps64,
(0b0101_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps80,
(0b0110_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps96,
(0b0111_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps112,
(0b1000_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps128,
(0b1001_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps144,
(0b1010_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps160,
(0b1011_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps176,
(0b1100_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps192,
(0b1101_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps224,
(0b1110_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer1) => BitRate::Kbps284,
(0b0001_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps8,
(0b0010_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps16,
(0b0011_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps24,
(0b0100_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps32,
(0b0101_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps40,
(0b0110_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps48,
(0b0111_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps56,
(0b1000_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps64,
(0b1001_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps80,
(0b1010_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps96,
(0b1011_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps112,
(0b1100_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps128,
(0b1101_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps144,
(0b1110_0000, MpegVersion::Mpeg2, MpegLayer::Layer2) => BitRate::Kbps160,
(0b0001_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps8,
(0b0010_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps16,
(0b0011_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps24,
(0b0100_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps32,
(0b0101_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps40,
(0b0110_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps48,
(0b0111_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps56,
(0b1000_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps64,
(0b1001_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps80,
(0b1010_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps96,
(0b1011_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps112,
(0b1100_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps128,
(0b1101_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps144,
(0b1110_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer2) => BitRate::Kbps160,
(0b0001_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps8,
(0b0010_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps16,
(0b0011_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps24,
(0b0100_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps32,
(0b0101_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps40,
(0b0110_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps48,
(0b0111_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps56,
(0b1000_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps64,
(0b1001_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps80,
(0b1010_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps96,
(0b1011_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps112,
(0b1100_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps128,
(0b1101_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps144,
(0b1110_0000, MpegVersion::Mpeg2, MpegLayer::Layer3) => BitRate::Kbps160,
(0b0001_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps8,
(0b0010_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps16,
(0b0011_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps24,
(0b0100_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps32,
(0b0101_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps40,
(0b0110_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps48,
(0b0111_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps56,
(0b1000_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps64,
(0b1001_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps80,
(0b1010_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps96,
(0b1011_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps112,
(0b1100_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps128,
(0b1101_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps144,
(0b1110_0000, MpegVersion::Mpeg2_5, MpegLayer::Layer3) => BitRate::Kbps160,
(0b0000_0000, _, _) => return Err(Error::InvalidBitrate),
(0b1111_0000, _, _) => return Err(Error::UnsupportedBitrate),
_ => unreachable!(),
};
Ok(bitrate)
}
pub fn decode_sample_rate(byte: u8, version: MpegVersion) -> Result<SampleRate> {
let sample_rate = match (byte & 0b11_00, version) {
(0b00_00, MpegVersion::Mpeg1) => SampleRate::Hz44100,
(0b01_00, MpegVersion::Mpeg1) => SampleRate::Hz48000,
(0b10_00, MpegVersion::Mpeg1) => SampleRate::Hz32000,
(0b00_00, MpegVersion::Mpeg2) => SampleRate::Hz22050,
(0b01_00, MpegVersion::Mpeg2) => SampleRate::Hz24000,
(0b10_00, MpegVersion::Mpeg2) => SampleRate::Hz16000,
(0b00_00, MpegVersion::Mpeg2_5) => SampleRate::Hz11025,
(0b01_00, MpegVersion::Mpeg2_5) => SampleRate::Hz12000,
(0b10_00, MpegVersion::Mpeg2_5) => SampleRate::Hz8000,
(0b11_00, _) => return Err(Error::UnsupportedSampleRate),
_ => unreachable!(),
};
Ok(sample_rate)
}
pub fn decode_channel_mode(byte: u8) -> ChannelMode {
let channel_mode = match byte & 0b1100_0000 {
0b0000_0000 => ChannelMode::Stereo,
0b0100_0000 => ChannelMode::JointStereo,
0b1000_0000 => ChannelMode::DualChannel,
0b1100_0000 => ChannelMode::Mono,
_ => unreachable!(),
};
channel_mode
}
pub fn decode_mode_extension(byte: u8) -> Option<ModeExtension> {
let mode_extension = match byte & 0b0011_0000 {
0b0000_0000 => ModeExtension::Bands4To31,
0b0001_0000 => ModeExtension::Bands8To31,
0b0010_0000 => ModeExtension::Bands12To31,
0b0011_0000 => ModeExtension::Bands16To31,
_ => unreachable!(),
};
let channel_mode = decode_channel_mode(byte);
match channel_mode {
ChannelMode::JointStereo => Some(mode_extension),
_ => None,
}
}
pub fn decode_copyrigth(byte: u8) -> bool {
let copyrigth = match byte & 0b0000_1000 {
0b0000_0000 => false,
0b0000_1000 => true,
_ => unreachable!(),
};
copyrigth
}
pub fn decode_original(byte: u8) -> bool {
let original = match byte & 0b0000_0100 {
0b0000_0000 => false,
0b0000_0100 => true,
_ => unreachable!(),
};
original
}
pub fn decode_emphasis(byte: u8) -> Emphasis {
let emphasis = match byte & 0b0000_0011 {
0b00_00 => Emphasis::None,
0b00_01 => Emphasis::FiftyFifteenMs,
0b00_10 => Emphasis::Reserved,
0b00_11 => Emphasis::CCITJ17,
_ => unreachable!(),
};
emphasis
}
pub fn get_samples_per_frame_from_header(header: &AudioFrameHeader) -> u64 {
let samples_per_frame = match (header.version, header.layer) {
(MpegVersion::Mpeg1, MpegLayer::Layer1) => 384,
(MpegVersion::Mpeg1, MpegLayer::Layer2) => 1152,
(MpegVersion::Mpeg1, MpegLayer::Layer3) => 1152,
(MpegVersion::Mpeg2, MpegLayer::Layer1) => 384,
(MpegVersion::Mpeg2, MpegLayer::Layer2) => 1152,
(MpegVersion::Mpeg2, MpegLayer::Layer3) => 576,
(MpegVersion::Mpeg2_5, MpegLayer::Layer1) => 384,
(MpegVersion::Mpeg2_5, MpegLayer::Layer2) => 1152,
(MpegVersion::Mpeg2_5, MpegLayer::Layer3) => 576,
_ => unreachable!(),
};
samples_per_frame
}
pub fn get_xing_offset_from_header(header: &AudioFrameHeader) -> u64 {
match (header.version, header.channel_mode) {
(MpegVersion::Mpeg1, ChannelMode::Stereo) => 32,
(MpegVersion::Mpeg1, ChannelMode::JointStereo) => 32,
(MpegVersion::Mpeg1, ChannelMode::DualChannel) => 32,
(MpegVersion::Mpeg1, ChannelMode::Mono) => 17,
(MpegVersion::Mpeg2, ChannelMode::Stereo) => 17,
(MpegVersion::Mpeg2, ChannelMode::JointStereo) => 17,
(MpegVersion::Mpeg2, ChannelMode::DualChannel) => 17,
(MpegVersion::Mpeg2, ChannelMode::Mono) => 9,
(MpegVersion::Mpeg2_5, ChannelMode::Stereo) => 17,
(MpegVersion::Mpeg2_5, ChannelMode::JointStereo) => 17,
(MpegVersion::Mpeg2_5, ChannelMode::DualChannel) => 17,
(MpegVersion::Mpeg2_5, ChannelMode::Mono) => 9,
}
}
pub fn is_xing_or_info(buffer: &[u8]) -> bool {
if buffer.len() < 4 {
return false;
}
return &buffer[0..4] == b"Xing" || &buffer[0..4] == b"Info";
}
pub fn decode_xing_flags(buffer: &[u8]) -> Result<XingHeaderFlags> {
if buffer.len() < 4 {
return Err(Error::XingBufferTooShort);
}
let flags = (buffer[0] as u32) << 24
| (buffer[1] as u32) << 16
| (buffer[2] as u32) << 8
| buffer[3] as u32;
let has_frames = 0 != (flags & 0b0000_0001);
let has_bytes = 0 != (flags & 0b0000_0010);
let has_toc = 0 != (flags & 0b0000_0100);
let has_quality = 0 != (flags & 0b0000_1000);
let has_sample_rate = 0 != (flags & 0b0001_0000);
let has_channels = 0 != (flags & 0b0010_0000);
let has_vbr_scale = 0 != (flags & 0b0100_0000);
let flags = XingHeaderFlags {
frames: has_frames,
bytes: has_bytes,
toc: has_toc,
quality: has_quality,
sample_rate: has_sample_rate,
channels: has_channels,
vbr_scale: has_vbr_scale,
};
Ok(flags)
}
pub fn decode_xing_header(buffer: &[u8; XING_BUFFER_SIZE]) -> Result<XingHeader> {
if buffer.len() < XING_BUFFER_SIZE {
return Err(Error::XingBufferTooShort);
}
let flags = decode_xing_flags(&buffer[4..9])?;
let frames = if flags.frames {
let frames = (buffer[8] as u64) << 24
| (buffer[9] as u64) << 16
| (buffer[10] as u64) << 8
| buffer[11] as u64;
Some(frames)
} else {
None
};
Ok(XingHeader {
flags,
frames,
bytes: None,
toc: None,
quality: None,
sample_rate: None,
channels: None,
vbr_scale: None,
})
}
pub fn get_frame_size_from_header(header: &AudioFrameHeader) -> u64 {
let samples_per_frame = get_samples_per_frame_from_header(header);
samples_per_frame / 8 * header.bitrate.bps() / header.sample_rate.hz() + header.padding as u64
}
pub fn get_frame_duration(samples_per_frame: u64, sample_rate: u64) -> Duration {
let nanos = samples_per_frame as f64 / sample_rate as f64 * 1_000_000_000 as f64;
Duration::from_nanos(nanos as u64)
}
pub fn get_frame_duration_from_header(header: &AudioFrameHeader) -> Duration {
let samples_per_frame = get_samples_per_frame_from_header(header);
get_frame_duration(samples_per_frame, header.sample_rate.hz())
}
pub fn compute_frame_index(audio_frames: &Vec<AudioFrame>) -> Vec<(Duration, u64)> {
let mut offset = 0;
let mut time = Duration::from_secs(0);
audio_frames
.iter()
.map(|frame| {
let frame_duration = get_frame_duration_from_header(&frame.header);
let frame_index = (time, offset);
time += frame_duration;
offset = frame.offset;
frame_index
})
.collect()
}
pub fn get_offset_for_time(frame_index: &Vec<(Duration, u64)>, time: Duration) -> u64 {
let mut offset = 0;
for (frame_time, frame_offset) in frame_index {
if *frame_time > time {
break;
}
offset = *frame_offset;
}
offset
}