tpt-cadence

Rust

Pure-Rust, zero-dependency audio codec suite (WAV, AIFF, FLAC, AAC, Opus, MP3, Vorbis). Memory-safe, real-time capable, dual-licensed MIT/Apache-2.0. Part of the TPT AV Stack by TPT Solutions.

0 stars0 forks0 watchersApache License 2.0

Languages

Rust81.1%HTML14.6%C3.7%Python0.4%JavaScript0.2%
README

tpt-cadence

CI codecov

A pure-Rust, zero-dependency audio codec suite. Memory-safe, real-time capable, and permissively licensed (MIT OR Apache-2.0).

Status: Early-stage / Pre-1.0 (0.1.0 packaging prepared for crates.io) — WAV, AIFF, FLAC, and raw PCM are implemented and bit-exact conformance-tested (decode and encode). The AAC-LC/HE-AAC-SBR, MP3, Opus, and Ogg Vorbis decoders all pass FFmpeg-reference conformance (>100 dB SNR); AAC remains decode-only pending a licensing decision. Encoders: the MP3 encoder (CBR and VBR, bit-reservoir borrowing, ISO start/short/stop window switching, mid/side plus opt-in intensity stereo, Info/Xing + LAME gapless tags, all of MPEG-1/2/2.5), the Vorbis encoder (block switching, psychoacoustic floor, quality 0-10), and the Opus encoder (CELT, SILK, and hybrid SILK/CELT, mono/stereo, CBR/VBR, LBRR/FEC, DTX, RFC 7845 pre-skip/granules recovering the exact input sample count) produce FFmpeg-decodable streams. The lossy encoders are gated against the source signal (tone purity, alignment, level, pre-echo), not only against another decoder; on stereo music the MP3 encoder matches libmp3lame's SNR at equal bitrate. Noise shaping (MP3's outer loop, Vorbis's masking model) has not been validated by listening tests — see todo.md. Ecosystem: TPT Solutions Open Source

tpt-cadence is the audio codec layer of the TPT AV Stack. It provides pure-Rust, spec-compliant decoders (and, for most formats, encoders) written from the specification up with zero external audio dependencies — no FFmpeg, no symphonia, no hound, no C bindings.

See DESIGN.md for the full design rationale.

Core Tenets

  1. Pure Rust, zero external audio dependencies.
  2. Permissive licensing only — the whole dependency tree is audited by cargo-deny in CI; no GPL/LGPL/MPL anywhere.
  3. Real-time safe decoding — all heap allocation happens during init()/open(); decode() writes into a caller-provided buffer and is allocation-free, lock-free, and panic-free.
  4. Bit-exact conformance — every decoder is validated against official reference vectors and cross-checked against FFmpeg output.
  5. Feature-gated modularity — each format is its own crate; compile only what you need.

Ecosystem

CrateRoleRelationship to tpt-cadence
tpt-kinetixMedia containers, video codecs, streamingDemuxes containers (MP4, MKV, OGG) and extracts raw audio packets, passing them to tpt-cadence for decoding.
tpt-cadenceAudio codecs (this repo)Decodes raw audio data into PCM f32 samples.
tpt-audioAudio processing, timeline, mixing, I/OConsumes decoded PCM and feeds it into the real-time mixing graph.

tpt-cadence can also operate standalone: it reads audio files directly from disk without tpt-kinetix, useful for simple audio tools that don't need container demuxing.

Crates

CrateFormatStatus
tpt-av-cadence-coreDecoder trait, StreamInfo, shared types✅ Core API
tpt-av-cadence-pcmHeaderless raw PCM — int 8/16/24/32 + float 32/64, both byte orders✅ Stable — decode + encode, bit-exact
tpt-av-cadence-wavRIFF/WAVE — 8/16/24/32-bit int + 32/64-bit float✅ Stable — decode + encode, bit-exact
tpt-av-cadence-aiffAIFF / AIFC (big-endian IFF)✅ Stable — decode + encode, bit-exact
tpt-av-cadence-flacFLAC (lossless, LPC + Rice coding)✅ Stable — decode + encode (LPC search to order 12, stereo decorrelation, wasted bits, real STREAMINFO MD5), bit-exact
tpt-av-cadence-opusOpus (RFC 6716) + Ogg Opus container (RFC 7845)✅ Decode conformance-tested — 100% final_range on all 12 official RFC 6716 vectors; SILK-only vectors bit-exact. ✅ Encoder scope complete: CELT encoder (mono/stereo, fullband, CBR/VBR, all 4 frame sizes, transient/TF handling, M/S + intensity stereo, dynalloc steering), a complete SILK encoder (SilkEncoder: reference noise-shaping NSQ + delayed-decision NSQ behind set_complexity, per-frame rate control onto the caller's budget, mono + stereo adaptive mid/side, VAD, Burg LPC, NLSF interpolation, LBRR/FEC via set_packet_loss_perc, DTX, CBR payload sizing), SILK-mode .opus writing (new_silk/new_silk_cbr), and hybrid SILK+CELT writing (new_hybrid, TOC configs 12–15, mono or stereo on a shared range coder) — all decoder-bit-exact, with RFC 7845 pre-skip/granules recovering the exact input sample count
tpt-av-cadence-oggOgg page/packet container (RFC 3533) shared by Vorbis and Opus✅ In use
tpt-av-cadence-aacAAC-LC (ISO/IEC 14496-3)✅ Conformance-tested (>100 dB SNR vs FFmpeg), decode-only
tpt-av-cadence-mp3MPEG Layer III✅ Decode conformance-tested (>100 dB SNR vs FFmpeg) on ten bundled streams plus a generated 23-stream LAME oracle matrix (MPEG-1/2/2.5, 8–320 kbps ladder, all channel modes, feature-coverage-asserted) standing in for the unobtainable ISO/IEC 11172-4 vectors. ✅ Encoder: full CBR and loudness/quality-targeting VBR across MPEG-1/2/2.5 with bit-reservoir borrowing, ISO start/short/stop window switching, mid/side + opt-in intensity stereo, and Info/Xing + LAME gapless tags. Gated against the source signal (tone purity 55–80 dB in every version family, sample-exact alignment, mid/side level, click-train pre-echo) and FFmpeg-decodable (90–120 dB inter-decoder); SNR matches libmp3lame at equal bitrate on stereo music. The masking-model outer loop is present but disabled (unvalidated perceptually) — see todo.md
tpt-av-cadence-vorbisOgg Vorbis I✅ Decode conformance-tested (136–138 dB SNR vs FFmpeg on six bundled fixtures). ✅ Encoder (VorbisEncoder, floor 1 + coupled residue type 1, quality 0–10, exact input length via granule trimming): block switching (2048/256), a Bark-band masking model driving the floor, FFmpeg-verified round trips at 136 dB inter-decoder; per-file adaptive Huffman books remain future work and the masking constants are unvalidated by listening tests — see todo.md
tpt-av-cadence-test-utilsConformance harness — FFmpeg comparison, fuzz helpers, MD5✅ Internal (dev-only)

See capabilities.json for a machine-readable version of this table (per-crate format list, decode/encode/conformance status, real-time-safety and fuzz flags), and CONFORMANCE.md for a generated dashboard of the actual per-stream SNR/pass-fail numbers each crate's conformance suite reports (regenerate with python3 tools/conformance_dashboard.py; CI regenerates it on every push to master and uploads it as a build artifact — FFmpeg must be on PATH for the FFmpeg-oracle rows to populate).

Quickstart

Decode a WAV file to interleaved f32 samples:

use std::fs::File;
use tpt_av_cadence_core::{Decoder, FormatReader};
use tpt_av_cadence_wav::WavReader;

let file = File::open("music.wav")?;
let mut reader = WavReader::open(Box::new(file))?;

let info = reader.info();
println!("{} Hz, {} channels, {} bit",
    info.sample_rate, info.channels, info.bit_depth);

// `decode()` is allocation-free, lock-free, and panic-free:
// safe to drive from a background decoding thread.
let mut buf = vec![0.0f32; 4096 * info.channels as usize];
loop {
    let frames = reader.decoder().decode(&mut buf)?;
    if frames == 0 {
        break; // end of stream
    }
    // `buf[..frames * channels]` now holds interleaved PCM in [-1.0, 1.0].
}

Quickstart per format

Every decoder crate ships a runnable example that decodes to raw interleaved f32 PCM. Each one prints stream info (sample_rate, channels, etc.) to stderr; most write raw PCM to stdout — redirect it to a file:

FormatCrateRun it
WAVtpt-av-cadence-wavcargo run -p tpt-av-cadence-wav --example wav_decode -- clip.wav > out.f32
AIFF / AIFF-Ctpt-av-cadence-aiffcargo run -p tpt-av-cadence-aiff --example aiff_decode -- track.aif > out.f32
Raw PCM (headerless)tpt-av-cadence-pcmcargo run -p tpt-av-cadence-pcm --example pcm_decode -- audio.raw s16le 2 48000 > out.f32
FLACtpt-av-cadence-flaccargo run -p tpt-av-cadence-flac --example flac_decode -- album.flac > out.f32
MP3tpt-av-cadence-mp3cargo run -p tpt-av-cadence-mp3 --example mp3_decode -- song.mp3 > out.f32
AAC-LC (+ SBR/HE-AAC)tpt-av-cadence-aaccargo run -p tpt-av-cadence-aac --release --example aac_dump -- song.aac out.f32
Ogg Vorbis Itpt-av-cadence-vorbiscargo run -p tpt-av-cadence-vorbis --example vorbis_decode -- file.ogg > out.f32
Opus (RFC 6716)tpt-av-cadence-opuscargo run -p tpt-av-cadence-opus --example opus_decode -- song.opus > out.f32

tpt-av-cadence-pcm's example takes the sample format on the command line (s8, s16le/s16be, s24le/s24be, s32le/s32be, f32le/f32be, f64le/f64be) since headerless PCM carries no self-describing metadata.

Encoders exist today for WAV, AIFF, PCM, FLAC (lossless), MP3, Ogg Vorbis, and Ogg Opus; AAC is decode-only:

FormatCrateRun it
WAVtpt-av-cadence-wavcargo run -p tpt-av-cadence-wav --example wav_encode -- tone.wav
AIFF-Ctpt-av-cadence-aiffcargo run -p tpt-av-cadence-aiff --example aiff_encode -- tone.aiff
Raw PCM (headerless)tpt-av-cadence-pcmcargo run -p tpt-av-cadence-pcm --example pcm_encode -- tone.raw
FLACtpt-av-cadence-flaccargo run -p tpt-av-cadence-flac --example flac_encode -- tone.flac
MP3tpt-av-cadence-mp3cargo run -p tpt-av-cadence-mp3 --example mp3_encode -- tone.mp3
Ogg Vorbistpt-av-cadence-vorbiscargo run -p tpt-av-cadence-vorbis --example vorbis_encode -- tone.ogg 5 (quality 0-10)
Ogg Opustpt-av-cadence-opuscargo run -p tpt-av-cadence-opus --example opus_encode -- tone.opus hybrid (celt, vbr, silk or hybrid)

The MP3 encoder (CBR and VBR, MPEG-1/2/2.5) produces FFmpeg-decodable streams whose decode reproduces the source (see the fidelity gates in tpt-av-cadence-mp3/tests/encoder_fidelity.rs); what remains open is perceptual noise-shaping tuning, which needs listening tests — see todo.md.

Decode any supported format to PCM

For format auto-detection across the whole suite, the tpt-av-cadence-cli crate (cadence info <file> / cadence decode <file>) is the canonical reference — see its src/main.rs for the full implementation, including sniffing an .ogg file's first page for OpusHead vs. \x01vorbis to tell Opus and Vorbis apart.

tpt-av-cadence-cli gates each format behind its own Cargo feature (wav/aiff/flac/mp3/aac/opus/vorbis, all on by default) — a build that only needs one format can drop the rest as compiled dependencies entirely, not just at runtime:

cargo build -p tpt-av-cadence-cli --release --no-default-features --features wav,flac

The core of it distills to matching on file extension and opening the matching reader behind the shared FormatReader trait:

use std::fs::File;
use std::path::Path;
use tpt_av_cadence_core::{CadenceError, FormatReader};

fn open_any(path: &Path) -> Result<Box<dyn FormatReader>, CadenceError> {
    let file = File::open(path).expect("open input");
    let ext = path.extension().and_then(|e| e.to_str()).unwrap_or_default();

    let reader: Box<dyn FormatReader> = match ext.to_ascii_lowercase().as_str() {
        "wav" | "wave" => Box::new(tpt_av_cadence_wav::WavReader::open(Box::new(file))?),
        "aif" | "aiff" | "aifc" => Box::new(tpt_av_cadence_aiff::AiffReader::open(Box::new(file))?),
        "flac" => Box::new(tpt_av_cadence_flac::FlacReader::open(Box::new(file))?),
        "mp3" => Box::new(tpt_av_cadence_mp3::Mp3Reader::open(Box::new(file))?),
        "aac" | "adts" => Box::new(tpt_av_cadence_aac::AacReader::open(Box::new(file))?),
        "opus" => Box::new(tpt_av_cadence_opus::OggOpusReader::open(Box::new(file))?),
        // ".ogg"/".oga" need the OpusHead/vorbis sniff — see main.rs's `sniff_ogg`.
        other => panic!("unsupported extension: {other}"),
    };
    Ok(reader)
}

// Then decode identically regardless of format:
let mut reader = open_any(Path::new("music.wav"))?;
let mut buf = vec![0.0f32; 4096 * reader.info().channels as usize];
loop {
    let frames = reader.decoder().decode(&mut buf)?;
    if frames == 0 { break; } // end of stream
    // buf[..frames * channels] is interleaved f32 PCM in [-1.0, 1.0].
}

Headerless raw PCM isn't in this dispatch — with no header, there's nothing to auto-detect the sample format from; use tpt-av-cadence-pcm directly with the format supplied out-of-band, as in pcm_decode above. A cargo-generate template isn't provided (the snippet above plus tpt-av-cadence-cli's full implementation cover the same ground); one may be added later if there's demand for a scaffolded starter project.

WASM

Every decoder crate builds for wasm32-unknown-unknown with zero code changes (verified in CI) — each one operates on an in-memory Box<dyn Read + Send> source rather than the filesystem, so nothing about the actual decode path is platform-specific. tpt-av-cadence-wasm-demo is a minimal wasm-bindgen wrapper (WAV only, as a proof of the pattern) with a Node.js test proving real decoded output through an actual wasm runtime, not just a successful compile — see that crate's src/lib.rs for the build/bind steps and test.js for the harness.

Comparison to other Rust audio crates

An honest comparison, not a sales pitch — some of these projects are more mature and more broadly capable than tpt-cadence today.

tpt-cadencesymphoniahoundminimp3-rs
ScopeWAV/AIFF/PCM/FLAC/MP3/Opus/Vorbis decode+encode; AAC-LC+SBR decode-onlyVery broad: demuxing (MP4/MKV/OGG/...) plus WAV, FLAC, MP3, AAC, Vorbis, Opus, ALAC, ADPCM decodersWAV read + write onlyMP3 decode only
ImplementationPure Rust, zero external audio dependencies, no unsafe in the decode/encode path (verified: no unsafe blocks, no -sys crates in the workspace)Pure RustPure RustWraps the C minimp3 library by default via FFI (unsafe); has an optional pure-Rust backend
ConformanceEvery decoder is validated against official reference vectors (e.g. bit-exact on all 12 RFC 6716 Opus test vectors, IETF FLAC testbench MD5s) and/or cross-checked against FFmpeg output at >100 dB SNRBroad real-world use and testing; no published bit-exactness claims of this kindSimple round-trip tests (WAV has no lossy path to conform against)Relies on the underlying minimp3 C decoder's own correctness
Real-time safetyExplicit contract: all allocation happens at open()/init(); decode()/encode() are allocation-free, lock-free, and panic-freeNot a documented contractN/A (simple I/O)Not a documented contract
LicensingMIT OR Apache-2.0; whole dependency tree enforced permissive-only in CI via cargo-deny (no GPL/LGPL/MPL)MPL-2.0 (copyleft on the crate itself)MIT OR Apache-2.0MIT (bindings); links a C library at build time
MaturityPre-1.0, very young (started Sept 2026), 0.1.0 packaging prepared but not yet published to crates.ioMature, widely deployed, large contributor baseMature, narrow scope, widely usedMature, narrow scope

Format-specific incumbents worth knowing about too:

  • claxon — pure-Rust FLAC decoder, mature and widely used; tpt-av-cadence-flac covers the same ground plus an encoder, with conformance pinned to the official IETF vectors.
  • lewton — pure-Rust Vorbis decoder; tpt-av-cadence-vorbis is a newer, independently-from-spec implementation, cross-checked against FFmpeg (136-138 dB SNR on the bundled fixtures) rather than against lewton itself.
  • audiopus / the opus crate — Rust bindings to the reference C libopus via FFI (unsafe, requires a system or vendored libopus build); tpt-av-cadence-opus is a from-spec pure-Rust reimplementation with no C dependency, validated against the same RFC 6716 test vectors libopus itself ships.

Why pick tpt-cadence today: you want a pure-Rust dependency tree with no C bindings or unsafe anywhere in the codec path, permissive licensing enforced by CI, and decoders that are individually conformance-tested against official references rather than only exercised in aggregate.

Why you might not (yet): it's a young, pre-1.0 project — smaller ecosystem and less battle-tested in production than symphonia; compressed encoders are functional and source-verified but their perceptual noise shaping is unvalidated (the MP3 outer psychoacoustic loop is disabled and Vorbis's masking model has had no listening tests; Vorbis also lacks adaptive Huffman books and its quality ceiling is about 22 dB SNR on music, 31 dB on pure tones, at q10); AAC has no encoder; no container demuxing (that's tpt-kinetix's job, not this crate's); not yet published to crates.io; and there's no published benchmark suite yet, so no performance claims are made here one way or the other. Development so far has been on Windows/MSVC, though CI exercises Linux, macOS, and Windows on every change.

Repository Layout

All sub-crates share the tpt-av-cadence- prefix for ecosystem coherence and clean namespace resolution on crates.io. See DESIGN.md §3 for the full tree.

Building & Testing

Requires Rust 1.75+ (the MSRV enforced in CI). CI builds and tests the workspace on Linux, Windows, and macOS:

cargo build --workspace --all-targets
cargo test --workspace                                        # includes bit-exact conformance suites
cargo fmt --all -- --check                                    # CI also runs clippy -D warnings
cargo clippy --workspace --all-targets -- -D warnings
cargo deny check licenses                                     # MIT/Apache-only dependency audit

Conformance testing is anchored by tpt-av-cadence-test-utils:

  • FLAC output is MD5-verified against the official IETF decoder testbench vectors (CC0, bundled under tpt-av-cadence-flac/tests/data/).
  • WAV is cross-checked against FFmpeg via assert_bit_exact_vs_ffmpeg; tests skip gracefully when FFmpeg is not installed locally.

Contributing

This project does not accept pull requests. See CONTRIBUTING.md for how to report bugs or request features via GitHub issues.

License

Dual-licensed under either of

at your option.