From 1ad4699fcd278dbfd5a15d7c523229c0ecf7b7c3 Mon Sep 17 00:00:00 2001 From: alehel Date: Wed, 4 Nov 2026 15:20:29 +0100 Subject: [PATCH] craft-audio: review fixes, round 5 (#443) No change in decoding. An aac-encode build in the next PR needs the split_adts_upto re-export behind aac-decode, and ID_END only in tests. Docs say the lookahead's headers give an ADTS stream's configuration, that AAC in CAF still goes through symphonia, and that ProgramConfig is not #[non_exhaustive]. Co-Authored-By: Claude Opus 5.5 --- crates/audio/README.md | 5 +++-- crates/audio/src/aac/decoder.rs | 1 + crates/audio/src/aac/mod.rs | 1 + crates/audio/src/track.rs | 6 +++--- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/audio/README.md b/crates/audio/README.md index afbff374..667ae2a7 100644 --- a/crates/audio/README.md +++ b/crates/audio/README.md @@ -409,7 +409,8 @@ What else an app adjusts: `AudioBuffer::from_interleaved` and `num_channels`, and the `ChannelLayout` constructors and `channels()`. - `AudioInfo`, `AudioError`, `EncodeOptions`, `BwfInfo`, `SampleFormat`, `BitDepth`, the codec - `Error` enums and the codec modules' header, frame and config structs are `#[non_exhaustive]`. + `Error` enums and the codec modules' header, frame and config structs (but for + `aac::ProgramConfig`) are `#[non_exhaustive]`. `Speaker::ALL` is a slice. - `TrackInfo::sample_rate` and `channels` are `Option`s. - Features are per codec. SoundCraft's `encode` (WAV, AIFF, FLAC) is now `lossless-encode`, made @@ -419,6 +420,6 @@ What else an app adjusts: short slices instead of filling them with silence. - `DecodeOptions` is not `Copy`. - The FLAC encoder's vendor string is `craft-audio `. -- `decode` tries native decoders first. AAC no longer goes through symphonia. +- `decode` tries native decoders first. AAC no longer goes through symphonia, except in CAF. MP4 and Matroska files decode to presentation length. A packet that fails is concealed, not dropped. A failed source read is `AudioError::Io`. diff --git a/crates/audio/src/aac/decoder.rs b/crates/audio/src/aac/decoder.rs index a8a865d5..641f7123 100644 --- a/crates/audio/src/aac/decoder.rs +++ b/crates/audio/src/aac/decoder.rs @@ -17,6 +17,7 @@ const ID_LFE: u32 = 3; const ID_DSE: u32 = 4; const ID_PCE: u32 = 5; const ID_FIL: u32 = 6; +#[cfg(test)] const ID_END: u32 = 7; /// `extension_type` of a fill element carrying SBR data (ISO/IEC 14496-3 ยง4.5.2.8.2, Table 4.121). diff --git a/crates/audio/src/aac/mod.rs b/crates/audio/src/aac/mod.rs index a9e56f89..13419bcc 100644 --- a/crates/audio/src/aac/mod.rs +++ b/crates/audio/src/aac/mod.rs @@ -26,6 +26,7 @@ mod mdct; mod tables; mod tns; +#[cfg(feature = "aac-decode")] pub(crate) use config::split_adts_upto; pub use config::{AdtsHeader, AudioSpecificConfig, ElementType, ProgramConfig, config_layout, split_adts}; pub use decoder::Decoder; diff --git a/crates/audio/src/track.rs b/crates/audio/src/track.rs index 800effe4..d5eee04f 100644 --- a/crates/audio/src/track.rs +++ b/crates/audio/src/track.rs @@ -17,7 +17,7 @@ enum Inner { dec: Box, up: Option, order: Option<&'static [usize]>, - /// The format ADTS packets must keep, when the first ADTS header gave the configuration. + /// The format ADTS packets must keep, when their headers gave the configuration. adts_format: Option, }, Pcm { @@ -92,7 +92,7 @@ impl TrackDecoder { #[cfg(feature = "aac-decode")] CodecId::Aac | CodecId::HeAac => { // ADTS-framed packets (MPEG-TS, raw `.aac`) carry their configuration in each - // header: without extradata, the first header gives it. + // header: without extradata, the headers of the lookahead give it. let payloads: Vec<&[u8]> = lookahead.iter().map(|p| adts_frames(p).and_then(|f| f.first().map(|(_, unit)| *unit)).unwrap_or(p)).collect(); let mut adts_format = None; @@ -347,7 +347,7 @@ pub(crate) fn adts_format_of(h: &aac::AdtsHeader) -> AdtsFormat { (h.object_type, h.sf_index, h.channel_config) } -/// The raw access units of an ADTS-framed packet. In a stream whose first header gave its `format`, +/// The raw access units of an ADTS-framed packet. In a stream whose headers gave its `format`, /// a frame that changes it would play wrongly, so it is malformed; with extradata, that decides the /// format and headers are not compared with it. Frames with several raw data blocks are /// unsupported.