Skip to main content

Crate lac

Crate lac 

Source
Expand description

LAC — Lo Audio Codec.

Lossless audio codec targeting FLAC-class compression. Integer-only, bit-exact, streaming-oriented. Scope:

  • Input: signed 24-bit PCM (values in [-2^23, 2^23 − 1]), sample rate is caller-specified and not encoded in the stream — the container or transport carries it.
  • Channels: mono per encoded stream. Stereo is delivered as two independent mono streams (e.g., two QUIC streams in a streaming context); cross-channel decorrelation is explicitly out of scope.
  • Frames: self-contained. Each frame decodes independently — no cross-frame state. A lost or corrupt frame never affects subsequent frames.

§Pipeline

Encode: samples → LPC analysis → residuals → partitioned Rice coding → frame bytes. Decode is the exact inverse.

  • LPC: Levinson-Durbin at any order in [0, 32]. Order 0 is verbatim mode (residuals equal the raw samples).
  • Rice: residuals split into 2^partition_order equal partitions with partition_order ∈ [0, 7] (1 to 128 partitions). Each partition chooses its own Rice parameter k ∈ [0, 23].

Both selections are made by the encoder via exhaustive search over the combinations whose partition count evenly divides the frame size.

§Error handling

Decode returns Err(DecodeError) on any structural failure (bad sync, invalid header fields, truncated buffer). Callers are expected to substitute frame_sample_count zeros (or equivalent silence) for the frame period — never propagate partial state.

§no_std

The library is #![no_std] with a dependency on the alloc crate for Vec-backed buffers. Targets with an allocator (std OSes, WASI/WASM, embedded with heap) all link without feature flags. True bare-metal (no allocator) is unsupported because variable-length residual and coefficient buffers are fundamental to the codec. DecodeError implements core::error::Error (stable since Rust 1.81), so ?-propagation through Result-returning traits works in both std and no_std contexts.

§Wire-format touchpoints

The normative wire format lives in Specification.md; its implementation is split across three crate-private modules by concern. Any future wire-format revision (CRC tag, version flag, new partition mode, …) touches at least frame plus whichever module owns the new bits.

  • frame — fixed header layout (sync word, prediction_order, partition_order, coefficient_shift, frame_sample_count, LPC coefficients) plus synthesis. parse_header, encode_frame, decode_frame, and AudioFrameHeader all live here.
  • rice (crate-private) — partitioned Rice bitstream. Owns the 5-bit per-partition k field, the zigzag mapping and its inverse, and the q > u32::MAX >> k rejection bound from spec §4.2.
  • bit_io (crate-private) — MSB-first bit reader / writer primitives. Byte-level packing semantics (first bit → bit 7 of first byte) live here; both frame and rice are clients.

When reading the spec alongside the source, §3 maps to frame, §4 to rice, and the bit-order conventions of §2 / §4 to bit_io.

Re-exports§

pub use frame::AudioFrameHeader;
pub use frame::DecodeError;
pub use frame::SYNC_WORD;
pub use frame::decode_frame;
pub use frame::decode_frame_into;
pub use frame::encode_frame;
pub use frame::encode_frame_into;
pub use frame::parse_header;

Modules§

frame
Frame encode and decode.

Constants§

MAX_COEFFICIENT_SHIFT
Maximum supported coefficient_shift. At this value, coefficients span real-value range [−32, 32) — far beyond anything audio produces in practice. The bitstream decoder rejects larger values.
MAX_LPC_ORDER
Maximum supported LPC prediction order.
MAX_PARTITION_ORDER
Maximum supported partition order. partition_count = 1 << partition_order.
MAX_RICE_K
Maximum Rice parameter k.