A modern, network-enabled music player platform built on Rockbox technology. rockboxd.tsiry-sandratraina.com
rust deno navidrome airplay libadwaita zig mpris snapcast mpd rockbox audio subsonic
2

Configure Feed

Select the types of activity you want to include in your feed.

fix(rockbox-wasm): guard aac_bsf divide-by-zero on container-less ADTS; bump to 0.1.8

Progressive M4A/AAC playback re-frames MP4 samples to ADTS and decodes them
through the aac_bsf codec. Its update_playing_time() derives elapsed time as
(offset - first_frame_offset) * 8 / id3->bitrate, but the streaming shim
(rbcodec_open_stream) never sets id3->bitrate, so bitrate == 0 → integer
divide-by-zero → WASM "RuntimeError: divide by zero", killing playback of any
faststart-AAC track (and raw AAC radio) with a "stream error".

Guard the division: when bitrate is unknown (0) leave the elapsed indicator
untouched — the host tracks position from decoded PCM. Fix applied to both the
firmware source and the vendored rockbox-codecs copy.

Reproduced deterministically against the real failing track: without the guard,
the first decoded frame traps (bitrate=0, offset=935); with it, the whole file
decodes cleanly through the decode + DSP pipeline.

+17 -1
+1 -1
bindings/wasm/package.json
··· 1 1 { 2 2 "name": "rockbox-wasm", 3 - "version": "0.1.7", 3 + "version": "0.1.8", 4 4 "description": "Rockbox audio decoders + DSP compiled to WebAssembly — a batteries-included browser player (FLAC/MP3/Vorbis/Opus/ALAC/AAC/WavPack/…, 10-band parametric EQ, live internet radio) with the wasm bundled in.", 5 5 "license": "GPL-2.0-or-later", 6 6 "author": "Tsiry Sandratraina",
+8
crates/rockbox-codecs/vendor/lib/rbcodec/codecs/aac_bsf.c
··· 35 35 36 36 static void update_playing_time(void) 37 37 { 38 + /* Deriving elapsed time from the byte offset needs a known bitrate. When 39 + * this codec is fed a container-less ADTS stream (e.g. an M4A re-framed to 40 + * ADTS on the fly, or raw AAC radio), the metadata carries no bitrate, so 41 + * id3->bitrate is 0 — dividing by it would trap (integer divide-by-zero). 42 + * In that case leave the elapsed indicator untouched; the host tracks 43 + * position from the decoded PCM instead. */ 44 + if (ci->id3->bitrate <= 0) 45 + return; 38 46 ci->set_elapsed((unsigned long)((ci->id3->offset - ci->id3->first_frame_offset) * 8LL / ci->id3->bitrate)); 39 47 } 40 48
+8
lib/rbcodec/codecs/aac_bsf.c
··· 34 34 35 35 static void update_playing_time(void) 36 36 { 37 + /* Deriving elapsed time from the byte offset needs a known bitrate. When 38 + * this codec is fed a container-less ADTS stream (e.g. an M4A re-framed to 39 + * ADTS on the fly, or raw AAC radio), the metadata carries no bitrate, so 40 + * id3->bitrate is 0 — dividing by it would trap (integer divide-by-zero). 41 + * In that case leave the elapsed indicator untouched; the host tracks 42 + * position from the decoded PCM instead. */ 43 + if (ci->id3->bitrate <= 0) 44 + return; 37 45 ci->set_elapsed((unsigned long)((ci->id3->offset - ci->id3->first_frame_offset) * 8LL / ci->id3->bitrate)); 38 46 } 39 47