* craft-audio: ALAC decoder and encoder, ported from Apple's reference
Add `craft_audio::alac`, a Rust port of Apple's ALAC reference
implementation (macosforge/alac@c38887c, Apache-2.0):
- `alac::Decoder`: packets to planar i32, bit depths 1-32, 1-8 channels,
cookies in MP4/Matroska (24-byte config), CAF and old QuickTime form.
Hostile input returns errors; arithmetic wraps where C would overflow.
- `alac::Encoder`: 16/20/24/32 bits, 1-8 channels, fast mode, any frame
length; same packets as the reference for the same input.
- `SpecificConfig` (cookie parse/write), `wav_order`/`alac_order`,
`channel_mask`.
- Features `alac-decode` (in `decode-native`) and `alac-encode` (in
`encode`).
`TrackDecoder` decodes ALAC natively, so ALAC in MP4 and Matroska no
longer goes through symphonia (CAF still does).
Apple's reference writes the cookie's channel layout tag in host byte
order; this writes it big-endian as its cookie description specifies and
reads either.
Tests: unit tests for each part, an MP4 decode-and-seek test without
symphonia, and ffmpeg oracles both ways (bit-exact, 1-8 channels).
NOTICE and each file's header record the Apache-2.0 origin.
* craft-audio: ALAC review fixes (#731)
- Decode the full-width residual escape 0xffffffff as i32::MIN; the
reference's `nd + 1` wraps it to 0.
- Require a whole element tag after the last channel (the end tag, after
any fill or data stream elements), so a packet that lost its last byte
is an error instead of decoding without damage. Other elements there
end the packet, as in the reference.
- Refuse an ALAC track with no sample rate in its cookie or container.
- Conceal a damaged packet with the length its header gives
(`alac::Decoder::packet_frames`), falling back to the last packet's.
- Matroska: place ALAC packet starts at multiples of the frame length
instead of the rounded block timestamps, so seeks land on the exact
frame. MP4 keeps its exact sample-table timing.
* craft-audio: exact Matroska ALAC seeks after a short packet (#731)
Packet starts were multiples of the frame length, so a short packet
before the end moved every later packet and seeks after it returned
the wrong frames. When a packet's timestamp is further from that
multiple than its rounding allows, the starts are now counted from the
earlier packets' headers (read once and kept). Other codecs with a
fixed packet length fall back to the timestamp, as before.
---------
Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com>