Expand description
rusty_mp3 — an in-house, pure-Rust MP3 (MPEG-1/2/2.5 Audio Layer III)
decoder and encoder. Zero dependencies, no C, no FFI.
Why in-house: the robust Rust MP3 crate (Symphonia) is MPL-2.0, which trips a no-copyleft license gate; the permissive one (puremp3) is incomplete, and every existing Rust MP3 encoder option is an FFI binding to LAME. MP3’s patents expired in 2017 and Layer III is exhaustively documented, so we built our own.
§Layout (the framework, built brick by brick)
- shared:
header(frame header),frame(side-info + types),bitio(MSB-first bit I/O),tables(ISO constant tables) decode: side-info → reservoir → Huffman → scalefactors → requantize → stereo → antialias → IMDCT → synthesis filterbank → PCMencode: analysis filterbank → MDCT → psychoacoustic model → two-loop quantizer → Huffman → bitstream
§Stream API
Mp3Decoder and Mp3Encoder are the packet-level entry points:
push bytes/PCM in, pull frames/packets out. The pull calls follow FFmpeg’s
EAGAIN/EOF drain protocol via Error::Again / Error::Eof — see
error. The frame-level engines (Mp3Decode / Mp3Encode) are also
public for callers that do their own framing.
Re-exports§
Modules§
- bitio
- MSB-first bit I/O over the main-data byte stream.
- decode
- MP3 decode pipeline.
- encode
- MP3 encode pipeline (the inverse of decode, plus a psychoacoustic model).
- error
- Dependency-free error type for the MP3 codec.
- frame
- Shared MP3 types: channel layout, block types, side-information, and the fixed structural constants. These are read by the decoder and written by the encoder, so they live in one place.
- header
- MP3 frame header — the 32-bit sync header that prefixes every frame.
- tables
- Constant tables defined by ISO/IEC 11172-3 (MPEG-1) and 13818-3 (MPEG-2).
Structs§
- Decoded
Audio - One decoded chunk of PCM — the output of
Mp3Decoder::next_frame.samplesis interleaved f32 in[-1, 1],samples.len()= per-channel samples ×channels. - Mp3Decoder
- Stream-level MP3 decoder:
pushraw bytes (packets may split/join frames — the decoder frame-syncs internally, skipping ID3 and garbage), then drain decoded PCM withnext_frame. - Mp3Encoder
- Stream-level MP3 encoder: accumulates per-channel PCM, emits one MP3 frame per
1152 samples per channel (576 for MPEG-2/2.5). MPEG-1/2/2.5, CBR or VBR,
psychoacoustic noise shaping; mono, stereo, or per-frame mid/side joint
stereo. Configured via
Mp3EncoderConfig. - Mp3Encoder
Config - Configuration for
Mp3Encoder.
Constants§
- MAX_
INPUT_ AMPLITUDE - The largest input magnitude the encoder accepts: 8x (+18 dB over) full scale. Ordinary PCM, f32 overs included, is far inside it and passes through untouched. Beyond it, input is clamped – the rate loop was measured to fit up to 4096x full scale and to fail by 65536x, which used to surface as a panic in the reservoir assembly on hostile PCM (integer-valued “f32” samples, random bit patterns).
Functions§
- decode_
pipelined - Decode a complete MP3 stream with a two-stage pipeline across two threads.
- encoder_
header - Build the frame header from the input’s sample rate, channel count, and the configured CBR bitrate (VBR overrides the bitrate per frame later).
- snap_
bitrate - Snap a requested bitrate (kbps) to the nearest valid Layer III value for the MPEG version (the V1 and V2/2.5 bitrate tables differ).
- vbr_
quality_ index - Map an ffmpeg/LAME-style VBR quality index (
-q:a, 0 = best … 9 = smallest) to the peak-NMR targetMp3EncoderConfig::vbr_qualityexpects.