#![warn(rust_2018_idioms)]
#![forbid(unsafe_code)]
#![allow(clippy::comparison_chain)]
#![allow(clippy::excessive_precision)]
#![allow(clippy::identity_op)]
#![allow(clippy::manual_range_contains)]
#![allow(clippy::collapsible_else_if)]
use std::cmp::min;
use symphonia_core::audio::{
AsAudioBufferRef, AudioBuffer, AudioBufferRef, Channels, Signal, SignalSpec,
};
use symphonia_core::codecs::{
CodecDescriptor, CodecParameters, Decoder, DecoderOptions, FinalizeResult, CODEC_TYPE_ALAC,
};
use symphonia_core::errors::{decode_error, unsupported_error, Result};
use symphonia_core::formats::Packet;
use symphonia_core::io::{BitReaderLtr, BufReader, FiniteStream, ReadBitsLtr, ReadBytes};
use symphonia_core::support_codec;
const ALAC_VERSION: u8 = 0;
const ALAC_ELEM_TAG_SCE: u32 = 0;
const ALAC_ELEM_TAG_CPE: u32 = 1;
const ALAC_ELEM_TAG_CCE: u32 = 2;
const ALAC_ELEM_TAG_LFE: u32 = 3;
const ALAC_ELEM_TAG_DSE: u32 = 4;
const ALAC_ELEM_TAG_PCE: u32 = 5;
const ALAC_ELEM_TAG_FIL: u32 = 6;
const ALAC_ELEM_TAG_END: u32 = 7;
#[derive(Debug)]
enum ChannelLayout {
Mono,
Stereo,
Mpeg3p0B,
Mpeg4p0B,
Mpeg5p0D,
Mpeg5p1D,
Aac6p1,
Mpeg7p1B,
}
impl ChannelLayout {
fn channel_map(&self) -> [u8; 8] {
match self {
ChannelLayout::Mono => [0, 0, 0, 0, 0, 0, 0, 0],
ChannelLayout::Stereo => [0, 1, 0, 0, 0, 0, 0, 0],
ChannelLayout::Mpeg3p0B => [2, 0, 1, 0, 0, 0, 0, 0],
ChannelLayout::Mpeg4p0B => [2, 0, 1, 3, 0, 0, 0, 0],
ChannelLayout::Mpeg5p0D => [2, 0, 1, 3, 4, 0, 0, 0],
ChannelLayout::Mpeg5p1D => [2, 0, 1, 4, 5, 3, 0, 0],
ChannelLayout::Aac6p1 => [2, 0, 1, 5, 6, 4, 3, 0],
ChannelLayout::Mpeg7p1B => [2, 4, 5, 0, 1, 6, 7, 3],
}
}
fn channels(&self) -> Channels {
match self {
ChannelLayout::Mono => Channels::FRONT_LEFT,
ChannelLayout::Stereo => Channels::FRONT_LEFT | Channels::FRONT_RIGHT,
ChannelLayout::Mpeg3p0B => {
Channels::FRONT_CENTRE | Channels::FRONT_LEFT | Channels::FRONT_RIGHT
}
ChannelLayout::Mpeg4p0B => {
Channels::FRONT_CENTRE
| Channels::FRONT_LEFT
| Channels::FRONT_RIGHT
| Channels::REAR_CENTRE
}
ChannelLayout::Mpeg5p0D => {
Channels::FRONT_CENTRE
| Channels::FRONT_LEFT
| Channels::FRONT_RIGHT
| Channels::SIDE_LEFT
| Channels::SIDE_RIGHT
}
ChannelLayout::Mpeg5p1D => {
Channels::FRONT_CENTRE
| Channels::FRONT_LEFT
| Channels::FRONT_RIGHT
| Channels::SIDE_LEFT
| Channels::SIDE_RIGHT
| Channels::LFE1
}
ChannelLayout::Aac6p1 => {
Channels::FRONT_CENTRE
| Channels::FRONT_LEFT
| Channels::FRONT_RIGHT
| Channels::SIDE_LEFT
| Channels::SIDE_RIGHT
| Channels::REAR_CENTRE
| Channels::LFE1
}
ChannelLayout::Mpeg7p1B => {
Channels::FRONT_CENTRE
| Channels::FRONT_LEFT_CENTRE
| Channels::FRONT_RIGHT_CENTRE
| Channels::FRONT_LEFT
| Channels::FRONT_RIGHT
| Channels::SIDE_LEFT
| Channels::SIDE_RIGHT
| Channels::LFE1
}
}
}
}
#[derive(Debug)]
#[allow(dead_code)]
struct MagicCookie {
frame_length: u32,
compatible_version: u8,
bit_depth: u8,
pb: u8,
mb: u8,
kb: u8,
num_channels: u8,
max_run: u16,
max_frame_bytes: u32,
avg_bit_rate: u32,
sample_rate: u32,
channel_layout: ChannelLayout,
}
impl MagicCookie {
fn try_read<B: ReadBytes + FiniteStream>(reader: &mut B) -> Result<MagicCookie> {
if reader.byte_len() != 24 && reader.byte_len() != 48 {
return unsupported_error("alac: invalid magic cookie size");
}
let mut config = MagicCookie {
frame_length: reader.read_be_u32()?,
compatible_version: reader.read_u8()?,
bit_depth: reader.read_u8()?,
pb: reader.read_u8()?,
mb: reader.read_u8()?,
kb: reader.read_u8()?,
num_channels: reader.read_u8()?,
max_run: reader.read_be_u16()?,
max_frame_bytes: reader.read_be_u32()?,
avg_bit_rate: reader.read_be_u32()?,
sample_rate: reader.read_be_u32()?,
channel_layout: ChannelLayout::Mono,
};
if config.compatible_version > ALAC_VERSION {
return unsupported_error("alac: not compatible with alac version 0");
}
if config.bit_depth > 32 {
return decode_error("alac: invalid bit depth");
}
if config.num_channels < 1 || config.num_channels > 8 {
return unsupported_error("alac: more than 8 channels");
}
config.channel_layout = if reader.byte_len() == 48 {
if reader.read_be_u32()? != 24 {
return decode_error("alac: invalid channel layout info size");
}
if reader.read_quad_bytes()? != *b"chan" {
return decode_error("alac: invalid channel layout info id");
}
if reader.read_be_u32()? != 0 {
return decode_error("alac: invalid channel layout info version");
}
let layout = match reader.read_be_u32()? {
0x64_0001 => ChannelLayout::Mono,
0x65_0002 => ChannelLayout::Stereo,
0x71_0003 => ChannelLayout::Mpeg3p0B,
0x74_0004 => ChannelLayout::Mpeg4p0B,
0x78_0005 => ChannelLayout::Mpeg5p0D,
0x7c_0006 => ChannelLayout::Mpeg5p1D,
0x8e_0007 => ChannelLayout::Aac6p1,
0x7f_0008 => ChannelLayout::Mpeg7p1B,
_ => return decode_error("alac: invalid channel layout tag"),
};
if config.num_channels != layout.channels().count() as u8 {
return decode_error(
"alac: the number of channels differs from the channel layout",
);
}
if reader.read_be_u32()? != 0 || reader.read_be_u32()? != 0 {
return decode_error("alac: reserved values in channel layout info are not 0");
}
layout
}
else {
match config.num_channels {
1 => ChannelLayout::Mono,
2 => ChannelLayout::Stereo,
3 => ChannelLayout::Mpeg3p0B,
4 => ChannelLayout::Mpeg4p0B,
5 => ChannelLayout::Mpeg5p0D,
6 => ChannelLayout::Mpeg5p1D,
7 => ChannelLayout::Aac6p1,
8 => ChannelLayout::Mpeg7p1B,
_ => return decode_error("alac: unknown channel layout for number of channels"),
}
};
Ok(config)
}
}
#[derive(Debug)]
struct ElementChannel {
pred_bits: u32,
kb: u32,
mb: u32,
mode: u32,
shift: u32,
pb_factor: u32,
lpc_order: u32,
lpc_coeffs: [i32; 32],
}
impl ElementChannel {
fn try_read<B: ReadBitsLtr>(
bs: &mut B,
config: &MagicCookie,
pred_bits: u8,
) -> Result<ElementChannel> {
let mode = bs.read_bits_leq32(4)?;
let shift = bs.read_bits_leq32(4)?;
let pb_factor = (bs.read_bits_leq32(3)? * u32::from(config.pb)) >> 2;
let lpc_order = bs.read_bits_leq32(5)?;
let mut lpc_coeffs = [0; 32];
for coeff in &mut lpc_coeffs[..lpc_order as usize] {
*coeff = bs.read_bits_leq32_signed(16)?;
}
Ok(ElementChannel {
pred_bits: u32::from(pred_bits),
kb: u32::from(config.kb),
mb: u32::from(config.mb),
mode,
shift,
pb_factor,
lpc_order,
lpc_coeffs,
})
}
fn read_residuals<B: ReadBitsLtr>(&mut self, bs: &mut B, out: &mut [i32]) -> Result<()> {
let out_len = out.len();
let mut mb = self.mb;
let mut sign_toggle = 0;
let mut zero_run_end = 0;
for (i, sample) in out.iter_mut().enumerate() {
if i < zero_run_end {
continue;
}
let k = lg3a(mb);
let val = read_rice_code(bs, k.min(self.kb), self.pred_bits)? + sign_toggle;
*sample = rice_code_to_signed(val);
if val > 0xffff {
mb = 0xffff;
}
else {
mb -= (self.pb_factor * mb) >> 9;
mb += self.pb_factor * val;
}
sign_toggle = 0;
if mb < 128 && i + 1 < out_len {
let k = mb.leading_zeros() - 24 + ((mb + 16) >> 6);
let zeros = read_rice_code(bs, k.min(self.kb), 16)?;
if zeros < 0xffff {
sign_toggle = 1;
}
mb = 0;
zero_run_end = i + 1 + zeros as usize;
}
}
Ok(())
}
fn predict(&mut self, out: &mut [i32]) -> Result<()> {
if self.mode > 0 && self.mode < 15 {
return decode_error("alac: invalid mode");
}
if self.lpc_order == 0 {
return Ok(());
}
let num_clip_bits = 32 - self.pred_bits;
if self.lpc_order == 31 || self.mode == 15 {
for i in 1..out.len() {
out[i] = clip_msbs(out[i].wrapping_add(out[i - 1]), num_clip_bits);
}
}
let order = self.lpc_order as usize;
for i in 1..1 + order {
out[i] = clip_msbs(out[i].wrapping_add(out[i - 1]), num_clip_bits);
}
for i in 1 + order..out.len() {
let mut res = out[i];
let past0 = out[i - order - 1];
let sum = self.lpc_coeffs[..order]
.iter()
.rev()
.zip(&out[i - order..i])
.map(|(&coeff, &s)| coeff.wrapping_mul(s - past0))
.fold(0i32, |sum, s| sum.wrapping_add(s));
let val = (sum + ((1 << self.shift) >> 1)) >> self.shift;
out[i] = clip_msbs(out[i].wrapping_add(past0).wrapping_add(val), num_clip_bits);
if res != 0 {
let iter =
self.lpc_coeffs[..order].iter_mut().rev().zip(&out[i - order..i]).enumerate();
if res > 0 {
for (j, (coeff, &sample)) in iter {
let val = past0 - sample;
let sign = val.signum();
*coeff -= sign;
res -= (1 + j as i32) * ((sign * val) >> self.shift);
if res <= 0 {
break;
}
}
}
else {
for (j, (coeff, &sample)) in iter {
let val = past0 - sample;
let sign = val.signum();
*coeff += sign;
res -= (1 + j as i32) * ((-sign * val) >> self.shift);
if res >= 0 {
break;
}
}
}
}
}
Ok(())
}
}
pub struct AlacDecoder {
params: CodecParameters,
tail_bits: Vec<u16>,
config: MagicCookie,
buf: AudioBuffer<i32>,
}
impl AlacDecoder {
fn decode_inner(&mut self, packet: &Packet) -> Result<()> {
let mut bs = BitReaderLtr::new(packet.buf());
let channel_map = self.config.channel_layout.channel_map();
let num_channels = self.config.num_channels as usize;
let mut next_channel = 0;
let mut num_frames = 0;
self.buf.clear();
self.buf.render_silence(None);
loop {
let tag = bs.read_bits_leq32(3)?;
match tag {
ALAC_ELEM_TAG_SCE | ALAC_ELEM_TAG_LFE => {
let out0 = self.buf.chan_mut(channel_map[next_channel] as usize);
num_frames =
decode_sce_or_cpe(&self.config, &mut bs, &mut self.tail_bits, out0, None)?;
next_channel += 1;
}
ALAC_ELEM_TAG_CPE => {
if next_channel + 2 > num_channels {
break;
}
let (out0, out1) = self.buf.chan_pair_mut(
channel_map[next_channel + 0] as usize,
channel_map[next_channel + 1] as usize,
);
num_frames = decode_sce_or_cpe(
&self.config,
&mut bs,
&mut self.tail_bits,
out0,
Some(out1),
)?;
next_channel += 2;
}
ALAC_ELEM_TAG_DSE => {
let _tag = bs.read_bits_leq32(4)?;
let align_flag = bs.read_bool()?;
let count = match bs.read_bits_leq32(8)? {
val @ 0..=254 => val,
val @ 255 => val + bs.read_bits_leq32(8)?,
_ => unreachable!(),
};
if align_flag {
bs.realign();
}
bs.ignore_bits(8 * count)?;
}
ALAC_ELEM_TAG_FIL => {
let count = match bs.read_bits_leq32(4)? {
val @ 0..=14 => val,
val @ 15 => val + bs.read_bits_leq32(8)? - 1,
_ => unreachable!(),
};
bs.ignore_bits(8 * count)?;
}
ALAC_ELEM_TAG_CCE | ALAC_ELEM_TAG_PCE => {
return decode_error("alac: unsupported element");
}
ALAC_ELEM_TAG_END => break,
_ => unreachable!(),
}
if next_channel >= num_channels {
break;
}
}
self.buf.truncate(num_frames);
let shift = 32 - self.config.bit_depth;
if shift > 0 {
self.buf.transform(|sample| sample << shift);
}
Ok(())
}
}
impl Decoder for AlacDecoder {
fn try_new(params: &CodecParameters, _: &DecoderOptions) -> Result<Self> {
if params.codec != CODEC_TYPE_ALAC {
return unsupported_error("alac: invalid codec type");
}
let config = if let Some(extra_data) = ¶ms.extra_data {
MagicCookie::try_read(&mut BufReader::new(extra_data))?
}
else {
return unsupported_error("alac: missing extra data");
};
let spec = SignalSpec::new(config.sample_rate, config.channel_layout.channels());
let buf = AudioBuffer::new(u64::from(config.frame_length), spec);
let max_tail_values = min(2, config.num_channels) as usize * config.frame_length as usize;
Ok(AlacDecoder { params: params.clone(), tail_bits: vec![0; max_tail_values], buf, config })
}
fn reset(&mut self) {
}
fn supported_codecs() -> &'static [CodecDescriptor] {
&[support_codec!(CODEC_TYPE_ALAC, "alac", "Apple Lossless Audio Codec")]
}
fn codec_params(&self) -> &CodecParameters {
&self.params
}
fn decode(&mut self, packet: &Packet) -> Result<AudioBufferRef<'_>> {
if let Err(e) = self.decode_inner(packet) {
self.buf.clear();
Err(e)
}
else {
Ok(self.buf.as_audio_buffer_ref())
}
}
fn finalize(&mut self) -> FinalizeResult {
Default::default()
}
fn last_decoded(&self) -> AudioBufferRef<'_> {
self.buf.as_audio_buffer_ref()
}
}
fn decode_sce_or_cpe<B: ReadBitsLtr>(
config: &MagicCookie,
bs: &mut B,
tail_bits: &mut [u16],
out0: &mut [i32],
mut out1: Option<&mut [i32]>,
) -> Result<usize> {
let is_cpe = out1.is_some();
let _elem_instance_tag = bs.read_bits_leq32(4)?;
if bs.read_bits_leq32(12)? != 0 {
return decode_error("alac: unused header bits not 0");
};
let is_partial_frame = bs.read_bool()?;
let shift = 8 * bs.read_bits_leq32(2)? as u8;
let is_uncompressed = bs.read_bool()?;
if shift >= 8 * 3 || shift >= config.bit_depth {
return decode_error("alac: invalid shift value");
}
let num_samples =
if is_partial_frame { bs.read_bits_leq32(32)? } else { config.frame_length } as usize;
if !is_uncompressed {
let pred_bits = config.bit_depth - shift + u8::from(is_cpe);
let mid_side_shift = bs.read_bits_leq32(8)? as u8;
let mid_side_weight = bs.read_bits_leq32_signed(8)?;
if !is_cpe && (mid_side_shift != 0 || mid_side_weight != 0) {
return decode_error("alac: invalid mixing information for mono channel");
}
let mut elem0 = ElementChannel::try_read(bs, config, pred_bits)?;
let mut elem1 =
if is_cpe { Some(ElementChannel::try_read(bs, config, pred_bits)?) } else { None };
if shift > 0 {
let num_tail_values = if is_cpe { 2 } else { 1 } * num_samples;
for val in &mut tail_bits[..num_tail_values] {
*val = bs.read_bits_leq32(u32::from(shift))? as u16;
}
}
elem0.read_residuals(bs, &mut out0[..num_samples])?;
elem0.predict(&mut out0[..num_samples])?;
if let Some(out1) = out1.as_mut() {
let elem1 = elem1.as_mut().unwrap();
elem1.read_residuals(bs, &mut out1[..num_samples])?;
elem1.predict(&mut out1[..num_samples])?;
if mid_side_weight != 0 {
decorrelate_mid_side(out0, out1, mid_side_weight, mid_side_shift);
}
}
if shift > 0 {
let out0_iter = out0[..num_samples].iter_mut();
if let Some(out1) = out1.as_mut() {
let out1_iter = out1[..num_samples].iter_mut();
let tail_iter = tail_bits[..2 * num_samples].chunks_exact(2);
for ((s0, s1), vals) in out0_iter.zip(out1_iter).zip(tail_iter) {
*s0 = (*s0 << shift) | vals[0] as i32;
*s1 = (*s1 << shift) | vals[1] as i32;
}
}
else {
let tail_iter = tail_bits[..num_samples].iter();
for (s0, &val) in out0_iter.zip(tail_iter) {
*s0 = (*s0 << shift) | val as i32;
}
}
}
}
else {
if let Some(out1) = out1.as_mut() {
for (s0, s1) in out0[..num_samples].iter_mut().zip(&mut out1[..num_samples]) {
*s0 = bs.read_bits_leq32_signed(u32::from(config.bit_depth))?;
*s1 = bs.read_bits_leq32_signed(u32::from(config.bit_depth))?;
}
}
else {
for s0 in out0[..num_samples].iter_mut() {
*s0 = bs.read_bits_leq32_signed(u32::from(config.bit_depth))?;
}
}
}
Ok(num_samples)
}
#[inline(always)]
fn lg3a(val: u32) -> u32 {
31 - ((val >> 9) + 3).leading_zeros()
}
#[inline(always)]
fn read_rice_code<B: ReadBitsLtr>(bs: &mut B, k: u32, kb: u32) -> Result<u32> {
let prefix = bs.read_unary_ones_capped(9)?;
let value = if prefix > 8 {
bs.read_bits_leq32(kb)?
}
else if k > 1 {
let value = (prefix << k) - prefix;
let suffix = bs.read_bits_leq32(k - 1)?;
if suffix > 0 {
value + (suffix << 1) + bs.read_bit()? - 1
}
else {
value
}
}
else if k == 1 {
prefix
}
else {
0
};
Ok(value)
}
#[inline(always)]
fn rice_code_to_signed(val: u32) -> i32 {
(val >> 1) as i32 ^ -((val & 0x1) as i32)
}
#[inline(always)]
fn clip_msbs(val: i32, num: u32) -> i32 {
(val << num) >> num
}
fn decorrelate_mid_side(out0: &mut [i32], out1: &mut [i32], weight: i32, shift: u8) {
assert!(out0.len() == out1.len());
for (s0, s1) in out0.iter_mut().zip(out1.iter_mut()) {
*s0 = *s0 + *s1 - ((*s1 * weight) >> shift);
*s1 = *s0 - *s1;
}
}