use std::{
borrow::Cow,
num::{NonZeroU32, NonZeroUsize},
};
use symphonia::core::{
audio::{AudioBuffer, AudioBufferRef, Signal},
codecs::Decoder,
conv::FromSample,
probe::ProbeResult,
sample::{i24, u24},
};
use super::{check_total_frames, decode_warning, shrink_buffer};
use crate::{DecodeConfig, DecodedAudio, DecodedAudioType, error::LoadError};
pub(crate) fn decode_native_bitdepth(
probed: &mut ProbeResult,
config: &DecodeConfig,
num_channels: NonZeroUsize,
sample_rate: NonZeroU32,
original_sample_rate: NonZeroU32,
decoder: &mut dyn Decoder,
) -> Result<DecodedAudio, LoadError> {
let FirstPacketInfo {
first_packet_type,
file_frames,
max_frames,
mut total_frames,
track_id,
} = decode_first_packet(probed, num_channels, config.max_bytes, decoder)?;
let unexpected_format = |expected: &str| -> LoadError {
LoadError::UnexpectedErrorWhileDecoding(
format!(
"Symphonia returned a packet that was not the expected format of {}",
expected
)
.into(),
)
};
let pcm_type = match first_packet_type {
FirstPacketType::U8(mut decoded_channels) => {
while let Ok(packet) = probed.format.next_packet() {
if packet.track_id() != track_id {
continue;
}
match decoder.decode(&packet) {
Ok(decoded) => match decoded {
AudioBufferRef::U8(d) => {
if file_frames.is_none() {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
config.max_bytes,
)?;
}
decode_u8_packet(&mut decoded_channels, d, num_channels);
}
_ => return Err(unexpected_format("u8")),
},
Err(symphonia::core::errors::Error::DecodeError(err)) => decode_warning(err),
Err(e) => return Err(LoadError::ErrorWhileDecoding(e)),
}
}
shrink_buffer(&mut decoded_channels);
DecodedAudioType::U8(decoded_channels)
}
FirstPacketType::U16(mut decoded_channels) => {
while let Ok(packet) = probed.format.next_packet() {
if packet.track_id() != track_id {
continue;
}
match decoder.decode(&packet) {
Ok(decoded) => match decoded {
AudioBufferRef::U16(d) => {
if file_frames.is_none() {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
config.max_bytes,
)?;
}
decode_u16_packet(&mut decoded_channels, d, num_channels);
}
_ => return Err(unexpected_format("u16")),
},
Err(symphonia::core::errors::Error::DecodeError(err)) => decode_warning(err),
Err(e) => return Err(LoadError::ErrorWhileDecoding(e)),
}
}
shrink_buffer(&mut decoded_channels);
DecodedAudioType::U16(decoded_channels)
}
FirstPacketType::U24(mut decoded_channels) => {
while let Ok(packet) = probed.format.next_packet() {
if packet.track_id() != track_id {
continue;
}
match decoder.decode(&packet) {
Ok(decoded) => match decoded {
AudioBufferRef::U24(d) => {
if file_frames.is_none() {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
config.max_bytes,
)?;
}
decode_u24_packet(&mut decoded_channels, d, num_channels);
}
_ => return Err(unexpected_format("u24")),
},
Err(symphonia::core::errors::Error::DecodeError(err)) => decode_warning(err),
Err(e) => return Err(LoadError::ErrorWhileDecoding(e)),
}
}
shrink_buffer(&mut decoded_channels);
DecodedAudioType::U24(decoded_channels)
}
FirstPacketType::U32(mut decoded_channels) => {
while let Ok(packet) = probed.format.next_packet() {
if packet.track_id() != track_id {
continue;
}
match decoder.decode(&packet) {
Ok(decoded) => match decoded {
AudioBufferRef::U32(d) => {
if file_frames.is_none() {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
config.max_bytes,
)?;
}
decode_u32_packet(&mut decoded_channels, d, num_channels);
}
_ => return Err(unexpected_format("u32")),
},
Err(symphonia::core::errors::Error::DecodeError(err)) => decode_warning(err),
Err(e) => return Err(LoadError::ErrorWhileDecoding(e)),
}
}
shrink_buffer(&mut decoded_channels);
DecodedAudioType::F32(decoded_channels)
}
FirstPacketType::S8(mut decoded_channels) => {
while let Ok(packet) = probed.format.next_packet() {
if packet.track_id() != track_id {
continue;
}
match decoder.decode(&packet) {
Ok(decoded) => match decoded {
AudioBufferRef::S8(d) => {
if file_frames.is_none() {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
config.max_bytes,
)?;
}
decode_i8_packet(&mut decoded_channels, d, num_channels);
}
_ => return Err(unexpected_format("i8")),
},
Err(symphonia::core::errors::Error::DecodeError(err)) => decode_warning(err),
Err(e) => return Err(LoadError::ErrorWhileDecoding(e)),
}
}
shrink_buffer(&mut decoded_channels);
DecodedAudioType::S8(decoded_channels)
}
FirstPacketType::S16(mut decoded_channels) => {
while let Ok(packet) = probed.format.next_packet() {
if packet.track_id() != track_id {
continue;
}
match decoder.decode(&packet) {
Ok(decoded) => match decoded {
AudioBufferRef::S16(d) => {
if file_frames.is_none() {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
config.max_bytes,
)?;
}
decode_i16_packet(&mut decoded_channels, d, num_channels);
}
_ => return Err(unexpected_format("i16")),
},
Err(symphonia::core::errors::Error::DecodeError(err)) => decode_warning(err),
Err(e) => return Err(LoadError::ErrorWhileDecoding(e)),
}
}
shrink_buffer(&mut decoded_channels);
DecodedAudioType::S16(decoded_channels)
}
FirstPacketType::S24(mut decoded_channels) => {
while let Ok(packet) = probed.format.next_packet() {
if packet.track_id() != track_id {
continue;
}
match decoder.decode(&packet) {
Ok(decoded) => match decoded {
AudioBufferRef::S24(d) => {
if file_frames.is_none() {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
config.max_bytes,
)?;
}
decode_i24_packet(&mut decoded_channels, d, num_channels);
}
_ => return Err(unexpected_format("i24")),
},
Err(symphonia::core::errors::Error::DecodeError(err)) => decode_warning(err),
Err(e) => return Err(LoadError::ErrorWhileDecoding(e)),
}
}
shrink_buffer(&mut decoded_channels);
DecodedAudioType::U24(decoded_channels)
}
FirstPacketType::S32(mut decoded_channels) => {
while let Ok(packet) = probed.format.next_packet() {
if packet.track_id() != track_id {
continue;
}
match decoder.decode(&packet) {
Ok(decoded) => match decoded {
AudioBufferRef::S32(d) => {
if file_frames.is_none() {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
config.max_bytes,
)?;
}
decode_i32_packet(&mut decoded_channels, d, num_channels);
}
_ => return Err(unexpected_format("i32")),
},
Err(symphonia::core::errors::Error::DecodeError(err)) => decode_warning(err),
Err(e) => return Err(LoadError::ErrorWhileDecoding(e)),
}
}
shrink_buffer(&mut decoded_channels);
DecodedAudioType::F32(decoded_channels)
}
FirstPacketType::F32(mut decoded_channels) => {
while let Ok(packet) = probed.format.next_packet() {
if packet.track_id() != track_id {
continue;
}
match decoder.decode(&packet) {
Ok(decoded) => match decoded {
AudioBufferRef::F32(d) => {
if file_frames.is_none() {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
config.max_bytes,
)?;
}
decode_f32_packet(&mut decoded_channels, d, num_channels);
}
_ => return Err(unexpected_format("f32")),
},
Err(symphonia::core::errors::Error::DecodeError(err)) => decode_warning(err),
Err(e) => return Err(LoadError::ErrorWhileDecoding(e)),
}
}
shrink_buffer(&mut decoded_channels);
DecodedAudioType::F32(decoded_channels)
}
FirstPacketType::F64(mut decoded_channels) => {
while let Ok(packet) = probed.format.next_packet() {
if packet.track_id() != track_id {
continue;
}
match decoder.decode(&packet) {
Ok(decoded) => match decoded {
AudioBufferRef::F64(d) => {
if file_frames.is_none() {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
config.max_bytes,
)?;
}
decode_f64_packet(&mut decoded_channels, d, num_channels);
}
_ => return Err(unexpected_format("f64")),
},
Err(symphonia::core::errors::Error::DecodeError(err)) => decode_warning(err),
Err(e) => return Err(LoadError::ErrorWhileDecoding(e)),
}
}
shrink_buffer(&mut decoded_channels);
DecodedAudioType::F64(decoded_channels)
}
};
Ok(DecodedAudio::new(
pcm_type,
sample_rate,
original_sample_rate,
))
}
struct FirstPacketInfo {
first_packet_type: FirstPacketType,
file_frames: Option<u64>,
max_frames: usize,
total_frames: usize,
track_id: u32,
}
enum FirstPacketType {
U8(Vec<Vec<u8>>),
U16(Vec<Vec<u16>>),
U24(Vec<Vec<[u8; 3]>>),
U32(Vec<Vec<f32>>),
S8(Vec<Vec<i8>>),
S16(Vec<Vec<i16>>),
S24(Vec<Vec<[u8; 3]>>),
S32(Vec<Vec<f32>>),
F32(Vec<Vec<f32>>),
F64(Vec<Vec<f64>>),
}
fn decode_first_packet(
probed: &mut ProbeResult,
num_channels: NonZeroUsize,
max_bytes: usize,
decoder: &mut dyn Decoder,
) -> Result<FirstPacketInfo, LoadError> {
let track = probed
.format
.default_track()
.ok_or_else(|| LoadError::NoTrackFound)?;
let track_id = track.id;
let file_frames = track.codec_params.n_frames;
let mut max_frames = 0;
let mut total_frames = 0;
let mut first_packet = None;
let channel_capacity = |packet_capacity: usize| -> usize {
file_frames
.map(|f| f as usize + packet_capacity)
.unwrap_or(packet_capacity.next_power_of_two())
};
while let Ok(packet) = probed.format.next_packet() {
if packet.track_id() != track_id {
continue;
}
match decoder.decode(&packet) {
Ok(decoded) => match decoded {
AudioBufferRef::U8(d) => {
let packet_capacity = d.capacity();
let mut decoded_channels = Vec::<Vec<u8>>::new();
decoded_channels.reserve_exact(num_channels.get());
let capacity = channel_capacity(packet_capacity);
for _ in 0..num_channels.get() {
let mut v = Vec::new();
v.reserve_exact(capacity);
decoded_channels.push(v);
}
max_frames = max_bytes / num_channels;
if let Some(file_frames) = file_frames {
if file_frames > max_frames as u64 {
return Err(LoadError::FileTooLarge(max_bytes));
}
} else {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
max_bytes,
)?;
}
decode_u8_packet(&mut decoded_channels, d, num_channels);
first_packet = Some(FirstPacketType::U8(decoded_channels));
break;
}
AudioBufferRef::U16(d) => {
let packet_capacity = d.capacity();
let mut decoded_channels = Vec::<Vec<u16>>::new();
decoded_channels.reserve_exact(num_channels.get());
let capacity = channel_capacity(packet_capacity);
for _ in 0..num_channels.get() {
let mut v = Vec::new();
v.reserve_exact(capacity);
decoded_channels.push(v);
}
max_frames = max_bytes / (2 * num_channels.get());
if let Some(file_frames) = file_frames {
if file_frames > max_frames as u64 {
return Err(LoadError::FileTooLarge(max_bytes));
}
} else {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
max_bytes,
)?;
}
decode_u16_packet(&mut decoded_channels, d, num_channels);
first_packet = Some(FirstPacketType::U16(decoded_channels));
break;
}
AudioBufferRef::U24(d) => {
let packet_capacity = d.capacity();
let mut decoded_channels = Vec::<Vec<[u8; 3]>>::new();
decoded_channels.reserve_exact(num_channels.get());
let capacity = channel_capacity(packet_capacity);
for _ in 0..num_channels.get() {
let mut v = Vec::new();
v.reserve_exact(capacity);
decoded_channels.push(v);
}
max_frames = max_bytes / (3 * num_channels.get());
if let Some(file_frames) = file_frames {
if file_frames > max_frames as u64 {
return Err(LoadError::FileTooLarge(max_bytes));
}
} else {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
max_bytes,
)?;
}
decode_u24_packet(&mut decoded_channels, d, num_channels);
first_packet = Some(FirstPacketType::U24(decoded_channels));
break;
}
AudioBufferRef::U32(d) => {
let packet_capacity = d.capacity();
let mut decoded_channels = Vec::<Vec<f32>>::new();
decoded_channels.reserve_exact(num_channels.get());
let capacity = channel_capacity(packet_capacity);
for _ in 0..num_channels.get() {
let mut v = Vec::new();
v.reserve_exact(capacity);
decoded_channels.push(v);
}
max_frames = max_bytes / (4 * num_channels.get());
if let Some(file_frames) = file_frames {
if file_frames > max_frames as u64 {
return Err(LoadError::FileTooLarge(max_bytes));
}
} else {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
max_bytes,
)?;
}
decode_u32_packet(&mut decoded_channels, d, num_channels);
first_packet = Some(FirstPacketType::U32(decoded_channels));
break;
}
AudioBufferRef::S8(d) => {
let packet_capacity = d.capacity();
let mut decoded_channels = Vec::<Vec<i8>>::new();
decoded_channels.reserve_exact(num_channels.get());
let capacity = channel_capacity(packet_capacity);
for _ in 0..num_channels.get() {
let mut v = Vec::new();
v.reserve_exact(capacity);
decoded_channels.push(v);
}
max_frames = max_bytes / num_channels;
if let Some(file_frames) = file_frames {
if file_frames > max_frames as u64 {
return Err(LoadError::FileTooLarge(max_bytes));
}
} else {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
max_bytes,
)?;
}
decode_i8_packet(&mut decoded_channels, d, num_channels);
first_packet = Some(FirstPacketType::S8(decoded_channels));
break;
}
AudioBufferRef::S16(d) => {
let packet_capacity = d.capacity();
let mut decoded_channels = Vec::<Vec<i16>>::new();
decoded_channels.reserve_exact(num_channels.get());
let capacity = channel_capacity(packet_capacity);
for _ in 0..num_channels.get() {
let mut v = Vec::new();
v.reserve_exact(capacity);
decoded_channels.push(v);
}
max_frames = max_bytes / (2 * num_channels.get());
if let Some(file_frames) = file_frames {
if file_frames > max_frames as u64 {
return Err(LoadError::FileTooLarge(max_bytes));
}
} else {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
max_bytes,
)?;
}
decode_i16_packet(&mut decoded_channels, d, num_channels);
first_packet = Some(FirstPacketType::S16(decoded_channels));
break;
}
AudioBufferRef::S24(d) => {
let packet_capacity = d.capacity();
let mut decoded_channels = Vec::<Vec<[u8; 3]>>::new();
decoded_channels.reserve_exact(num_channels.get());
let capacity = channel_capacity(packet_capacity);
for _ in 0..num_channels.get() {
let mut v = Vec::new();
v.reserve_exact(capacity);
decoded_channels.push(v);
}
max_frames = max_bytes / (3 * num_channels.get());
if let Some(file_frames) = file_frames {
if file_frames > max_frames as u64 {
return Err(LoadError::FileTooLarge(max_bytes));
}
} else {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
max_bytes,
)?;
}
decode_i24_packet(&mut decoded_channels, d, num_channels);
first_packet = Some(FirstPacketType::S24(decoded_channels));
break;
}
AudioBufferRef::S32(d) => {
let packet_capacity = d.capacity();
let mut decoded_channels = Vec::<Vec<f32>>::new();
decoded_channels.reserve_exact(num_channels.get());
let capacity = channel_capacity(packet_capacity);
for _ in 0..num_channels.get() {
let mut v = Vec::new();
v.reserve_exact(capacity);
decoded_channels.push(v);
}
max_frames = max_bytes / (4 * num_channels.get());
if let Some(file_frames) = file_frames {
if file_frames > max_frames as u64 {
return Err(LoadError::FileTooLarge(max_bytes));
}
} else {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
max_bytes,
)?;
}
decode_i32_packet(&mut decoded_channels, d, num_channels);
first_packet = Some(FirstPacketType::S32(decoded_channels));
break;
}
AudioBufferRef::F32(d) => {
let packet_capacity = d.capacity();
let mut decoded_channels = Vec::<Vec<f32>>::new();
decoded_channels.reserve_exact(num_channels.get());
let capacity = channel_capacity(packet_capacity);
for _ in 0..num_channels.get() {
let mut v = Vec::new();
v.reserve_exact(capacity);
decoded_channels.push(v);
}
max_frames = max_bytes / (4 * num_channels.get());
if let Some(file_frames) = file_frames {
if file_frames > max_frames as u64 {
return Err(LoadError::FileTooLarge(max_bytes));
}
} else {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
max_bytes,
)?;
}
decode_f32_packet(&mut decoded_channels, d, num_channels);
first_packet = Some(FirstPacketType::F32(decoded_channels));
break;
}
AudioBufferRef::F64(d) => {
let packet_capacity = d.capacity();
let mut decoded_channels = Vec::<Vec<f64>>::new();
decoded_channels.reserve_exact(num_channels.get());
let capacity = channel_capacity(packet_capacity);
for _ in 0..num_channels.get() {
let mut v = Vec::new();
v.reserve_exact(capacity);
decoded_channels.push(v);
}
max_frames = max_bytes / (8 * num_channels.get());
if let Some(file_frames) = file_frames {
if file_frames > max_frames as u64 {
return Err(LoadError::FileTooLarge(max_bytes));
}
} else {
check_total_frames(
&mut total_frames,
max_frames,
d.chan(0).len(),
max_bytes,
)?;
}
decode_f64_packet(&mut decoded_channels, d, num_channels);
first_packet = Some(FirstPacketType::F64(decoded_channels));
break;
}
},
Err(symphonia::core::errors::Error::DecodeError(err)) => {
decode_warning(err);
}
Err(e) => return Err(LoadError::ErrorWhileDecoding(e)),
};
}
first_packet
.map(|packet_type| FirstPacketInfo {
first_packet_type: packet_type,
file_frames,
max_frames,
total_frames,
track_id,
})
.ok_or_else(|| LoadError::UnexpectedErrorWhileDecoding("no packet was found".into()))
}
fn decode_u8_packet(
decoded_channels: &mut [Vec<u8>],
packet: Cow<AudioBuffer<u8>>,
num_channels: NonZeroUsize,
) {
for (i, ch) in decoded_channels
.iter_mut()
.enumerate()
.take(num_channels.get())
{
ch.extend_from_slice(packet.chan(i));
}
}
fn decode_u16_packet(
decoded_channels: &mut [Vec<u16>],
packet: Cow<AudioBuffer<u16>>,
num_channels: NonZeroUsize,
) {
for (i, ch) in decoded_channels
.iter_mut()
.enumerate()
.take(num_channels.get())
{
ch.extend_from_slice(packet.chan(i));
}
}
fn decode_u24_packet(
decoded_channels: &mut [Vec<[u8; 3]>],
packet: Cow<AudioBuffer<u24>>,
num_channels: NonZeroUsize,
) {
for (i, ch) in decoded_channels
.iter_mut()
.enumerate()
.take(num_channels.get())
{
for s in packet.chan(i).iter() {
ch.push(s.to_ne_bytes());
}
}
}
fn decode_u32_packet(
decoded_channels: &mut [Vec<f32>],
packet: Cow<AudioBuffer<u32>>,
num_channels: NonZeroUsize,
) {
for (i, ch) in decoded_channels
.iter_mut()
.enumerate()
.take(num_channels.get())
{
for s in packet.chan(i).iter() {
ch.push(FromSample::from_sample(*s));
}
}
}
fn decode_i8_packet(
decoded_channels: &mut [Vec<i8>],
packet: Cow<AudioBuffer<i8>>,
num_channels: NonZeroUsize,
) {
for (i, ch) in decoded_channels
.iter_mut()
.enumerate()
.take(num_channels.get())
{
ch.extend_from_slice(packet.chan(i));
}
}
fn decode_i16_packet(
decoded_channels: &mut [Vec<i16>],
packet: Cow<AudioBuffer<i16>>,
num_channels: NonZeroUsize,
) {
for (i, ch) in decoded_channels
.iter_mut()
.enumerate()
.take(num_channels.get())
{
ch.extend_from_slice(packet.chan(i));
}
}
fn decode_i24_packet(
decoded_channels: &mut [Vec<[u8; 3]>],
packet: Cow<AudioBuffer<i24>>,
num_channels: NonZeroUsize,
) {
for (i, ch) in decoded_channels
.iter_mut()
.enumerate()
.take(num_channels.get())
{
for s in packet.chan(i).iter() {
ch.push(u24::from_sample(*s).to_ne_bytes());
}
}
}
fn decode_i32_packet(
decoded_channels: &mut [Vec<f32>],
packet: Cow<AudioBuffer<i32>>,
num_channels: NonZeroUsize,
) {
for (i, ch) in decoded_channels
.iter_mut()
.enumerate()
.take(num_channels.get())
{
for s in packet.chan(i).iter() {
ch.push(FromSample::from_sample(*s));
}
}
}
fn decode_f32_packet(
decoded_channels: &mut [Vec<f32>],
packet: Cow<AudioBuffer<f32>>,
num_channels: NonZeroUsize,
) {
for (i, ch) in decoded_channels
.iter_mut()
.enumerate()
.take(num_channels.get())
{
ch.extend_from_slice(packet.chan(i));
}
}
fn decode_f64_packet(
decoded_channels: &mut [Vec<f64>],
packet: Cow<AudioBuffer<f64>>,
num_channels: NonZeroUsize,
) {
for (i, ch) in decoded_channels
.iter_mut()
.enumerate()
.take(num_channels.get())
{
ch.extend_from_slice(packet.chan(i));
}
}