Browse / github.com/storytold/soundcraft / patch
Audio import: reconstruct AAC rate and channels with gapless trimming
Audio import: reconstruct AAC rate and channels with gapless trimming High-efficiency Advanced Audio Coding (AAC) imports currently expose the core rate/channel layout, causing wrong duration, lost stereo reconstruction, and rejected six-channel material. This draft uses pinned scalar `rusty_aac` 1.1.1 with default features disabled for AAC packets; Symphonia continues demuxing and handling other formats. Probing and decoding agree on the actual reconstructed rate, channel count and duration. It also applies ordinary single-entry `.mp4` edit-list trimming and Apple priming metadata at the reconstructed rate. Bounded sample checks, fallible output reservation, m
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- jackcanon (imported from pull request #814, open)
- Base
e8940766d77601942b31e62570a06c44db1ec68e- Size
- +487 −15 in 18 files
- Review
- pending
- Shared
- 2026-10-28
- Id
fe253f0d9a35323c7bb7f013
How it went
No other operator has reported using it yet.
Diff
raw · ATTRIBUTION.md Cargo.lock crates/audio-io/Cargo.toml crates/audio-io/src/aac.rs crates/audio-io/src/lib.rs crates/audio-io/src/mp4.rs crates/audio-io/src/pcm.rs crates/audio-io/src/symph.rs crates/audio-io/tests/aac_profiles.rs crates/audio-io/tests/fixtures/README.md crates/audio-io/tests/fixtures/aac-51.m4a crates/audio-io/tests/fixtures/he-v1.m4a crates/audio-io/tests/fixtures/he-v2.m4a crates/audio-io/tests/fixtures/lc-stereo.aac crates/audio-io/tests/fixtures/lc-stereo.m4a crates/audio-io/tests/malformed.rs crates/engine/src/io.rs docs/file-format-parity.md
@@ -15,6 +15,11 @@ the SoundCraft contributors) is listed under Files below. ## Audio +`crates/audio-io/tests/fixtures/` contains original synthetic tones generated by Codex for Jack+and encoded with macOS Audio File Convert or FFmpeg. The source recipe is in that folder's+README.md. These test fixtures are licensed MIT OR Apache-2.0, like this project; no third-party+recordings or proprietary sample content are included.+ The demo session's audio (drums, bass, pad) and its MIDI parts are synthesised in code in `crates/engine/src/demo.rs` by the SoundCraft contributors (MIT OR Apache-2.0). No sample files are bundled.@@ -29,6 +34,7 @@ and, at runtime, the operating system's own UI fonts when available (never redis | Path | Author | Source | License | |---|---|---|---|+| `crates/audio-io/tests/fixtures/` | Codex for Jack | Original generated test tones; recipe in folder | MIT OR Apache-2.0 | | `docs/brand/artcraft-logo.svg` | ArtCraft Team | craftrules `assets/brand/` | ArtCraft brand terms (`docs/brand/LICENSE-brand.txt`) | | `docs/brand/artcraft-logo.png` | ArtCraft Team | craftrules `assets/brand/` | ArtCraft brand terms | | `docs/brand/artcraft-logo-white.svg` | ArtCraft Team | craftrules `assets/brand/` | ArtCraft brand terms |@@ -3321,6 +3321,12 @@ dependencies = [ "wait-timeout", ] +[[package]]+name = "rusty_aac"+version = "1.1.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9408128402e729f7f5b71f05870198b9140bcb597e6e09dddc75f1272f7aec48"+ [[package]] name = "same-file" version = "1.0.6"@@ -3604,6 +3610,7 @@ version = "0.10.0" dependencies = [ "log", "proptest",+ "rusty_aac", "serde", "serde_json", "symphonia",@@ -12,6 +12,7 @@ serde.workspace = true thiserror.workspace = true log.workspace = true symphonia.workspace = true+rusty_aac = { version = "=1.1.1", default-features = false } [dev-dependencies] proptest.workspace = truenew file mode 100644@@ -0,0 +1,117 @@+//! AAC packets from Symphonia's demuxer, decoded with SBR/PS and multichannel support.+//! The scalar-only dependency has no native runtime or unsafe acceleration enabled.++use symphonia::core::{codecs::CodecParameters, errors::Error as SymError, formats::FormatReader, units::TimeBase};++use crate::{AudioBuffer, AudioError, AudioInfo, Result, pcm::check_decode_samples};++fn decoder_error(error: rusty_aac::Error) -> AudioError {+ match error {+ rusty_aac::Error::Unsupported(message) => AudioError::Unsupported(format!("AAC: {message}")),+ other => AudioError::Malformed(format!("AAC: {other}")),+ }+}++/// Container trim counts use its time base, which may be the AAC core's rate.+fn trim_frames(trim: u32, time_base: TimeBase, output_rate: u32) -> Result<usize> {+ if time_base.denom == 0 || time_base.numer == 0 {+ return Err(AudioError::Malformed("AAC has an invalid time base".into()));+ }+ let frames = u128::from(trim) * u128::from(time_base.numer) * u128::from(output_rate) / u128::from(time_base.denom);+ usize::try_from(frames).map_err(|_| AudioError::TooLarge("AAC trim exceeds addressable memory".into()))+}++pub(crate) fn run(+ mut reader: Box<dyn FormatReader>,+ params: &CodecParameters,+ track: u32,+ mut info: AudioInfo,+ count_only: bool,+) -> Result<(AudioInfo, AudioBuffer)> {+ let mut decoder = match params.extra_data.as_deref() {+ Some(config) => rusty_aac::AacDecoder::with_config_bytes(config).map_err(decoder_error)?,+ None => {+ let channels = params.channels.map(|c| c.count()).unwrap_or(usize::from(info.channels));+ // ADTS demuxing supplies the standard AAC configuration's channel count.+ let configuration = match channels {+ 1..=6 => channels as u16,+ 8 => 7,+ _ => return Err(AudioError::Unsupported("AAC requires a supported channel configuration".into())),+ };+ rusty_aac::AacDecoder::with_config(rusty_aac::AudioSpecificConfig {+ object_type: 2,+ sample_rate: info.sample_rate,+ channels: configuration,+ })+ }+ };+ let time_base = params.time_base.unwrap_or(TimeBase { numer: 1, denom: info.sample_rate });+ let mut planar: Vec<Vec<f32>> = Vec::new();+ let mut frames = 0u64;+ let mut format = None;+ loop {+ let packet = match reader.next_packet() {+ Ok(packet) => packet,+ Err(SymError::IoError(error)) if error.kind() == std::io::ErrorKind::UnexpectedEof => break,+ Err(error) => return Err(AudioError::Malformed(format!("AAC container: {error}"))),+ };+ if packet.track_id() != track {+ continue;+ }+ let decoded = decoder.decode(packet.buf(), None).map_err(decoder_error)?;+ let channels = usize::from(decoded.channels);+ if decoded.sample_rate == 0 || !(1..=8).contains(&channels) || !decoded.samples.len().is_multiple_of(channels) {+ return Err(AudioError::Malformed("AAC decoder returned an invalid audio layout".into()));+ }+ let current = (decoded.sample_rate, decoded.channels);+ if format.is_some_and(|previous| previous != current) {+ return Err(AudioError::Unsupported("AAC changes sample rate or channel layout within the stream".into()));+ }+ if format.is_none() {+ format = Some(current);+ info.sample_rate = decoded.sample_rate;+ info.channels = decoded.channels;+ if !count_only {+ planar = (0..channels).map(|_| Vec::new()).collect();+ }+ }+ let start = trim_frames(packet.trim_start(), time_base, decoded.sample_rate)?;+ let end_trim = trim_frames(packet.trim_end(), time_base, decoded.sample_rate)?;+ let n = decoded.frames();+ let end = n+ .checked_sub(end_trim)+ .filter(|&end| start <= end)+ .ok_or_else(|| AudioError::Malformed("AAC packet trim exceeds decoded frames".into()))?;+ frames = frames.checked_add((end - start) as u64).ok_or_else(|| AudioError::TooLarge("AAC frame count overflow".into()))?;+ check_decode_samples(frames, decoded.channels, decoded.sample_rate)?;+ if !count_only {+ for dst in &mut planar {+ dst.try_reserve(end - start).map_err(|_| AudioError::TooLarge("not enough memory to decode AAC".into()))?;+ }+ let samples =+ decoded.samples.get(start * channels..end * channels).ok_or_else(|| AudioError::Malformed("AAC trim is out of range".into()))?;+ for frame in samples.chunks_exact(channels) {+ for (dst, &sample) in planar.iter_mut().zip(frame) {+ dst.push(if sample.is_finite() { sample } else { 0.0 });+ }+ }+ }+ }+ if format.is_none() {+ return Err(AudioError::Malformed("AAC stream contains no audio packets".into()));+ }+ info.frames = frames;+ Ok((info.clone(), AudioBuffer { sample_rate: info.sample_rate, channels: planar }))+}++#[cfg(test)]+mod tests {+ use super::*;++ #[test]+ fn trims_follow_the_output_rate_and_reject_invalid_time_bases() {+ assert_eq!(trim_frames(512, TimeBase { numer: 1, denom: 24_000 }, 48_000).unwrap(), 1024);+ assert_eq!(trim_frames(1024, TimeBase { numer: 1, denom: 48_000 }, 48_000).unwrap(), 1024);+ assert!(trim_frames(1, TimeBase { numer: 1, denom: 0 }, 48_000).is_err());+ }+}@@ -14,6 +14,7 @@ //! of any length never has to fit in memory. #![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)] +mod aac; mod aiff; mod buffer; mod caf;@@ -104,3 +104,222 @@ fn sample_sizes(b: &[u8], body: usize, end: usize) -> Result<bool> { } Ok(fits) }++// Edit-list support adapted from MarekSpodBiedry's SoundCraft pull request #713,+// commit 4a6228af98d3533c932a91ee1d667e347af94d8b, under this project's MIT/Apache-2.0 license.+/// The part of a decoded MP4 audio track that the file's edit list keeps, in frames at the+/// track's sample rate. AAC streams start with encoder delay that only the edit list excludes.+#[derive(Debug, Clone, Copy, PartialEq, Eq)]+pub(crate) struct Trim {+ /// Frames to drop from the start of the decoded stream.+ pub skip: u64,+ /// Frames to keep after those, or all that remain.+ pub len: Option<u64>,+}++impl Trim {+ /// Total frames left of a decoded stream of `total` frames.+ pub(crate) fn frames(self, total: u64) -> u64 {+ let rest = total.saturating_sub(self.skip);+ self.len.map_or(rest, |n| n.min(rest))+ }++ /// Cut every channel down to the kept frames.+ pub(crate) fn apply(self, channels: &mut [Vec<f32>]) {+ for ch in channels {+ let skip = usize::try_from(self.skip).unwrap_or(usize::MAX).min(ch.len());+ ch.drain(..skip);+ if let Some(n) = self.len {+ ch.truncate(usize::try_from(n).unwrap_or(usize::MAX));+ }+ }+ }+}++/// Child atoms in `pos..end` as (kind, body start, atom end). Stops at the first header that+/// does not fit.+fn children(b: &[u8], mut pos: usize, end: usize) -> Vec<([u8; 4], usize, usize)> {+ let end = end.min(b.len());+ let mut out = Vec::new();+ while pos < end {+ if out.len() >= 65_536 {+ break; // Metadata lookup must not allocate in proportion to an unbounded atom count.+ }+ let (Some(size), Some(kind)) = (be_u32(b, pos), crate::pcm::tag(b, pos + 4)) else { break };+ let (head, len) = match size {+ 0 => (8, (end - pos) as u64),+ 1 => (16, be_u64(b, pos + 8).unwrap_or(0)),+ n => (8, u64::from(n)),+ };+ let Some(atom_end) = usize::try_from(len).ok().filter(|_| len >= head).and_then(|n| pos.checked_add(n)).filter(|&n| n <= end) else { break };+ out.push((kind, pos + head as usize, atom_end));+ pos = atom_end;+ }+ out+}++/// The timescale of an `mvhd` or `mdhd` atom whose body starts at `body`.+fn timescale(b: &[u8], body: usize) -> Option<u64> {+ let at = match *b.get(body)? {+ 0 => body.checked_add(12)?,+ 1 => body.checked_add(20)?,+ _ => return None,+ };+ be_u32(b, at).filter(|&t| t > 0).map(u64::from)+}++/// `value` units of a clock running at `from` Hz, as frames at `rate` Hz.+fn rescale(value: u64, rate: u64, from: u64) -> Option<u64> {+ u64::try_from(u128::from(value) * u128::from(rate) / u128::from(from)).ok()+}++/// The frames kept by the edit list of the first sound track of the MP4 file `b`, for a track+/// decoded at `rate` Hz. None without a usable edit list: several entries, an empty edit, or a+/// cut that keeps everything.+pub(crate) fn edit_trim(b: &[u8], rate: u32) -> Option<Trim> {+ let rate = u64::from(rate);+ let moov = children(b, 0, b.len()).into_iter().find(|c| &c.0 == b"moov")?;+ let parts = children(b, moov.1, moov.2);+ let mvhd = parts.iter().find(|c| &c.0 == b"mvhd")?;+ let movie_scale = timescale(b.get(..mvhd.2)?, mvhd.1)?;+ for (_, trak, trak_end) in parts.iter().filter(|c| &c.0 == b"trak") {+ let kids = children(b, *trak, *trak_end);+ let mdia = kids.iter().find(|c| &c.0 == b"mdia")?;+ let media = children(b, mdia.1, mdia.2);+ let is_sound =+ media.iter().find(|c| &c.0 == b"hdlr").is_some_and(|h| b.get(..h.2).and_then(|b| crate::pcm::tag(b, h.1 + 8)) == Some(*b"soun"));+ if !is_sound {+ continue;+ }+ let mdhd = media.iter().find(|c| &c.0 == b"mdhd")?;+ let media_scale = timescale(b.get(..mdhd.2)?, mdhd.1)?;+ let edts = kids.iter().find(|c| &c.0 == b"edts")?;+ let elst = children(b, edts.1, edts.2).into_iter().find(|c| &c.0 == b"elst")?;+ let b = b.get(..elst.2)?;+ let body = elst.1;+ let wide = match *b.get(body)? {+ 0 => false,+ 1 => true,+ _ => return None,+ };+ if be_u32(b, body + 4)? != 1 {+ return None;+ }+ let (duration, start) = if wide {+ (be_u64(b, body + 8)?, i64::from_be_bytes(be_u64(b, body + 16)?.to_be_bytes()))+ } else {+ (u64::from(be_u32(b, body + 8)?), i64::from(i32::from_be_bytes(be_u32(b, body + 12)?.to_be_bytes())))+ };+ let media_rate = if wide { body + 24 } else { body + 16 };+ // Reverse, freeze and accelerated edits require timeline rendering, not a trim.+ if be_u32(b, media_rate)? != 0x0001_0000 {+ return None;+ }+ let skip = rescale(u64::try_from(start).ok()?, rate, media_scale)?;+ let len = if duration == 0 { None } else { Some(rescale(duration, rate, movie_scale)?) };+ return (skip > 0 || len.is_some()).then_some(Trim { skip, len });+ }+ None+}++/// Apple's encoder stores priming in iTunSMPB instead of an edit list. Its counts+/// use the media clock, which is the core rate for dual-rate HE-AAC.+pub(crate) fn itunes_trim(b: &[u8], rate: u32) -> Option<Trim> {+ let find = |pos, end, kind: &[u8; 4]| children(b, pos, end).into_iter().find(|c| &c.0 == kind);+ let moov = find(0, b.len(), b"moov")?;+ let mut sound = children(b, moov.1, moov.2).into_iter().filter(|c| &c.0 == b"trak").filter_map(|trak| {+ let mdia = find(trak.1, trak.2, b"mdia")?;+ let hdlr = find(mdia.1, mdia.2, b"hdlr")?;+ (crate::pcm::tag(b.get(..hdlr.2)?, hdlr.1 + 8)? == *b"soun").then_some(mdia)+ });+ let mdia = sound.next()?;+ if sound.next().is_some() {+ return None; // A global tag cannot identify which audio track it describes.+ }+ let mdhd = find(mdia.1, mdia.2, b"mdhd")?;+ let scale = timescale(b.get(..mdhd.2)?, mdhd.1)?;+ let udta = find(moov.1, moov.2, b"udta")?;+ let meta = find(udta.1, udta.2, b"meta")?;+ let ilst = find(meta.1.checked_add(4)?, meta.2, b"ilst")?;+ for item in children(b, ilst.1, ilst.2).into_iter().filter(|c| &c.0 == b"----") {+ let mean = find(item.1, item.2, b"mean")?;+ let name = find(item.1, item.2, b"name")?;+ if b.get(mean.1.checked_add(4)?..mean.2)? != b"com.apple.iTunes" || b.get(name.1.checked_add(4)?..name.2)? != b"iTunSMPB" {+ continue;+ }+ let data = find(item.1, item.2, b"data")?;+ let text = std::str::from_utf8(b.get(data.1.checked_add(8)?..data.2)?).ok()?;+ let mut fields = text.split_ascii_whitespace();+ let reserved = u64::from_str_radix(fields.next()?, 16).ok()?;+ let delay = u64::from_str_radix(fields.next()?, 16).ok()?;+ let _padding = u64::from_str_radix(fields.next()?, 16).ok()?;+ let length = u64::from_str_radix(fields.next()?, 16).ok()?;+ if reserved != 0 || length == 0 {+ return None;+ }+ return Some(Trim { skip: rescale(delay, u64::from(rate), scale)?, len: Some(rescale(length, u64::from(rate), scale)?) });+ }+ None+}++#[cfg(test)]+mod tests {+ use super::*;++ fn atom(kind: &[u8; 4], body: &[u8]) -> Vec<u8> {+ let mut v = ((body.len() + 8) as u32).to_be_bytes().to_vec();+ v.extend_from_slice(kind);+ v.extend_from_slice(body);+ v+ }++ fn header(scale: u32) -> Vec<u8> {+ let mut v = vec![0u8; 12];+ v.extend_from_slice(&scale.to_be_bytes());+ v.extend_from_slice(&[0; 8]);+ v+ }++ fn file(movie_scale: u32, media_scale: u32, entries: &[(u32, i32)]) -> Vec<u8> {+ let mut elst = vec![0, 0, 0, 0];+ elst.extend_from_slice(&(entries.len() as u32).to_be_bytes());+ for &(d, t) in entries {+ elst.extend_from_slice(&d.to_be_bytes());+ elst.extend_from_slice(&t.to_be_bytes());+ elst.extend_from_slice(&[0, 1, 0, 0]);+ }+ let mut hdlr = vec![0u8; 8];+ hdlr.extend_from_slice(b"soun");+ let mdia = [atom(b"hdlr", &hdlr), atom(b"mdhd", &header(media_scale))].concat();+ let trak = [atom(b"mdia", &mdia), atom(b"edts", &atom(b"elst", &elst))].concat();+ let moov = [atom(b"mvhd", &header(movie_scale)), atom(b"trak", &trak)].concat();+ [atom(b"ftyp", b"M4A \0\0\0\0"), atom(b"moov", &moov)].concat()+ }++ #[test]+ fn edit_list_drops_priming_and_padding() {+ let t = edit_trim(&file(48_000, 48_000, &[(48_000, 1024)]), 48_000);+ assert_eq!(t, Some(Trim { skip: 1024, len: Some(48_000) }));+ assert_eq!(t.map(|t| t.frames(49_152)), Some(48_000));+ }++ #[test]+ fn edit_list_scales_movie_and_media_clocks() {+ // A 1000 Hz movie clock (as ffmpeg writes) and a 44.1 kHz media clock.+ let t = edit_trim(&file(1000, 44_100, &[(1000, 2112)]), 44_100);+ assert_eq!(t, Some(Trim { skip: 2112, len: Some(44_100) }));+ }++ #[test]+ fn empty_or_split_edit_lists_are_ignored() {+ assert_eq!(edit_trim(&file(1000, 48_000, &[(500, -1)]), 48_000), None);+ assert_eq!(edit_trim(&file(1000, 48_000, &[(500, 0), (500, 100)]), 48_000), None);+ }++ #[test]+ fn trim_cuts_every_channel() {+ let mut ch = vec![vec![1.0, 2.0, 3.0, 4.0], vec![5.0, 6.0, 7.0, 8.0]];+ Trim { skip: 1, len: Some(2) }.apply(&mut ch);+ assert_eq!(ch, vec![vec![2.0, 3.0], vec![6.0, 7.0]]);+ }+}@@ -7,6 +7,44 @@ use std::io::Write; /// Maximum number of decoded `f32` samples (all channels) we will produce: 4 GiB of output. pub(crate) const MAX_DECODE_SAMPLES: u64 = (4u64 << 30) / 4; +pub(crate) fn check_decode_samples(frames: u64, channels: u16, rate: u32) -> Result<()> {+ if frames.saturating_mul(u64::from(channels)) > MAX_DECODE_SAMPLES {+ return Err(decode_limit_error(frames, channels, rate));+ }+ Ok(())+}++/// Compressed file size is not the decoded allocation. Keep the guard and explain+/// what users can do, rather than suggesting an apparently small file is corrupt.+pub(crate) fn decode_limit_error(frames: u64, channels: u16, rate: u32) -> AudioError {+ let samples = frames.saturating_mul(u64::from(channels));+ let gib = samples as f64 * 4.0 / (1u64 << 30) as f64;+ let minutes = if rate == 0 { 0.0 } else { frames as f64 / f64::from(rate) / 60.0 };+ AudioError::TooLarge(format!(+ "{minutes:.1} minutes at {rate} Hz with {channels} channels requires {gib:.2} GiB of decoded audio; \+ the per-file decode limit is 4 GiB regardless of compressed file size. Split the source into shorter files before importing"+ ))+}++#[cfg(test)]+mod limit_tests {+ use super::*;++ #[test]+ fn large_compressed_import_error_explains_decoded_memory_and_recovery() {+ assert!(check_decode_samples(MAX_DECODE_SAMPLES / 2, 2, 48_000).is_ok());+ assert!(matches!(check_decode_samples(MAX_DECODE_SAMPLES / 2 + 1, 2, 48_000), Err(AudioError::TooLarge(_))));+ assert!(check_decode_samples(u64::MAX, u16::MAX, 48_000).is_err());+ let error = decode_limit_error(MAX_DECODE_SAMPLES / 2 + 1, 2, 48_000);+ assert!(matches!(error, AudioError::TooLarge(_)));+ let text = error.to_string();+ assert!(text.contains("4 GiB"));+ assert!(text.contains("compressed file size"));+ assert!(text.contains("Split the source"));+ assert!(decode_limit_error(u64::MAX, u16::MAX, 0).to_string().contains("decode limit"));+ }+}+ /// Little-endian `u16` at `pos`. pub(crate) fn le_u16(b: &[u8], pos: usize) -> Option<u16> { let s = b.get(pos..pos.checked_add(2)?)?;@@ -16,7 +16,7 @@ use symphonia::core::io::{MediaSourceStream, MediaSourceStreamOptions, ReadBytes use symphonia::core::meta::MetadataOptions; use symphonia::core::probe::Instantiate; -use crate::pcm::{MAX_DECODE_SAMPLES, be_u32};+use crate::pcm::{be_u32, check_decode_samples}; use crate::{AudioBuffer, AudioError, AudioInfo, FileFormat, Result, SampleFormat}; /// The most frames a packet may declare: decoders allocate a packet's frames up front, and ALAC@@ -160,11 +160,10 @@ fn run(bytes: &[u8], detected: FileFormat, count_only: bool) -> Result<(AudioInf } }; let (track_id, mut info) = info_of(reader.as_ref(), detected)?;- if let Some(n) = reader.tracks().iter().find(|t| t.id == track_id).and_then(|t| t.codec_params.n_frames) {- let total = n.saturating_mul(u64::from(info.channels.max(1)));- if !count_only && total > MAX_DECODE_SAMPLES {- return Err(AudioError::TooLarge(format!("{total} samples exceeds the decode limit")));- }+ if let Some(n) = reader.tracks().iter().find(|t| t.id == track_id).and_then(|t| t.codec_params.n_frames)+ && !count_only+ {+ check_decode_samples(n, info.channels.max(1), info.sample_rate)?; } let params = reader .tracks()@@ -176,6 +175,16 @@ fn run(bytes: &[u8], detected: FileFormat, count_only: bool) -> Result<(AudioInf if params.max_frames_per_packet.into_iter().chain(alac.map(u64::from)).any(|n| n > MAX_PACKET_FRAMES) { return Err(AudioError::Malformed("the file declares packets far longer than any codec uses".into())); }+ if params.codec == CODEC_TYPE_AAC {+ let (mut info, mut audio) = crate::aac::run(reader, ¶ms, track_id, info, count_only)?;+ if let Some(trim) = crate::mp4::edit_trim(bytes, info.sample_rate).or_else(|| crate::mp4::itunes_trim(bytes, info.sample_rate)) {+ info.frames = trim.frames(info.frames);+ if !count_only {+ trim.apply(&mut audio.channels);+ }+ }+ return Ok((info, audio));+ } let mut decoder = symphonia::default::get_codecs().make(¶ms, &DecoderOptions::default()).map_err(map_err)?; let mut planar: Vec<Vec<f32>> = Vec::new();@@ -216,16 +225,15 @@ fn run(bytes: &[u8], detected: FileFormat, count_only: bool) -> Result<(AudioInf if ch == 0 { continue; }+ let channels = u16::try_from(ch).map_err(|_| AudioError::Unsupported("too many channels".into()))?; if planar.is_empty() { // The decoded stream is authoritative for the channel count.- info.channels = u16::try_from(ch).map_err(|_| AudioError::Unsupported("too many channels".into()))?;+ info.channels = channels; planar = (0..ch).map(|_| Vec::new()).collect(); } let n = decoded.frames() as u64; frames = frames.saturating_add(n);- if frames.saturating_mul(ch as u64) > MAX_DECODE_SAMPLES {- return Err(AudioError::TooLarge("decoded audio exceeds the 4 GiB limit".into()));- }+ check_decode_samples(frames, channels, info.sample_rate)?; if count_only { continue; }@@ -259,6 +267,11 @@ pub(crate) fn probe(bytes: &[u8], detected: FileFormat) -> Result<AudioInfo> { Opened::Empty(info) => return Ok(info), }; let (_, info) = info_of(reader.as_ref(), detected)?;+ if reader.tracks().iter().any(|t| t.codec_params.codec == CODEC_TYPE_AAC) {+ // AAC extensions may change rate and channels only when packets are decoded.+ // Header-only answers otherwise describe the core, not the audible stream.+ return run(bytes, detected, true).map(|(i, _)| i);+ } if info.frames > 0 && info.channels > 0 { return Ok(info); }new file mode 100644@@ -0,0 +1,43 @@+use soundcraft_audio_io::{decode, probe};++#[test]+fn aac_extensions_preserve_duration_rate_and_channels() {+ for (name, bytes, rate, channels) in [+ ("HE v1", include_bytes!("fixtures/he-v1.m4a").as_slice(), 32_000, 2),+ ("HE v2", include_bytes!("fixtures/he-v2.m4a").as_slice(), 48_000, 2),+ ("5.1", include_bytes!("fixtures/aac-51.m4a").as_slice(), 48_000, 6),+ ("LC stereo", include_bytes!("fixtures/lc-stereo.m4a").as_slice(), 48_000, 2),+ ] {+ let (info, audio) = decode(bytes, None).unwrap_or_else(|err| panic!("{name}: {err}"));+ assert_eq!(info.channels, channels, "{name}");+ assert_eq!(info.sample_rate, rate, "{name}");+ assert_eq!(audio.sample_rate, rate, "{name}");+ assert_eq!(audio.frames(), rate as usize, "{name}: one second, including gapless trimming");+ assert_eq!(info.frames, audio.frames() as u64);+ assert_eq!(probe(bytes, None).unwrap(), info, "{name}: probe and decode disagree");+ assert!(audio.channels.iter().flatten().all(|s| s.is_finite()));+ }+}++#[test]+fn adts_without_a_container_config_still_decodes() {+ let (info, audio) = decode(include_bytes!("fixtures/lc-stereo.aac"), None).unwrap();+ assert_eq!((info.sample_rate, info.channels), (48_000, 2));+ assert!(audio.frames() >= 48_000);+ assert_eq!(probe(include_bytes!("fixtures/lc-stereo.aac"), None).unwrap(), info);+}++#[test]+fn truncated_and_mutated_aac_profiles_never_escape_as_panics() {+ for bytes in [include_bytes!("fixtures/he-v2.m4a").as_slice(), include_bytes!("fixtures/aac-51.m4a").as_slice()] {+ for end in (0..bytes.len()).step_by(37) {+ let _ = probe(&bytes[..end], None);+ let _ = decode(&bytes[..end], None);+ }+ for at in (0..bytes.len()).step_by(29) {+ let mut damaged = bytes.to_vec();+ damaged[at] ^= 0xff;+ let _ = decode(&damaged, None);+ }+ }+}new file mode 100644@@ -0,0 +1,18 @@+# Original Advanced Audio Coding (AAC) test fixtures++Generated by Codex for Jack, October 19, 2026; MIT OR Apache-2.0.+No recorded audio or third-party samples. Input: one second at 48000 hertz, 16-bit signed+samples, amplitude 2000. Channel c is round(2000 * sin(2*pi*(220+c*110)*i/48000)).+Stereo uses two channels; surround uses six in waveform-file channel order.++he-v1.m4a: afconvert -f m4af -d aach -b 32000 stereo.wav he-v1.m4a+he-v2.m4a: afconvert -f m4af -d aacp -b 32000 stereo.wav he-v2.m4a+aac-51.m4a: afconvert -f m4af -d 'aac ' -b 256000 surround.wav aac-51.m4a+lc-stereo.m4a: ffmpeg -i stereo.wav -c:a aac -b:a 128k -f ipod lc-stereo.m4a+lc-stereo.aac: ffmpeg -i stereo.wav -c:a aac -b:a 128k -f adts lc-stereo.aac++Apple's encoder chooses 32000-hertz output for high-efficiency version 1 at this bitrate; version 2 is 48000.+FFmpeg 9.0.2 independently decodes the three Apple files and the LC container to exactly+one second. The ADTS elementary stream has no container gapless metadata; it has encoder+priming and padding and is therefore intentionally longer. Binary hashes are in the review+manifest. Regeneration requires the encoders; normal regression tests use these fixed files.new file mode 100644GIT binary patchliteral 20802zcmeIZc|4Tw_dkBm7#c!jNh8u&L&%<F8AA3YLPAK{muy9ru|^?;>?FG^S&L#qh%7~hztR+dZCHpep>(=Y_`Fua$-{be!_pk5c@jkBOy60YJ&ULPHo%1~Bh9HRjrkAg~j-(O}z0tELi?vmmTo^CD>graeAbMpbaon3tFZQ<kJchloxhM-0Q1hqjB;-JBY{u227Kj{DXzjQ<}8|34p)5QNO|^00OSN6fvP4xV}Fzn=*|4JPp1|BViI{vXfz_soA!!~eT+&?9ABzY#pq@CeFq7|L1r8J)g_o*4g9VOFiAZUH{$ww?{0xIJn*fpD>;-fA93q5gyyW``K+hzZotQ3g1;lJw}&(C?>3^!)62#gZ2Ne6c^*jj?|$ee7y<a(!Svt13khN19kAR1N!;+Xz^@KMl2m}Hb=ux0&#xp}$aE<g2h~fuC3HBfvDycw+0D^^%c-nX!JVrxI8hpfhdU+k(z0c^uh5d-%C9mEg5&2@MK5PTVY4BYgfr}(Fb_YH&d{6PONf$JeAaETN+)d27jz~FiWz8{kubX~FS5&>sSP0WkO~2qVA}fDHl50_Fj12Ur2H6<{^MX8~&ghVOY9a6Die!0`28zY!LE*qX3%#z6%&W*BmgAI>HSw0q`xr@VW3k;rqjVDB!Drfqo-&0q+A|fWUn4^tukNzJ0S3TVWA6cL69DJHni<+>tzl4-!3-}dibROp(8-AJgnW_;Zgl>YIAV*^a3AW2?GK>zyUPvh15LW_<{|>0eM7{-$lLV>JQ~cd)-E^TOW{3+I{M0BGtAcd;AybbA)M$x^mju>zQuLoa|F!Y=xU#a$zehy>Z#N+5@W-1THx9lR{2l&7|B=9dB=8>z{6_-+k-&c>@E-~MzM*{zmz<(t0|CR)lG+jVg0rf)&YUnrxo*PGjx2HW0K~vBsvv9wPjQsAq2F=7#mzPy<zyGlpHWKeQiME3U&W1lhYV<*ExPIk<1Ge6p~*w;!3`r)<z=bQZOt}%Kqd$%EBYkbi|zQOv7t|B!bG$HSEsMTD<=MCm(QuO?;Qf%EYkjYMi6Bg~?#c)-c%xQSaWw`E37E$5z-zHxTyTvUAn5HjlV_s&n_e%`f4(`gK0?PY<7w*SqiiqXoo`)P{9Yx;#QMpT*DWYMcEjz>WoUWA>~`eXe674OEi*y2g!1@sfaRd?dr+)puKb4&g|EqPwvhWgZC9;+xH`wr{)F|z6FTLm7jG4FA>N+$j6Nh_V;Mos<#s`n(RdzeCue6IQFtO@T!yE+4Dq!N3v1AzHaB-BzUOcC-p+TM;3Put9Qm%VX8DPlLlO3D8(u3;zx2BR=?(O>vUJ%G`rOxwN=%{D7z!x}Xzo7!)X@h&rauHvede*x)Fa6f11&7LUAZZ&=axAu4PK6GJM=B{J0sIFl!u18^I@(B6$z_P#<k=0X{ga4(pzlQX8(qGEX|>C5xlXD*IayZM(sMhWug-sjJaYN;Np>D8u?zPM)9zo%1Gp?lhUr(7v@rGn9fS?SmwuAi&di?+J?I^Zu{m4a&GUS0b-JS+8V?Ojhfk$2TeNz1yywJnKFlI;BAk;ANIeiOZ^oJl^HhA$V5)~$D?!y-KJXcIVn#(#{+6)(Kx#G2}8DOzCsJ7$mg;#kkujl*FIe%+3KxgU@;L?aj0gMaeshEnvygM5KD!#)b8cnUvUTx?>78Q&zoO-`6^RmbApNNc(WudaOF=FxA-Kn3I>`|e+YfQycmsnq$KRs~FTi@6^&K3zlDawQFzRAe%FvyuBKmPt{ubvo(;iFA?ju|WPZ2d0${q1B)pBqIF1qbFAAtv$bBNI0c^K}1NJzdrrY)w6I;CfqSc&cyIX8Fw;GW+nN5d*)Kmz98MC4?!_I7ux8=PU9fgo{HSVJT<jpKzuYbDv?G-s+?_SSMC(;>?<_`K3e(!=g+4S$+yGABY<LV6XS4QPs%q=Sl2g;8L&OjU(z2*ImSkS5?Ov}}=w8Xk45<#W_daXuGxZ<&_+M__h4E42zIA<Ftt?7-w~y+zQ><UmBQzN1D~j7k^tmrmAzSY{C!3=h~YT6ewH>^OY^5{!6m+J$0jjuKApGayJr&v8s?g>+n-Sz3*^KUf)5BZPc)K>6N$##U?gTLTnozk3X*-=%!^vF4DXWFt`I+rDwNb{<Z9%l9W*<bzWIUMe9Vba-6!Cn=L?MX`%t%bm6r@NdcSFzcUZNJeLE95)ND?=hwcwoOfOb=_L)E=%zL_AImEw{3@)koH<H@rx=Gv96Xb@<*#eO`0(s&1jG?lZZrw$<9h8sDmQ#M+dw`c{hMzJ@VAADO)_d@?p8#TU$ZfPM5xC1z&h3`%x;-i9z;=Yu+IW3JP&5n1pEQ2=Y|)VCxW8z8#gtC(+>kbEAq`5simd$rEKz_VOrl~x7j2Gf~DwC1rIq+6b+&YNSrklBF9Y>b;;fBzrwl?6h{Hxd1I3L%<NMf17PkWU$`^;Q#*mF9!-SHzNrsS+kieDWmcFxDzOyeU?l$-Jz%x2xydiTmL{FJ;0qpp%^nGFJm%s~;t`1wT@8Yh?6@k;DiPL#xsKY3SHsgw2Aj6S2*zh9E!bqDE7C(NoK5e4L;Xd)sqbW$xAanf>XlKpb*L4MU8z<4&*5(^1W-q`28i`nl!|zy<j@bz)gcbv`QxLN@XwxAI>_ryVFPh^HL{5lrOo^>E&rg7ES}sY~mgkJ0^L&jhYLgzf>T0s4lZr3ttyf`ClFLd>B72nYr<L*>lSLeFPqE<`s7x7L&FJiEhq|H?}gytWduL7zko|8Qy9%}9#SXK<#^z#My2qzQ+fhI(Z6bHq`t3*Jtp0bhCK5lrDNVOcxbOHR%}U)^zpF&kxATFHp2nCtE&(eujjtnUes_!Fr{`huSrsoIh<K9A}jzpdi`VP}03*+>T52|Pbztj@rnz3i86%iFby<^?V67*1xbUaU!8^S3u)C;PSt#Lp>MENk)osaNGpEH7cbP~0Pbz#ny=m@~9vgLIwi1Hx##Y)6R$!`qWal^*#nhtrpdfv~;C86r|Y}-%PWLd-O<0a)8(DzN<k|20VRPUQtA0Ke7q>L@?qW8=Dzpj&E;Fel=F)P4Ni{lqgO3Ng*TS;UmW^kt3rVmzrET?Ir(JbdnnG|f3psG{qg5y{!C9|$8@{ed`K5gnqO0UEQe>_UZj>!9fFF3!&PhjUzCR?S3DC=q`Tg8P&Sy7Q1LfLw3P>brf?T>}(GxMM*Ay`EYk;%(7cx4<FC;I%pqT)Uoz=fQyCj%S+K?>;N<+c>V^cBfWw!KOOZP$*G8g+`OQZf)0%oc^iX3)Lkwc#83=C-*y+zIn*Jbj&NHAoNYTB8*r~Enjd$vgS@dKdKJTqL1KbYR<?bXuRY28#`N~)d9Bz1$)b-hzH8n3?{X}6LLru-(#dFG*np%+2owvlR#mvEz+S+HZnA3_M5;o6^=Xb*JB9CB#qk98(zR>=DV9zc8y`3zpx7m>>N%VGRf)~_4s$D0^+hzA<9g2gBw!USh--t{hRe$bS5Q7rMLzL4*u<Jpb#vTc5gayN);dEPV`o^d~!S58SHQfb*<Nae=bt443Q}Wtg!#S~)Z{7?|k8zDp<-RYkLn{HwHEug$a?-^N~@zvif)BBliAG25h`OdCzS$P?dE5Xq2_Y6BWD?S}AisztB%Y?4!Fi-e<Ca6)%CLqsE5XQiUBGf^}A|R0)*nL6Drn91lU%E+YCopeL&;(YUjTxz4ipZRkD3>?ursuzHH9SndTibI)))C3$)6jEhF3$-@I3erJcI;(^`#&M@_F)>ETZ&xzJ};wz1lmWj9~>8YWfPejS&(wWnjR5%1B#2wLWnc-+pl1O^-@#_Z1^}cIrx}O%p;xFz3Lkc}=SPyu!wdE<wEsoU*jq26RNH%s;))17m~bix0#it&^N?!T!_7XjaT-J;aW+RHz_I|=^ziv{6<?AOEmao>4Y*Z?==NMC^T}_gCqim45A&#@FTR|J2CaVJwR630I$7wbwz-vHw(R4}u3_Fa?C@9Q49Y5o#vtjX@Miacy4uk>HV;M9*^**lv}#va)HH;e+@f*sFZzoDxq@(VlD$SdWR6=8kQlW(sb@1vmHgHIl!HTG{26NcI(2A4zqLEHkThtdKE6`rx3rz7AytsJwzmq!Sls_1qaU;LL1JmuUvM0+Qe_D;8`mzg(*YlWBsQ(*gOBi%%B&mB)&;=zmlR!b=4Sj=)K9H~K``JsY3ONB0)wYS-*Si>8HQ^Q>ImAe&u=`wtw%OIl@;igOgu{&zjyQZ%E&S@z!gT%C^y8n~Ln*+DV41XDhQCkEyNUggu6~C-PNFd^475;+04$cxkY2hczo())2iYLwFT?v*p5$f!^rs1pCx_|z8ojW6qoqE2oyq@#njiB!nt(K^1TeY5uo^)yFzk!sS<kxB|7iQ{d@7=p9ec30<T7szA+;_*#O(aOrFTNl0|@DM#8Cg(U639qEVR(1xSz56+3|>?$<Zeyq=%cz)e<tht^59zlF0`tcLBD=_O!=V4N`#D0mzPB8-F;VF8Qf!4fKzhRXNPVy&csaLUZ=&|%=R+{LkCDKVk!`+-3_Tb3alA;vs{YQ-j}2BEg5Xu9Iy;CqfPzI%UDlH_9rstfZ4)MPjkHc<>_$y#yuPvyhvjk^HyUcYkdL$!<GdwPF-J_r7N=W@-MSzgy`9&$!4F1x$?Asnz$&~EQ_cFIs$<KST??;&ZA7h5OU<CV&>H5zTONoY^j-#b8{P%z{c<{0&Dwj)j{i8FU#sP7zeOYwqC}fYMINEx3JJs6rA_vYHj#ImO$gsmmz?W&jr}5RzMW{UUbZBe_YaR2tp1+AmX4QW+I<_R&k;3?<_c_F_%?U};ZBmwWyd|y4Ab6OC+zYrczniPz|S#t}dHnaV6^+wXHMzvkeoWUoI%}1YIb9xlD(>D=x!Q$$1A^Yc1{0X4tCTi%0z#P-Iv9Fh1zrILfQ#gh<uZFP4mqKvGmEoW-aT~>u6AwEceHb<G68O%2FrWTGhmWR4<zW0$;6A{ry|$4b5))qHtU<~$f9hY_LQEiJ^i>ik7TN0IJ6R$Me_Ug{=AlH$F+?L9wvz8g$}zvMv|ZS-z9(3}P&YD7dH&HHTQzUAy1g)j^p>EvoURIpFNaDG@bh4E-T;&}O7?z6g%)Vh{_lx%j)$<(-zl;Dn=Qkoka|-qp6b%defb??O%2TUVClQ1&oC2l^e-dZan@rz$wws(KGKy12gd{Fhq3r#Cc3ogi9R|9if6E=h*v^lt}dDH?!7i4$85PlPtV&Ju(Ea|zmGhkVya!}b23GxFX3hG3dxb?&93s#nf<?7E+Qye*Pw?3vOdJ&#aDCqW-n`|vy1-}}zp=Lx3|JnSA&fB1lAtky+TwMIT+v-le(|E-{%98GIpfaBu=krHK=6rl=OT`tuZTR2Gzhz_9T_JdSSn?$@Vahx^O_Yr7)ci8NHd6r`&W4^D@x4+@@f=(=r@XWB-{z4)!8N|+DzKvDEmX6kIB3@qH}ll8L$WMPZ(T`QuJ%>ccnWzm(kRdGwr|5|7JCrjB>1-bcSx?GZPz@Y9Gq0nWimpsrtpzD95|tI%`ElR0O%h6=OpA0;G3HAW{aqAjqKPdUAxIl54`2JY=_zEKN3zE;K)uCy{i#Kx;J7eb;nNU|mn~tmN)kSNO$Di1G_|2q%kH0qYqG7m~T}yFvclzn2wYaYvovyKH;Xxx-D6UfX9L>kXXcsRU+84y+_j8*N!j3GIdYH8#L=ZEc29aqV}Wgzauy5bb8sZ(wUy=SYtnwV6URjgOEip4+e{mMG71aJpr)qQDp8ht*H$K_&wDzGljaDdz2rQINBF%l8BYS7a?Q0^CX6k99V`45>^(i4>HpOxOx?|R@@oWYSKe8CWGJqp~#fN4Ez>D}JjUd<ITvW`W6cSp|qn>t=7Nv3tiVn=FSAq!>E90GK5hunJQ13?MRqfBMFdwX4$zWUhEZwc06h_&U<j;eo1!{-;9C!OKO#bi$Oz4h84L-evY`!$vBJUtQCrha`xK$2ehdz(LxmRRj&dk<b!rSgM*DA2Axc4uTdL2tn%u{-N%n-I%XcvQO)epz32`hjM-T8Kzv6bz21)`%13~I7%oO+uJXgA`OFaS$TT6Tj6)%NckflPyyjkP?%a#|kSm>K2^}6EJM~}SczLRxaw-3M(B%*bw`*V+YOW+>$+U%4f5pZ;w56C=J%jiY541au5Vq)a#nO|r@4Hql>rzBXwF8j9v3+_WqvPH&NQyldbtK>Tgk1p<p6WXgbHG=MYWeDX5FS@_Y}kMzGq7hP>Qbz>)Tzsz0&b|&Y3E?AVnfg^-}B|F)3B;)8`)jwcFQxWPD|p-)6!zeC7R>HzOnObzK$tz)ssY3HB+MbMUOlL1~i$#%|ipiEG6n`Mft^`h1NxGBG$=+DreS1{RjI>yKZLeAq)#3z+UUBa(Pr13vt`|f57Rt2guHMVNrBMkS9<ddpNNabeNwD{s7JngkH8acN_w#~F2UX*zc(FF+mCna{m2anj5`~55A+5tisjSmze{FstA~;|zR8OSmq&U0lT~RKw{qvpGH`onvz*Bv<?^C(6^p!le;dK7cK26NHJ;ThW*XOAk6rf6VeWY`QHT;5~iB&0^(kH;J5lt3aWzcnlou5sAQBwqC&(RpP^#XICd5?r*P8)ErR~yk7G5O!OVi8z>OY?OS!`CqABOiq@)oz1q_z^Ey$YK8h;EWpMut;VcXhRBWKm#{zHV8T-tZt3)!8-RYPR-<W@mY(x-T4a-r=Nzb#O`u&`~)>SV!BwS!0=%k(iL<v!vO|)%_!r`qou5l4y3MgJYIMk<gXX`o$?8zFS6rzD2#KqZf*I$DB;h2(66G7@QYJHa2@aGK}LpDwBO$K3+$WOA!k5`>FZT2a_Mnj>EB#^z|Klrc4i+b@X+b!cgRb(Z@-au?faGd$aTre2E2GWqOC<U9X=gUrd9L|lT%yr?lx8B)zg4wifwc4}Hv&^Mn6xR8X_q9^FW;}Ub+LP3y$^tzG0f;2#UkGtb&N95hw7@b;Ke=l{zcKTUnMgOWq<{Q1%3t<yx#%`fz&*Uoxf>#2VJi0~rv|rQS@D%-}#c(2wkGi7c*T#?ezt)ZqkBE&@hwp)dPcuv0x@&I1v1KoFa$-egYM_Y*IK-XXkyF5fVju9vMuFkt{&l^M7z@o3i$|KScyd}l(?`3!bg*J0u;gYGb3)G&c(v$K2mf_4M^UVNiUr5X6bFm_8T$58BezSmD{sdpfB8Lgh53KDn=f6<206@rNTYgyZddL~CcEvlgzFu#B9)@yDU~D9$Z5?OCk(z49yP2pA`>A^6esn5RB%_yVF&R-On1j543u(Zqj8Pv{Y7BR>Ow$+NA=KaVD=~lSZGTz<6k9vEznQPTb`p-?GM&vo&-*`zCLt>OrC<*3{(V@+xEsJIY4U=^0r`%jQZBDC3T<rzMzW!JSDxlC-lSs#*D?=})y{`k6{DSPuyGvz`vEeFfwe21+Als+80J?8$(39g_}JjjzhfrlUQ2D6CbI|yr_!8{W)O>uf4<2^$KY0*|tmkwGYxE%yoNbok>5#|^k#D##64OlqzfqGl}&R4~>68mv?sKu{3F@&m#{CIoc#nZN9_4$W`u!x6eN<A(i-(j3FQ9WKtMm<tTzlwE(FAjV7!zzAX=DVv>q<l0`@%4>pXwRb2o)+oJ1X8?FlR|nrz$ZeeO(~}MRIz<TzzWUSFZ6W>yn1{oCol7XFRXFo<BG$$ew05xK}-sMsi4$JPPtk2<iLPumi`KJh8b>?#~zpyBHgGO2ST-^<eKsHg^spRueMvC0cK-?6>AzxK{v!5&QrrU9$5DXfoQh2YgV=xfmWz&u)nQXZ7{NnH0(?ITUJChl+^AL6-~pyvl;_qZlc#Jsb^cy*U4U|BSY3S2SlZdy>>zz-x-6^dR2ow<{R;;w+}!V@Q>FgFX|ow3l{qzc(MNxBC0dAKl#`vNZvb8M~GHRsSj1~zQ7SUanWy+wk$?9K_MDq|u=ej?{C)Os6r1wf@_HX^?QU{1Q*lx?bgk|9RqO{bbcqM^z-fr+U=Q#FAi$^^-@roeM*eAeD%6{QPNsN((lp#E*2H+nze<W0EdY)iKOa0uTqK&kSzI1VQAHxRlb83@21Z9Ws*^uV7>G}>0*I8gXIQa@XW<yGXji`<1d6;Xj}JAJQqJ_~+cz6#Vf#xBUU@kG4de-`99@Y0%mod}$5|@8iA@Ba%ICn#x{z#t2=M;g%wRC<Ov|$F6W9zjTS@Lk%8ajC4XeEJrjQ~PYveWhmT!hM@Bze-d$hqlkbIQeHViiZr8qA9fFuNxw>q*z#L(6%e)|#^mxd}9E0NIxbEh@uCO0-dIyDW2!nRPp!dq&<LTaEPZSGBJP|8xw!=lKRz5GV(X9;F>qPMcLQj#J)q{m;qn?u|+!3<n8(&ua5rt>c-A;`GG3-?@ugr`Xyd91M_jz6tfb>6auay)pMvHC#kNq+!yq@DQJC@bZHntReFr=YRpSVhnBQj7qoJ4aKRgaRx2WLzB-GwTo7VX=w~zec_l+X1jh!tR3jAa=lD;uL_s254#5n)P(`r&FJ|JBS?<S35sctBFzq@%5Lf6RvJRyw^{813xrw*2V?AeO&vevuR*H2|8$T1||@19=`-dyX-=AG(syq<^+(z|IWFfJ+_IkvVq}RsEh~2sYCz*CWlr9tABM5Rje;2m)G=nLe^K~NA7#K-iSjVkz0NDzadli$B$Qt$#au`wgO|<@ksA_qO|h+cW7=epfbEGHVV&&=)Q^29S}t}70xEYv;(Y4yzRu(z7t}{tzxoKz-0KeWnk;wtv;5Rq-Z%>?wZTK`k{&{%#$O)HbcK6o#!?(1YqpwtLzUuBaV0HD%;H}NYl_@f1ORYq%>3PCDd!cZ9I%Jz41ee4dIOhnMfT>CITj~B}A68_Lazn{&VQ0+nbu)PHuGh^|*)9vS<`U5o_FP1cL)pEF~FFLOqdx}wG2uqQbTjH|Gx+WQZGz(Cn$Jg_oHDJDp6a;_8B4cv$<1#8Kn+PVt!EdD;mQmdjE~`mo6085m(btjcdy+C1H;zklk!j{)8YF#9bdNqLktUV+elx2_{BAv;Occy^OAEOpmB4R(CeS>R2`_EXFpclg4e3zwk2ixeY|JR38lC5py1i%_@TssFTur7Lo$sg^+aZtLkTJ=+~Fo1OwYoy%b~eQ6^VbpzG_b0-zgl|HDKX_b?!$uyuC^JK-0w}cr5={dVZ_{fS=#|;U7vV4&5f7KLJ5p?Hb+Cjz)SPbG^WR<H4hmLmo1jQntf?Q;YZI{==FsM)5f8Pjr1M*wABv;KUVt3gz7p|uPV!Mxz2mVbPHiwFn^4yvf>G;lMI+ou2x^;TODKjX(aNTy9mI5M*UhXfvaF5vCIr8nsH;ev4zr8=f~8tNx^?3`tnZ!BzFTlXc<I~7PIT}p%SVf-?%X<U|8lB1^QqCT}BExYes5#!1Gz6zNy!xuKrY+fdlOdVFnjE$_bi2v-6ppi@X?<x62nGK@(A?awk)&NH@0F@}xJ&dk5tzUJIPmCc@D&Q%<{rTB|qHYf956_iqDNAEvWHRb|AgFCM_p!2v&q_{Q0mh!11AJ6nEXz^x=a~6G@)|96S~Kw)guMsdQfAtKA5yfcTiZ<L85~3}7_=X+1r1yGEDMA{d`w409wkz12R*4YwzWFpyJ~EU4-^sSNu1PleE`8=!12&AB*Q)4Dsz#T-umGqeF-X4v!P!=<zG(zMG(wj9&4V)ssqR-%!(7uy1FVee=SzTmzVwH7A4R`!il^FHMJtuN8cPXEHX2*G|JL^zdd}ah>Qi4ADeb7sxLe%HDp1i%Rc@F6d5Fb}&z<K+bX5o^4nnm7L|g^|OEp=an^uzsz6Uw^2)wkQAG#kfHq%nBEpk`u4?9-~Qt|pkxA@<*^K6%n&H%oeWJm6ME#qTXs5EIiLzX6$R+88?4E;PW+8S*eaO<q3eV`CDQ>S7#(8zrImzqO7bEmZWLKTWU>RQ`&0K39O_QzcqFAAe;AY8ovqO_?~e9b;p>N!u-B2YV$sjoWw%HMJ#TrIT}rQh{XS?2Tibuy&+p&AzZ|NyYtd`s!+>}j52G3%^B2Fu^H%}T}=zB<(3RbIhpP#i*wk>c|tGYX#kY1oCw>!`az?4thU3l#m^hSl<EB8*&kqj1qcHznBp1JI3`>ffv@y=R_3=^WIqr&<v)OfU9}P4X>OzZWT7K_4xP~xA^-%`!YaYKPDuWTq@Rh$}4Q7kz?hcL7}2PQl&{%{^wW`F{~d71~D}(z)G6m2H8E!XAib;PrrH%Z#=#RGj$akZC3G3(`#z;OK$q^h%G^DO+Z!$6)Wzzo_bh=>z&Db*AT+wr3V>%|loT96&Xb7Q2lnO#|{fMEcJOGvNt_^I@t?dQAR&NO<5DtW?MrjfFzaP&r#%ywhr2RMwl7&|%r_Gb6Iv*k)q^0k(7hfmt8|790>U;C|Fk#ZN1wla~-oD_<NzlbZqAy$UB|WE{E(E$@xBub(wNr_s%Ll$k2Gt$T{~Cq%_VORJ8B5oSzW!V^v|l`uTJzHU}h1754m)()0CL*yX&1l0mBhR6BDsP-gQ*!ptzGbOWvEGq*%DqvEztBDA7+Hfp7fz#q+uz3BYm9-<Aq*u*4@mP|sry;Zb2gfmqM8l-jeXnuqSLsI5tA;v-28zDZVRKLj3izJIv&AB*38wzzZZ(*fKuv&lL^cZ@#`9xOeU2`D7Q05;o53@hNuJ{d18LKy9m67M5FCz#VQ`sG1@0Muy{BWq(3yGPWk#V3&Cs`5tnSj$q>Oyow>80^mJq1Z1+qWo;7`Nri1qCz{qu`I0$!;fK+G{|KJG@QlBQ4wsuRe2io8TVWXGICw29LkBl{OpudUq<)Wx^VNMoiVzl>bZ)Suky7xpsNxpZax_@X)gIuSs9~nVr`yB0ipU2|64}`4fRvfzTl${U8P+gkW%Czv}C!}rPVFFRg&eHOywPdwZGQ5P0c`oP?Eh-OBX(Q_>Siu$F>{@{{VqFpQ!;A^@)>{z*UaJcMXIT)nx$5HWgI=<5j>UxssH+#L&X$4AYO^;qRLdBtEBq6{H^fvcAtZ^RFM!{zy+#as$*yMZ^~4SVqx?(hM<d=^$Hv4uj;I6D)KAR!T_U)jqBnDY_D<PiF6sa!0v`Vtzp%7z1W)&v4^`%F1J8KmY7=#+cDwOfkwML0DGdwfPS&pY&BZG%WU0wUlDb&}lv?Pb%zYHF*<TUfcR-JPL_lh-WW1p06M(lhEkT4pXfU8*C^qxQ~S%5hLbCF$?_X%9d`kXSkfzqvBSH#mXu@;w{!P9t&ZWqeqxQ{t-`mB#1m!hW>&<E7P6s=;OAywNl|kWHT>l#WEWUzi;fuUMg)G+teEG?7}9z^J#!g=5mj*e?e@q&{Ts2phm@@Ea8XN8z{o{U>5$~;&!ZQBzTkC<NRb~i0S8;7%fc&A9$l!F>$^6%Zm)SIXL8--quOOzokBj$<K0rW;xcNr&MYn@BzZcr3<V37|;AI3KPPP?W-ScYQmMChGkR1E%nOca3K+0Qys6>PU2eZPpSIt*GW2d9-#z$guE_@Aw(%*vKs-7yQmhoR?`jW3WCWqyih{ePEF5^iT5$2I)N}D<1#+i%v(RsMyYaz-r{Y@VcL&6r!28kAfjk%>HR2C{WLxOi70WT|Eqg?D`~}C;l=c|FFkl54R*%MeD-|5zo-%%^XOI%MH;8eMgDL$mt-HC%iyGJtPr<Xuj_G-)HPwXt&di6|dCP%ZQTkz~+pN4}zm<F+CHFpo(yYDq8BbMDj#-V-`v>=hY6+VDaK0Zu7KAwD;t378WyAVvd^!;IoC-4GAzt4tl>rl{x|c&)F!X~U2I7p2JF$!4B&$ZnZB&Ob?w{5C8L5mZzxAVi#aeMcgh<u!01zT8mW`k(-AH1#wgu;&G~7AEa>aPv^x08P~|bNn^B<(2o48t;S}FZg&Y!C$L<EoEzo7zCdKHkDO1IzqMomoblk|nAphHP-8pmiXBj1FC6Yz8DmhjzI>n6(Lh4v-qDhpN<=*?nzqu;`uL84Fe07FmKKaGuKR;<5ECS6k|NKrW9g}o-7423ZI`uhH#Yc!;ExHZIXc?B8vzKJB|yn6W%$Bf&t!g?<>6ZFy%p#%aY~c$iOfJlx|%G4DFhBBN?m^t*$sU!d8B=Xl?3z`9YG7-+W%Nemt+EvhjzrDx>}=bs&09@+_IsUWEYw!`Lv|+sy%spEu{rytPg|7N~5ezl-H9SV*DA=P;j)U+=f%_)icu1=OYDM@a)te#$_k|h>Lp+$7N<0(=M@?LK@WeSOf|$zhGyOL+t@4pM%sBeNpRK|9Y#G&JiDvxW_3F<=H1n?#}P8l!-v-QCwkI_t8aXm5<*}Yz4(Ab2(VPT;>mv?@k8NB#b6_`WWDZh=83Rk-9i>V+BUa#eR!f&<$mRK>+4GuWv&$w5zHJ^)JjA{le`f3YFv!6fRl$FfY<jK`^=M^cIpILbqmhq<0^I>4R78HjGKLq0i`waJNzkk8eFjRUjo_P4hoiRunLliH^&XnubF^HK&zpG2PtISfp6Busx|7EVnFJuI`bW9LUQzTWxRR!wY>=M2B2;II*vOkyU<EHYX%Ew*{sS?ffiXyDJ59aeunuNC9Z{?$M06H(bFgzps<10JTN<}x0Yl!^lH(f5!EH!d6IVHHcxDDAG__`xO=wlffRut{dU}H4~FfoR-fF)z9U~P67J?u~gnV&f{uh9j!TRS%lBb(IW0<UWQzA@v)0uxnJGc^5HK>9#Yw)W-NI}WwzGvEKZy}$8jHEQ|U`mD@b?3gy|tH{JN=4NhO{`b1Sol-g<<)?Lyag8NFw|TB~#cj!Lz>QTwylIe&>5?^BKrArA(%&A&5U@43z{h3`2?ejjlJux(0?BcSTNI!v!2_s~0sv{sKzIJN~#;O@~xng@&&eWR<{yYnW6E^Il%(r$l3?z9*>*Gg8(i_O(LJQU`%x&Q*AZcSf-zcOk~r#KYPuDpw-kEA#6Vlht%zOq=cU<{+cPHP<Kd%LDW`{u~`Va9@v0*?*Eu)R26nzA<d+IjlU|FgEx^81+uh|XwU{ZqB@7DZq0vy{Bex!Ze(ZGc5HhWL%&|?AP+%lW-sa+zo?EaFP&pJfp)#M51+)6w-vlTAUA^4o%Ew8GQ!=P6ZWNx8OBnqD<fRV>iU)C=-%y;4zULE{2cSR>SJi1^w@xeXUL{0w0s~=sO^pB2V!Ll&1(0^dX;CctQry$WnMRis=@zPi1zR|F_g3U1m&oj7~y@~4A=@Jf~eJ|0CRzV~iZ!{%!piBVUv9#MD+<QKYu-5U-&%p`W2zFEQ<s6O+7kR@W`lbe4f6n_I@Lb0f2M&SI^^)Zr^VEB+QIPC(<~;WQ9lAFUihI0RzRz!#9w*%FniTO!i;9<LU6Z6BjXwU$s8mgIeDNXAE1<lY&cQdDOjsu1i=7zQ50mIvI4Wz{uPP+R$0I`Z3$3Gf}M)hOp|^m(aV!Gt{E3*_oKZh6bAne2vt#%#vlJo$sLM^@fx7ez0I&IiQC-P)3-Z+KIR5FUMLM$UR;vWr_5Antb5$3)G*)GdDcIcqiJjlU5wC{i019|}z+KtLw^!-%UQN&!F)}_~hsaxcY?$2YjmCE-$(V==0pQ=7lvYu`juNA^vb*tMsXmI|;zZNqIcU>h%K`5+kqiTXms;~1t_CcoL?Sj7FSOe6pn<pcdzN$pu5RisV7Kf$MsFa&*Mz6ql`*gCQG*YK5w%Q-%F=f6i~yoji8(*a^22^DEa?1%+(f5{xdT28t{UI{Dm}ip{+JzCd2asqCu687jH^ggz9ucxl$9TVQ7H}|MJMHU}|O2M-NA5$bnKm7a-BXEC%8!U-8w8z)L^#u$rfIURmj%MUwpM8%PFZpWOJHF9dofSaD#N5^lAJL7I~R(F*CqRC~3I5TB9DHz=L825h5)tsx6LokFIF%V)cHBtIezD^d6#ka!|Mk+=7SO1j39JIgn}t{Ig{fsCOA7_zXM49W(|2yOQK+Zf5Fb3n^Umw>@vmm8<Jjjq<<2SlKC<q>JDyV4dI4K$V5T1hb8-qOzD_^*jQEaf_9sHJp>N%n_#{kW&Ms=jVH!x_=f-Of1q+^`S7YB<9dClg8i!RlED36Q_z(?uU9FhkIjFdQhli$hL-Zu&Fek6;1*T%KqKd*7GMuNIR(Z^U;YXZWyPca8tl?1%*Azb4A~`Hlz`K3fkef?&n!9^4_R0QDe4NR#picXVMowt)Vg~h>8l4;4&6k=Tc_I!l3l#zRem~JH5!T4Ez-^{zs=hoh{FS8oEcn=w@=d_gOP}h>K_wQa|f2ucUEce))70E2oBHnz-C4a@+4(Xj2z5Kcz8UNJB{k#GSRL;BIh!}(wN`cm3aNkk3N&Nb;z7a0?G5riV{aIOzs6r4!vnx|yoDH1w_a=*7Hif+JnHwHcANruz6P6@xd;XzPsyNk6+pX|<lDxGzbv#P$zcpJAh!OB+u!Sc%VpS4c%Wa&@eH9M=0@+Gf5n%&Ozd$=I|C&mq2SB7}AuFPaz=@bf?z@DG_k70<zQ=cVc~Z0>^wAp<5B3N)VXLXbQm_)EirR0jbTrF)Ag56D{tXQz<9cx=Dgz_K8>qmO)0)?u^hE72%6Xx!Yp7NuOuUdJk}&&tuN!F0RrdqACnJb?HXYH|_kZX14s}zf8U#-_GFASg1#OgJ3wP2s;Ebh`q(gRPzj9HbRe(OSZSs<@*eMw9VD2;UX&L}ckzy)zh4jZiB%SsJzGyxcFCP}xa4940B78ZL5LV4F9EK~Y-dy&bj=5FwdK4ODx;Xl~RHh!)zXxH(e>mVe#FT(D9>r;nu3;<d+pXjKb;DjwRv_U3^)G)T;4bW&cw4UDd9mTAZ59%`dz;oLQiZ{c(H-GwNf27$wATYTpO98(MkTmDVga0=JXJno+P4f_*8KZEg=l@LhGe5B$EzKRMmBv%8l{p3Q-{<&-4~PppKRTg3#kr;H?XwzRHo-{+5K#?yqNt>`EMa~N(bkg9iHzAQ*vctMH(}gfTdEuW;%6E$<Djm1AkH(w8H3pKXgHbJQ8?D6C4ai-b!H0K`Y~ynOihz+wr!SjNi24MO12J3$wgMf(E}_NE7%~&eRL_QP%T{G8Dl{!|OPB*;8Bsa8{xYl8I7pzewDsCeR}EUGKGjjf5cJqj>ix`-3~dsAx2Qx!NI`k=7R~GU~o0(6-W%NYQ7)XVc}F!zp8xEiI1iw)g`R)jrWxlxk3X0DFt*H7o6!>#@urT9XJ&#>2DEV0IAzo`bW12i2qJ@!zPq_*iF<Ib4N}rxDZ6FA#jjnXiR;}fZ8OC&y-e}D^I}cC+ldC86``19VZqIp1(CHjCzxC}RCLT(%p*ZLV>bc_Go{`r;Z_1TlV6B%s!R4iLVW&w95!vyN-Yzt*I)(z+m0|;;hz%)L8&IqEv+3eqq!@sX8$3<r=92?`zee<gC{AS3H2h}8!9@2vgoBc;vd?7Kd3L>JgkzGg=Rb@}Cpa{wmWX(iaQrS6GKmJ@?@#t64D3Fy_H2Qzj&-se}PoEQ8lZGsB<WLQPKfzo|2gQX`90bh8MVM0MjK5w-MrZ{hLRNJCfBAl+guac@dPd?;f-BpKF8*FK%Clabm?Yzk54{6+nxUHXcB%FZ*T$~TFn{GDG{U~=M-Dp-kc1*GzgR7j$pQ`ylr&IL?fT`D(y$Hz(`}%lAUHUz6Ru%|;}GDr1tIKIBHy%N#MbZZahG|MvdY^<E?GynJ!ju*HqEFMG^R|3zQOY`H<Asm)%F3?ee}TG}$nes{1g?HcPNIGb1{00qrcfLhSpTz2p1-}bsq_lGR4X>ezA04APlP9P>SUR$!)7B0YJv;q0Us9*Ky3V)<BcqXqf$#;ou?#-PIF`c@nxGG9AGM}Iz6uAu%Ic<GJ23E#kaeMv2#eqZ*8vlN`Ip}6XU7ni$+sjk#9UI{j;-Y;Q(inQap45N+zqx_GFpU%9-Yct1BrcOE~$!W=HNn2}MYlc7bOR_Hu1ez5)<ZAME@^U3&he4eHk9rZ?zWqrqT2)b8;ODj1Dw1KjHan6xGhY<|ArUzj1H9j^<mY3g*1yp~xaVm|#G-{Ggd)IHdzgTCpfrSG@f&xvmkH@Tm81|ypb%O=flmEGFJiE^_x(tR0=QjB?dYfFj6!0N<5R=nAAz-@kT|)O7&*Hx2n&WVBm5DSi0tJNMn_M~3dj(n0oUesS1gUzQGYkHlSHU6ksu{5<%Yz>X@MDJ(Q<biBxGx_oVaqQqK`v#&o3l!;>XvKoQJ;wf@hbnCm(fD1oD;?GnW1zOYPGzHpA!XTZLhK`%ZpZBrkb(6Zvb33)Ak3cwem(KgyK+k*GN@rw@$LndEDaID8i>kQdORzbQA&l7}r__k!Cn1asR^~jp9LZaNOBGQ|>xbU?wI_L3?_#H>RP6{hb{ZR`kuMPX}(az@naoNulwo%1qLl2_|o^)Ya-(r1t@WOba##~i%Qq2(7G8~^4<a85}GWieC811RfvmMzqM%v^Rp_9k3&<ao93>@iAtIFzt^2_U{YK6>l37#ui=lCCf%YrJ!4TX_KXUllOV=tEzdU|XuZ8YooF~L0ER667Z%9AJEM&)D!ZjtIIzuTiq#tdgZ_#4PEjlQ$9Ywi_x6PpX=z6AJ14TK=pVz!LnDMfs|r4lpsAUy>FUI*Z4hNP12bcgN`LY@da1fa4;GehJPv1fRgRzo1MC6pLL?#&rD-#)VTg_WvU$c%;PR#xeuBNFymW#zegUQ=}z6OdYdT9MvSMnr(jSnzPo4j>wMJfi?Ohqpl>f<c=ZAAx)mP@_S9=pPD-WWt1X@T6VMYCbpT|hya%zSBz}ZN|zGlSwXq@|*~zrV#b6JOWpJK=Dx%vCe#v^@a{?ox-SK*QK)Lr*UY7!|x_v&oE&d2W3Dzsqz7Nb?T;Uju7KAl3%9PFd)JxI{|73M`x6_OvDdJT=1SkD}a#Jo{cY>OJhuHT4Te_z=B{3nq%c|iqm%LOvarOt<S70TVW2~xTyCTW-x(awMTIn|QTwS}QcTZP#bDK9^`K%PzJ8?ed)~3auF=_ga%SqRIk8_3jH65&x?e`5p9q2*3TxK-V!lSmv(Zt58We(!+P>36hz@)3J(Q58Zw8m)|Ws;@|OxfS$ar_KY0PB1MmvP*g%4~<BTp84IqX)>8*0-_=~LH*SDzeyyYYRcR>{#II_G`r&R0usiv_zPYU<J74xU#z%&+W(Dj1KhAL*lt_0e7(H|n^QY<|z1f}mzdhPzI>Xv5G9vsl2XCAk@B^nCnnIP3CyIv<04%W>)QB)Wb6lTJa{MN$StmPf^z=|;)%4J=k-r@FnfD!Nx7G{wCA``IXy7ac{}Q6>fo*PYKADA+EG%2QDZtACSF>B5PgzL#K==V~#$-iNXox11K5*clXgLf)#TUeT7RMCoiO-)UOC6Hi>-^AWAuYDmA>^mQ<n8ztdHuiyQ$31cYCr=c0N|B;$gE3?LqZzkFah^b%WS#`>eoIm$V{{sbByIrohRwt~g?Aza7`ts6t%KBMu-WuS%WQl4gg6h?RYBHi3VsPx1BHLwWRdM--kc}(}j>w6<f!%5}tkEzeH#UO6SFH#ZPNQ3{#D_u{J9E{l9gNKxZWqz7Hr3fvc^QzAl^dO{H!}o0Ri>%<c=b1z0(64G-|%9M63AI+h79DNks*hg%<k1WN4q}_L;9!y7v^upCu_v|FNsZ`o>K@~U_ui0zHI}yJc5lrZn)FP#!&zCGGj&rfbLk~~US;*Ej9j^&j+?VroC<&Q#lQLNq43|kV;mSzz&Lv#{GUzW!;NMZ&K@I$h{QF5zIzogk1zc|P9IMnkFhic$F2%W`iXWd&44kSp*VhuNz+Uvb?L*>~G9$Fb}+)s1`<E!&>J@|YlucIl^ZOTX$+>@=nlI>};>BZWzDXzQu9weLIzH{TThkYC?A@#`;&6!3Wij#ogIxvaEcq26`$c3g|c!bd9*oj`}?0RZqMGLj+eVtL>VzsgAE}3)j6>;TfuGGeDOV>tncH6613;LDz|Qq}HQkMM+6X2P6nV4G@g2x;<j0pkSd=zWukdU#D($Z(cEKz+Hj<y)z$f-$-Sk{+oH72r}e@v-g+w%tb<GoE0n&8`%XDp@48MTz0uSZp+C0}Q%}U)IBT!q6pJYJ_rj_;16X2x2S28D7{clpgtXJ{KSy|x+24TYoiqu;)z<W$TrF!a>-+@&$glFDuuqq-6^M~iu-m*%dQ(>@7-+K*u!Q2XKI^XN*^>Nb9{_7$VkzTHX~KdDPpd!gBdCD8i|`(B%V9@FbkrOr&YOK&iJdL0%(~{2_+(D(hUnVhKGq1OVR|zcHA)1I`h-Y4;Yd6xnohGqII^W(fse0Rwo+#z1wR)5SXpiq9t}O1Z`Ned5%$3wjTH;z@V{hMfJqWxw}|EtDZnVVjCB6OwaDGwhyf)YiUFb8uG2h?A;;9t{^+GwVO40g`uW!YzBUz|M7n&IRDMJ|AtVmxbXV<e8_ve?^cE{pPQ6*QjRF)Srn`*lrd9}M2lQ^~6?oqL0zZ&(xaqXI09lYbt}0T7{9`F>KAH0+~^%R^4lq`+y_6)T+ckfnUror83A!8y#|qKWHnz3gfa(v>%|)(deviQF69AnLFbx9!!;wi>lw;d)xeVa<k#Ji*8AKS9_Osu_Q^SVZNZQzJVT%^L!kVzjgt;s9Ll$$H0#&X+vEC5s_}dExt1I=f_9cZk^rxSU^&`+z<-nxg$d&bzYT6<%eW0+iHqFQt>r3Rl+5#Py|67j|6K!EfubpH^Pu<1%{$g-^h<0G$I}*E7OdwY>zf|PWTJ;?8LGrQMi^q%)Wxlt42$p^ARP9G}N_&|Zai1VvJ^{)mJ(VZ~952LbEWwa{#zi72?Prgd`iZe5eYsS}sfrOzJw7aV0uds+KQv`p2LfktZPX7lCPoSYtR#e2>l*<~1+zerNuzgaoM!!(dKc-J>#$kNMJ%f9ImU2NhL9348z%i41PRNNn7m2QMM*lU$r>h2?d>zURf7UH_d#?smj;(nC3J{(8-JR9>>F#kouEzm1xU>KUbITPaUXuqD%&y+WxaX|I?B5znAah~-~n8lndMS)n~DK_na`#vF)yF53M5wU3Ov6dQ%d{imv@Apj|>)zO^%>aiAwwazCW=iZ%12nY;WBcn27x)oNkapjY=$8{bOde1j(_vgP_0#zuKeqM{0#c{FHR`(MF07Ez{LUru?xQzVqmZuEJGz@B^IJg?HSOK-vo%wD5cj{f6nwvgjePharVA950uSc`1qB-;zQ@OITNxA>2)&#CRYo#d+(CFaY;mG$!xJWcNs-pQCz({9HHya1v=mbAHE=0GcGfmGuzcI#20cT0e*<=(5+&z4p5B31Lk;Qwe-4+vbnhM0O>lbC#dr02ShI|d=nBXLk9r!dl%zKa%g0od5Qg6gi-&!5yNHFB@TP$Su`<)GbhI+#kj-<w)@e6&4ouH2I3@<4gIb%8)(VzT2B7YX3N3~B7z+l=|Nly3b<bQzN>fry$1&$h#{hp8y766cp06G?s{;?yD=#Y)W7e0zKl|P8yU7svYinlQ`LLw$=XN$v{e2phs7vn?`K~|GVKW<L;C79g@1zt_;epcNB$hs`zTVI57l$9}R6qwK>OAR11TM#mq!XQs99blf-6fbEz1ZMK1eDK!J%h_OkIMpee2i}Fbz#^M3-#NmY6)IrfPlU!iH@9k;J@c@jK&6Ty*p!`}Vzb`Yn4#{n&`{aJBM+$HyoEMHYz*1g;#2wv!UdRZ-rrJ$yB%Ic;P1I@&@0}OTVFNSJ>xxCQV=esp;9+Xv1*=3KBL4Ex6z_VuUxKfb3(=*TbgEZA)stw(^`@`K^TVkhoiOr^7Dif_XoBwB*xn;&LpDE2W2F6N!Hzq7|_m7OUk>sCV25A+h}Uf^856FM%LI@=8QZ^>;V3oXvgbmj;PAgg%4l9f*j<ocijzz7YpZDypl!ZP$0)bP{xRDD{Oz-n^kq-;0*S7N^5oTe4a&*!kd~o!>3#+2H{wP@KzJ2zPZO7k%U9Twl6x!)8Z0s&9J9+GPMeAw50B(akW4v^IfgoR@cJR_@wMQ7arxjPMVfc@z=QoC$DW?=(E;vOs@?8h`(%Ryz#rmX$)N|FahO@<oZ*q&q5yj9-vq7Kz=VN6^Cq3+)z`3yde)xY`)33MD~dw2cMf{nKxTn@0aK7OO_Y5-V}##da&8;o@N6YAc*;Q|Jm1E_b)zl@B@aeH144zh?)@4h|J$5*Xe3QpxovR<E;<aL4m(Wt>LDys)172Q~e->oo<hzlhzUzrg|P6Y4se#ySda9q?Zx2?JtM?l>PbY{Hd>cZEO_p!jethD{~)S){~nd;AwG0DY{KazIltCHHXDu=<357gOD@XuOFcWc96U`Nt=cKOu2t_G{d8IH38tvn@rcaAYZ~&)#w}^Tz`(nA5#~lBR$c!`yQ@%#^n-WCD2Te&&pUa~!ojAJtV&k^?$}@%=IARzl?kI)^;!`%lz(t;njdES<RhRJEie=>_Bp!QePcz9O>0Tl*Ov@y3F3A@0W#rb^9_D!6j3-t@EKS%oaz%~uiU`J%pN>=l+9GMsog`t5UqordJ$wS7N{vZDqD@#0SiESXoWXL3GLVdpy@SLISkzgwz<A=HYVfD(1}s_unm>id^<wR0n1#?07DnFS@2vzd(6NC``SLcXEf5jlS)>jO_4Cz<QM;wFYK7_y&3+sF1y#O%dt<#%hG?9#?G-gIW4t6XQ%)5?f4`r#8Z$CV(eEA7VCU+zsP6Xeont#Mw(E5-I3<2M6#3wH0BPOkko6%QPRkMWqsYq@zfbPpwWc)5nbdnRkbdO(zx_nG4)p09^lWab6pB)AQlZytLo4Y?HE<2W#@Y?k~vo6t(WOm0>Dt|V$m0`u=$m|=_z+p}(pSN=4++1VcxD1jIm6Q0O={jv{3Con9=#qfl)wc(UFS$wP(dVe&CSQG{o3cV4@zT1<^JP`%7yABiblvD0x}QAyPO$)6kkK`91N)Z0oS?e<ig6E79Bj2Wk@WKpEo=4}cDzC85G`VWQ_OH#V|OeiidQqD9VV3-NGJ{Q9Zo%jg$LqroQ|!SN=gdEm3f!wTvgBcy#HzgF3Z#t}1ikySxvWP%Wi5&#f4((N9v(z4G?e-&1gHbgEhzyZq<eXco)kw~wO+`seFvzDmz_y9BSf;>6C8;5}!~=JgLRCzTs6(rFtc9o3GmSK(^ya?TT%<#B1K0X-}0XNY^ayz9JxjdX;mPxN62QBh$E<9S-0mF*7`OJXf#o$V@qEcQyC5B+;|~G*U+MWI!fq>!l>^1z3;POjy%M4dixa*53UhNf7Z=SDdlgZ?&F%SVj%PGn^4hiA%Q%RzmZOhZzNr(xm4PdEzHDIpbcGR>8eHR@QbJJ4W*4bTrv3+#q*<pY%1{L-rC3}AzBkyK*3h6&UalG2!e-|NAzr$KD!KO1+4_F2Te-`wNZ`x;Yg3~g&|UNtBg%U1c?FGMR+nrT+m)KouwbTckjnJ=ohz*3QnyGj(LotVVswrXYPrQGntmk*X&hVz_Vflt+nTU}INT?)RFN9{oH%mva%k!OualzxqUL_!sEl-cN7v&k9=m};jrZ*cBnlQ@vf>;{JOz#(SfwPz|8F9lW85)SAWm(N|ndijplJuYTYVC{g)>5&M5&k(l;*3jpA*)o_EVHc!(#sz@lalSliteral 0HcmV?d00001new file mode 100644GIT binary patchliteral 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 0HcmV?d00001new file mode 100644GIT binary patchliteral 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 0HcmV?d00001new file mode 100644GIT binary patchliteral 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 0HcmV?d00001new file mode 100644GIT binary patchliteral 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 0HcmV?d00001@@ -207,7 +207,10 @@ fn well_formed_caf_still_reads() { assert_eq!((info.format, buf.frames()), (FileFormat::Caf, 480)); let table = packet_table(3, 3072, &[10, 0x81, 0x48, 5]); let aac = caf(&[caf_desc(b"aac ", 0, 1024, 2, 0), (b"pakt", table.len() as i64, table), (b"data", 219, vec![0; 219])]);- assert_eq!(probe(&aac, None).unwrap().frames, 3072);+ // The packet table is valid, but its zero-filled payload is not AAC. AAC probes+ // now decode packets to learn the actual SBR/PS rate and channel count.+ assert!(matches!(probe(&aac, None), Err(AudioError::Malformed(_))));+ assert!(matches!(decode(&aac, None), Err(AudioError::Malformed(_)))); } fn atom(kind: &[u8; 4], body: &[u8]) -> Vec<u8> {@@ -153,8 +153,13 @@ fn stamp_at_rate(stamp: u64, file_rate: u32, session_rate: u32) -> u64 { pub fn import_audio_bytes(e: &mut Engine, name: &str, bytes: &[u8], path: Option<&str>, target: Option<TrackId>, at: Samples) -> Result<Value> { let ext = Path::new(name).extension().and_then(|x| x.to_str()).map(str::to_ascii_lowercase); let (info, buf) = soundcraft_audio_io::decode(bytes, ext.as_deref()).map_err(|err| EngineError::Io(format!("{name}: {err}")))?;- let buf = at_rate(buf, e.session().sample_rate.hz(), MAX_IMPORT_SAMPLES)- .ok_or_else(|| EngineError::Io(format!("{name}: file is too large to import")))?;+ let buf = at_rate(buf, e.session().sample_rate.hz(), MAX_IMPORT_SAMPLES).ok_or_else(|| {+ EngineError::Io(format!(+ "{name}: decoded audio would exceed the 4 GiB per-file memory limit after conversion to the session's {} Hz sample rate. \+ Compressed file size does not determine decoded memory; split the source into shorter files before importing",+ e.session().sample_rate.hz()+ ))+ })?; if buf.frames() == 0 { return Err(EngineError::Io(format!("{name}: no audio"))); }@@ -1,6 +1,6 @@ # File-format parity -> **Last reviewed:** 2026-10-13 · **Last updated:** 2026-10-13 · **Change:** trivial (WAV: empty data chunk with trailing metadata (#466); previously minor: continuous fade curvature in SoundCraft sessions) · **Target:** Avid Pro Tools Ultimate 2026.4.1+> **Last reviewed:** 2026-10-20 · **Last updated:** 2026-10-20 · **Change:** minor (AAC extension decoding and gapless trim; readiness estimate unchanged) · **Target:** Avid Pro Tools Ultimate 2026.4.1 Every format Pro Tools reads or writes, and ours. The Pro Tools list comes from the document types its bundle declares (`CFBundleDocumentTypes` in Info.plist: names only, nothing else read) and its@@ -39,7 +39,7 @@ Legend: ✅ supported and tested · 🟡 partial · ❌ missing · — not appli | AIFF / AIFF-C | native | ✅ | ✅ (`fl32`) | Native | | FLAC | import | ✅ | ✅ | Own encoder | | MP3 | import, bounce | ✅ (symphonia) | ❌ | G-21 |-| AAC / M4A / MP4 audio | import, bounce | ✅ (symphonia) | ❌ | G-21 |+| Advanced Audio Coding (AAC) / M4A / MP4 audio | import, bounce | ✅ (Symphonia demuxing, scalar rusty_aac decoding) | ❌ | High-efficiency extensions retain reconstructed rate and stereo; six-channel decoding tested. Single ordinary MP4 edit and Apple priming metadata handled. Export still G-21; complex edit lists and broad codec conformance remain unqualified | | ALAC | import | ✅ | ❌ | | | Ogg Vorbis | — | ✅ | ❌ | Beyond Pro Tools | | CAF | — | ✅ | ❌ | |@@ -80,6 +80,7 @@ Legend: ✅ supported and tested · 🟡 partial · ❌ missing · — not appli | Date | Change | Summary | |---|---|---|+| 2026-10-19 | minor | AAC extensions and six-channel decoding use pure Rust with scalar dependency features. Regressions cover actual duration, rate, channels and ordinary priming metadata; no readiness percentage change | | 2026-10-13 | trivial | WAV: empty data chunk with trailing metadata (#466) | | 2026-10-13 | minor | Fade curvature round-trips in sessions with a zero default for older files. Format version and readiness estimate unchanged | | 2026-10-10 | major | Created: format inventory against Pro Tools 2026.4.1's declared document types and import/bounce options |