rockbox-codecs
Audio decoding with Rockbox's codecs as a reusable Rust library.
The decoders are the Rockbox firmware codecs — the exact code that has
played music on hundreds of DAP models for two decades — compiled into
the crate by build.rs and driven through Rockbox's codec_api by a
small C shim modeled on the upstream warble standalone test player.
No external decoder libraries, no subprocess.
let mut dec = open?;
println!;
while let Some = dec.next_chunk
Codecs (feature-gated)
All 29 codecs of Rockbox's static-link set (the same set the Android /
WASM builds of rockboxd link) are available and enabled by default;
disable default-features and pick what you need to trim compile time
and binary size.
| Feature | Formats | Decoder library | Verified by test |
|---|---|---|---|
flac |
FLAC | libffmpegFLAC | bit-exact roundtrip |
shorten |
Shorten (SHN) | libffmpegFLAC | compiles + table |
alac |
Apple Lossless (M4A) | libalac + libm4a | bit-exact roundtrip |
wavpack |
WavPack | libwavpack | bit-exact roundtrip |
ape |
Monkey's Audio (APE) | libdemac | compiles + table |
tta |
True Audio | libtta | bit-exact roundtrip |
wav |
WAV (PCM + ADPCM family) | libpcm | bit-exact roundtrip |
aiff |
AIFF | libpcm | bit-exact roundtrip |
au |
Sun AU / SND | libpcm | bit-exact roundtrip |
wav64 |
Sony Wave64 | libpcm | bit-exact roundtrip |
smaf |
SMAF (Yamaha mobile) | libpcm | compiles + table |
vox |
Dialogic VOX ADPCM | libpcm | compiles + table |
mpa |
MP1 / MP2 / MP3 (incl. MP3-in-ASF) | libmad + libasf | decode + energy check |
vorbis |
Ogg Vorbis | libtremor | decode + energy check |
aac |
AAC / HE-AAC (M4A) | libfaad + libm4a | decode + energy check |
aac_bsf |
raw AAC / ADTS streams | libfaad | decode + energy check |
opus |
Opus | libopus (fixed point) | decode + energy check |
mpc |
Musepack SV7 / SV8 | libmusepack | compiles + table |
speex |
Ogg Speex | libspeex | compiles + table |
wma |
WMA v1/v2 in ASF | libwma + libasf | decode + energy check |
wmapro |
WMA Professional | libwmapro + libasf | compiles + table |
a52 |
AC3 / A-52 | liba52 | decode + energy check |
a52_rm |
AC3 in RealMedia | liba52 + librm | compiles + table |
cook |
RealAudio Cook | libcook + librm | compiles + table |
raac |
AAC in RealMedia | libfaad + librm | compiles + table |
atrac3_rm |
ATRAC3 in RealMedia | libatrac + librm | compiles + table |
atrac3_oma |
ATRAC3 in Sony OMA | libatrac | compiles + table |
adx |
CRI ADX (game audio) | built-in | decode + energy check |
mod |
Amiga MOD | built-in | compiles + table |
Not included: the libgme chiptune family (NSF, GBS, HES, KSS, AY, SGC, VGM, VTX), SPC, SID and SAP — their emulator cores share symbols across codecs and only work in Rockbox's dlopen-one-codec-at-a-time model, so the upstream static builds exclude them too.
API model
- [
Decoder::open] parses metadata (via the siblingrockbox-metadatacrate, re-exported asMetadata), selects the codec by format, and starts a dedicated decode thread. - [
Decoder::next_chunk] pulls interleaved stereoi16PCM through a bounded channel (backpressure keeps memory flat). Mono sources are duplicated to stereo; high-depth codecs are converted from their native fraction-bit format. - [
Decoder::seek] / [Decoder::elapsed] map to the codec's native seek handling (sample-accurate where the codec supports it). chunk.sample_rateis the codec's output rate — Opus always decodes at 48 kHz, everything else at the file's native rate. Pair withrockbox-dspfor resampling, EQ and ReplayGain.
One session at a time: Rockbox codecs share a single global
codec_api instance, so Decoder::open blocks until any other live
Decoder in the process is dropped.
How it's built
- Each codec (wrapper +
codec_crt0.c+ its decoder library) compiles in its ownccbuild with the four entry symbols renamed per codec (-D__header=__header_<name>, …) — the same compile-time scheme the Rockbox WASM build uses, so no objcopy is needed on any platform. - A static codec table maps formats to the renamed
__header_<name>entry points (the pattern of Rockbox's Android static-codec loader). codeclib(shared helpers),libm4a(shared by alac + aac),tlsf(allocator for the ogg codecs) andlibasf(MP3-in-ASF) compile once.- libopus and libtremor both bundle libogg's
framing.cwith identical symbol names but different internals; the opus copy is prefix-renamed (opus_ogg_*) so both codecs can coexist in one binary. - In-repo builds compile from the live
lib/rbcodectree; the published package builds from thevendor/snapshot (./sync-vendor.sh).
Examples
# Player CLI: Rockbox decode → cpal output
Caveats
- License: the compiled C sources are Rockbox firmware code (and GPL-compatible decoder libraries), GPL-2.0-or-later overall — linking this crate makes the consuming binary GPL.
- Output is always interleaved stereo
i16in this version; multichannel sources are downmixed/dropped per the codec's own handling. - Gapless trims (encoder delay/padding) follow each codec's built-in handling; MP3 LAME-tag gapless works, but the very last Opus packet (flagged e-o-s) is skipped by the upstream wrapper.
- The upstream ASF/WMA code targets WMP-muxed files; ffmpeg-muxed WMA decodes only partially (and its header carries a preroll-inflated duration). WMP-produced files are the codec's tested corpus.