#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum AudioSsrc {
None = 0,
Alac44100S16Stereo = 0x0000FACE,
Alac48000S24Stereo = 0x15000000,
Aac44100F24Stereo = 0x16000000,
Aac48000F24Stereo = 0x17000000,
Aac48000F24Surround51 = 0x27000000,
Aac48000F24Surround71 = 0x28000000,
}
impl AudioSsrc {
pub fn from_u32(v: u32) -> Self {
match v {
0x0000FACE => Self::Alac44100S16Stereo,
0x15000000 => Self::Alac48000S24Stereo,
0x16000000 => Self::Aac44100F24Stereo,
0x17000000 => Self::Aac48000F24Stereo,
0x27000000 => Self::Aac48000F24Surround51,
0x28000000 => Self::Aac48000F24Surround71,
_ => Self::None,
}
}
pub fn is_aac(self) -> bool {
matches!(
self,
Self::Aac44100F24Stereo
| Self::Aac48000F24Stereo
| Self::Aac48000F24Surround51
| Self::Aac48000F24Surround71
)
}
pub fn sample_rate(self) -> u32 {
match self {
Self::Alac44100S16Stereo | Self::Aac44100F24Stereo => 44100,
_ => 48000,
}
}
pub fn channels(self) -> u8 {
match self {
Self::Aac48000F24Surround51 => 6,
Self::Aac48000F24Surround71 => 8,
_ => 2,
}
}
pub fn adts_channel_config(self) -> u8 {
match self {
Self::Aac48000F24Surround51 => 6,
Self::Aac48000F24Surround71 => 7,
_ => 2,
}
}
}
pub fn adts_header(packet_len: usize, rate: u32, channels: u8) -> [u8; 7] {
let profile = 2u8; let freq_idx: u8 = match rate {
48000 => 3,
44100 => 4,
_ => 4, };
let chan_cfg = channels;
let len = packet_len as u16;
[
0xFF,
0xF9,
((profile - 1) << 6) | (freq_idx << 2) | (chan_cfg >> 2),
((chan_cfg & 3) << 6) | ((len >> 11) as u8),
((len & 0x7FF) >> 3) as u8,
(((len & 7) as u8) << 5) | 0x1F,
0xFC,
]
}
pub fn wrap_adts(raw_aac: &[u8], rate: u32, channels: u8) -> Vec<u8> {
let total_len = raw_aac.len() + 7;
let header = adts_header(total_len, rate, channels);
let mut out = Vec::with_capacity(total_len);
out.extend_from_slice(&header);
out.extend_from_slice(raw_aac);
out
}
pub struct AacDecoder {
decoder: Box<dyn symphonia::core::codecs::Decoder>,
sample_rate: u32,
channels: u8,
}
impl AacDecoder {
pub fn new(sample_rate: u32, channels: u8) -> Result<Self, String> {
use symphonia::core::audio::Channels;
use symphonia::core::codecs::{CODEC_TYPE_AAC, CodecParameters, DecoderOptions};
let mut params = CodecParameters::new();
params.for_codec(CODEC_TYPE_AAC).with_sample_rate(sample_rate);
let ch = match channels {
1 => Channels::FRONT_CENTRE,
2 => Channels::FRONT_LEFT | Channels::FRONT_RIGHT,
6 => {
Channels::FRONT_LEFT
| Channels::FRONT_RIGHT
| Channels::FRONT_CENTRE
| Channels::REAR_LEFT
| Channels::REAR_RIGHT
| Channels::LFE1
}
8 => {
Channels::FRONT_LEFT
| Channels::FRONT_RIGHT
| Channels::FRONT_CENTRE
| Channels::SIDE_LEFT
| Channels::SIDE_RIGHT
| Channels::REAR_LEFT
| Channels::REAR_RIGHT
| Channels::LFE1
}
_ => Channels::FRONT_LEFT | Channels::FRONT_RIGHT,
};
params.with_channels(ch);
let decoder = symphonia::default::get_codecs()
.make(¶ms, &DecoderOptions::default())
.map_err(|e| format!("AAC decoder init failed: {e}"))?;
Ok(Self {
decoder,
sample_rate,
channels,
})
}
pub fn decode(&mut self, raw_aac: &[u8]) -> Option<Vec<u8>> {
use symphonia::core::audio::SampleBuffer;
use symphonia::core::formats::Packet;
let packet = Packet::new_from_slice(0, 0, 1024, raw_aac);
let decoded = self.decoder.decode(&packet).ok()?;
let spec = *decoded.spec();
let duration = decoded.capacity() as u64;
let mut sample_buf = SampleBuffer::<f32>::new(duration, spec);
sample_buf.copy_interleaved_ref(decoded);
let samples = sample_buf.samples();
let mut pcm = Vec::with_capacity(samples.len() * 4);
for &s in samples {
pcm.extend_from_slice(&s.to_le_bytes());
}
Some(pcm)
}
pub fn sample_rate(&self) -> u32 {
self.sample_rate
}
pub fn channels(&self) -> u8 {
self.channels
}
}
#[cfg(test)]
mod tests {
use super::*;
fn hex_encode(data: &[u8]) -> String {
data.iter().map(|b| format!("{b:02x}")).collect()
}
#[test]
fn c_vector_adts_44100_stereo_107() {
let h = adts_header(107, 44100, 2);
assert_eq!(hex_encode(&h), "fff950800d7ffc");
}
#[test]
fn c_vector_adts_48000_stereo_507() {
let h = adts_header(507, 48000, 2);
assert_eq!(hex_encode(&h), "fff94c803f7ffc");
}
#[test]
fn c_vector_adts_44100_stereo_1031() {
let h = adts_header(1031, 44100, 2);
assert_eq!(hex_encode(&h), "fff9508080fffc");
}
#[test]
fn wrap_adts_prepends_header() {
let raw = vec![0xDE, 0xAD];
let wrapped = wrap_adts(&raw, 44100, 2);
assert_eq!(wrapped.len(), 9); assert_eq!(&wrapped[0..2], &[0xFF, 0xF9]); assert_eq!(&wrapped[7..], &[0xDE, 0xAD]); }
}