use symphonia_core::codecs::audio::AudioDecoder;
use super::Backend;
use crate::decode::Decoded;
use crate::{Activity, Error, Layout, aac};
pub(super) const NAME: &str = "symphonia";
pub(super) struct Symphonia {
inner: symphonia_codec_aac::AacDecoder,
sample_rate: u32,
layout: Layout,
}
impl Symphonia {
pub(super) fn open(catalog: &hang::catalog::AudioConfig) -> Result<Box<dyn Backend>, Error> {
use symphonia_core::codecs::audio::well_known::CODEC_ID_AAC;
use symphonia_core::codecs::audio::{AudioCodecParameters, AudioDecoderOptions};
let hang::catalog::AudioCodec::AAC(codec) = &catalog.codec else {
return Err(Error::Unsupported(format!("symphonia cannot decode {}", catalog.codec)));
};
let description = aac::description(catalog, codec.profile)?;
let mut params = AudioCodecParameters::new();
params
.for_codec(CODEC_ID_AAC)
.with_extra_data(description.to_vec().into_boxed_slice());
let inner = symphonia_codec_aac::AacDecoder::try_new(¶ms, &AudioDecoderOptions::default())
.map_err(|err| Error::Unsupported(format!("aac decoder: {err}")))?;
let params = inner.codec_params();
let sample_rate = params
.sample_rate
.ok_or_else(|| Error::Unsupported("aac config declares no sample rate".into()))?;
let channel_count = params
.channels
.as_ref()
.map(|channels| channels.count())
.ok_or_else(|| Error::Unsupported("aac config declares no channels".into()))?;
Ok(Box::new(Self {
inner,
sample_rate,
layout: Layout::from_channels(channel_count as u32)?,
}))
}
}
impl Backend for Symphonia {
fn decode(&mut self, packet: &[u8]) -> Result<Decoded, Error> {
let packet = symphonia_core::packet::PacketRef::new(
0,
symphonia_core::units::Timestamp::ZERO,
symphonia_core::units::Duration::ZERO,
packet,
);
let decoded = self
.inner
.decode_ref(&packet)
.map_err(|err| Error::Decode(format!("aac: {err}")))?;
let mut samples = Vec::new();
decoded.copy_to_vec_interleaved(&mut samples);
Ok(Decoded {
samples,
activity: Activity::Active,
})
}
fn reset(&mut self) -> Result<(), Error> {
self.inner.reset();
Ok(())
}
fn sample_rate(&self) -> u32 {
self.sample_rate
}
fn layout(&self) -> Layout {
self.layout
}
fn name(&self) -> &str {
NAME
}
}