* craft-audio: native MP3 (Layer III) decoder (feature `mp3-decode`)
A clean-room Layer III decoder written from ISO/IEC 11172-3 and 13818-3:
MPEG-1, MPEG-2 and MPEG-2.5 (8-48 kHz), CBR and VBR, mono, stereo, dual
channel and joint stereo (mid/side and intensity), long, short and mixed
blocks, and the bit reservoir. It shares the encoder's Huffman and
scalefactor band tables and the MP1/MP2 synthesis filter.
`decode`, `Decoder` and `TrackDecoder` now read raw .mp3 files and MP3 in
MP4 and Matroska natively instead of through symphonia. A Xing / Info / VBRI
frame is not a packet, and the LAME tag's encoder delay and padding are
applied, so a file decodes to its exact presented length. The seek
pre-roll covers how far back the bit reservoir can reach, so a seek is
bit-exact. symphonia stays the fallback for free-format MP3.
The encoder moves to mp3/encoder.rs so that each half builds without the
other.
* craft-audio: MP3 review and CI fixes
- Huffman: big values stop at the granule's part2_3_length. A damaged
granule no longer reads the next granule's bits, as ffmpeg does.
- Joint stereo runs on the lines in coded order, before short blocks are
reordered, as ffmpeg and libmad do. Where the two channels' block layouts
differ, against the specification, each channel is then reordered by its
own layout.
- Seek pre-roll: sized from the smallest frame the stream can hold (the
lowest bit rate for its version, rate, mode and CRC), not the last frame,
so a seek into a VBR stream's small frames still has the reservoir. The
decoder learns the stream's format from its first frame.
- Mixed-block oracle test: edit only granules whose scalefactors take no
bits, so the edited streams stay valid, and not before a pure short
block. ffmpeg's short-block IMDCT drops overlap that a mixed block's long
subbands carry, where the specification adds it. Use 16 kHz instead of
12 kHz.
- Routing oracle: ffmpeg before 9 decodes the 1105 samples of the MP3
Matroska CodecDelay.
* craft-audio: MPEG audio packets of several frames keep their length
An MP4 or Matroska packet may hold several MP1/MP2/MP3 frames.
TrackDecoder now counts the frames each packet holds from their headers:
- frames_per_packet is None once a packet in the lookahead or a decoded
packet has held several frames, so an MP4 track's length is no longer
capped at one frame per sample and the container's timing decides.
- Concealment is the length of the frames a damaged packet holds. For MP3
a packet lost whole is as long as the last packet, and one frame before
any is decoded.
Also corrects the Huffman doc comment: a big-value pair that starts
before the granule's end is kept whole, as ffmpeg does.
* craft-audio: MPEG audio concealment after partial packets and before the first
- A packet whose later frame fails decodes only in part: like AC-3, it no
longer replaces the length of the last whole packet that concealment
uses.
- MP1/MP2: a packet lost before any has decoded, or right after a seek, is
one frame (384 or 1152 samples) of silence rather than none, as MP3's
already is.
---------
Co-authored-by: alehel <git@ornumhelgaker.no>
* craft-audio: FilmCraft's FLAC encoder and MP1/MP2 decoder speed-ups
FLAC: per-order predictor kernels, merged Rice partition sums, the LPC
window kept per block length, and batches consumed by offset
(filmcraft 5eaff794, d9dad4a5). The output is unchanged: 64 golden cases
hash the same before and after.
MP1/MP2: the faster synthesis filterbank (filmcraft 51c755e5), with its
bit-exact test.
* craft-audio: FilmCraft's AAC and Opus decoder speed-ups and refactors
AAC: table-driven Huffman decoding, per-stage FFT twiddles and fused
stages, reused per-channel work buffers, and the encoder's memoised
per-band work (filmcraft f9627280, d587ceed, 6121635c, dc124ab7,
7a532eca).
Opus: radix-2/3/4 FFT kernels in the CELT IMDCT, the PVQ table built
once, one de-emphasis loop for both channels, the SILK resampler
without per-sample divisions and with eight partial sums, concealment
and FEC capped at 120 ms (filmcraft bf7ac420, 12e32026, c4dc64d1,
eb352ec8, 87b8e22d, 014b5e56, 78d77b72).
The per-frame mid-only flag this crate fixed in the SILK decoder is
kept in the refactored decode.
* craft-media: Ogg CRC-32 by slice-by-16
FilmCraft's 6763f9bf: sixteen independent lookups per 16 input bytes, so
opening a file is several times faster. Checked against a bit-at-a-time
reference on every short length and alignment, and across every split.
* craft-audio: SoundCraft's CAF cookie-size and FLAC vendor-length checks
A CAF magic cookie size above the signed range is refused instead of
passed to symphonia (soundcraft 3bd3965), and a Vorbis comment block
whose vendor string claims more than the block holds is refused
(soundcraft ddfe991). Each with its regression test.
* craft-audio: AC-3 reads bits through the shared BitReader
FilmCraft's 1c9c2e82: the AC-3 decoder's private bit-at-a-time reader is
replaced by craft-media's BitReader, with its two tests: the decoded
output of 2,000 synthetic and 12 real syncframes (and their damaged
variants) hashes the same as before, and the reader agrees with the old
one on random reads, skips and overruns. The three AC-3 features now
turn on craft-media's bitstream module.
* craft-audio: the quantiser rounds without a libm call
SoundCraft's d293336, the audio-io part: round-half-away by integer
arithmetic in the bounce's inner loop, with its test against f64::round
over the quantiser's range.
FilmCraft's MPEG audio Layer I/II decoder as `craft_audio::mpa` behind
`mpa-decode`, kept over symphonia's: the same quality where both
decode, and it also decodes the MP2 files ffmpeg writes by default
(mono at 384 kbit/s), which symphonia rejects. `TrackDecoder` and the
native read path take MP1/MP2 in MP4, Matroska and raw streams;
symphonia keeps MP3 only, so its `mp1` and `mp2` features are dropped.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com>