FLAC
How musefs scans and synthesizes native FLAC files (.flac). FLAC inside an
Ogg container is a different beast — see Ogg. For the segment
model these layouts plug into, see
the segment model.
What round-trips
- All text tags. Canonical keys (
title,artist,albumartist,date,tracknumber, …) map to their conventional Vorbis field names via the shared vocabulary (musefs-format/src/tagmap.rs); any other field round-trips verbatim by its own name. Multi-value fields keep their order. User-defined keys that are not legal Vorbis field names (empty, containing=, control characters, or non-ASCII bytes — i.e. outside ASCII0x20–0x7Dminus=) are dropped on synthesis and logged; they cannot round-trip by name. - Binary metadata blocks.
APPLICATIONandCUESHEETblocks are captured at scan time as binary tags (anAPPLICATIONpayload includes its 4-byte application id) and re-emitted on synthesis, streamed from the DB rather than held in memory. - Embedded pictures. Each
PICTUREblock round-trips with its MIME type, picture type, description, and dimensions; image bytes are stored content-addressed and streamed at read time. - Structural blocks.
STREAMINFOandSEEKTABLEare preserved bit-exact. They are captured into the read-onlystructural_blocksstore at scan time (external tools must not edit them) and re-emitted on synthesis.
Leading ID3 tags
FLAC does not define an ID3 tag, but files that put one (or several) in front
of the fLaC marker exist in the wild — usually a blank header left behind by
a converter. musefs scans them rather than skipping them:
- The tag run is stepped over to find the
fLaCmarker, and the recorded audio offset counts it, so the audio segment still reads the right range out of the backing file. A tag is stepped over by its declared size, whatever its version: the ID3v2 header has the same shape in every version, and the spec's own rule for a version a reader does not understand is to ignore the tag. A header musefs cannot parse the frames of is therefore still skipped correctly — only its contents go unread. What is required is that the header matches the spec's detection pattern ($49 44 33 yy yy xx zz zz zz zz, both version bytes below$FF, every size byte below$80) and that its declared length lands where the next thing in the file starts — the following ID3v2 header, or thefLaCmarker for the last tag in the run. A header that fails either test contradicts the file it is in, and the file is skipped rather than guessed at. - The tag's text frames and
APICpictures are ingested as a fallback: the FLAC's ownVORBIS_COMMENT/PICTUREblocks win, and the ID3 tag only supplies keys the FLAC does not define. The rule is all-or-nothing per key, so a multi-value field never mixes values from both sources. A file whose tags live only in the ID3 header is therefore still ingested with its tags. - A 128-byte trailing ID3v1 tag is trimmed from the audio length, so it is not
served as audio. This check runs only for files that carry a leading ID3v2
tag: a stock FLAC pays no extra read, and audio that happens to spell
TAG128 bytes from the end is never mistaken for a trailer. - Neither tag survives into the synthesized file — see the lossy edge below.
Lossy edges
- A leading ID3v2 tag is not preserved: it is metadata, and the synthesized
file is regenerated metadata in front of untouched audio. Its contents are
ingested first (above), so they come back as Vorbis comments and
PICTUREblocks — the served file is a stock FLAC that starts atfLaC. This matches how MP3's original ID3v2 tag is treated. - A trailing ID3v1 tag is dropped without being read. Unlike the leading tag, its fields are never parsed into tags — it is only excluded from the audio length so its 128 bytes are not served as audio. This mirrors MP3, where ID3v1 is likewise not read; populate those tags through the store instead.
PADDINGblocks are dropped — the synthesized file carries no padding.- Metadata blocks of unknown/reserved types are dropped at scan time.
- A
PICTUREblock whose picture type falls outside the standard0–20range is clamped to0(Other) at scan time, matching the store'strack_art.picture_typeCHECK. This sharedPICTUREparser also serves FLAC-in-Ogg, so the same clamp applies there. - The
VORBIS_COMMENTvendor string is replaced with musefs's own. - Vorbis field names are case-insensitive by spec; musefs re-emits canonical
keys under their conventional uppercase names and upper-cases unknown
field names. A field stored as
MixedCasecomes back asMIXEDCASE— same field to a conforming reader, different bytes.
How synthesis works
flac::synthesize_layout (musefs-format/src/flac.rs) builds the layout in
this order — an inline metadata region, DB-streamed payloads, then the
untouched audio:
offset 0
┌──────────────────────────────────────────────┐ ┐
│ █ "fLaC" marker (Inline) │ │
│ █ STREAMINFO / SEEKTABLE, bit-exact (Inline) │ │ generated
│ █ VORBIS_COMMENT rebuilt from DB (Inline) │ │ metadata
│ ▒ APPLICATION / CUESHEET bodies (BinaryTag) │ │ region
│ █ PICTURE framing + ▒ image bytes (ArtImage) │ │
├──────────────────────────────────────────────┤ ┘
│ ░ audio frames, verbatim (BackingAudio) │
└──────────────────────────────────────────────┘
EOF █ inline-generated ▒ DB-streamed ░ untouched backing
Inline— thefLaCmarker plus the preserved structural blocks (STREAMINFO,SEEKTABLE, sorted by block type) and aVORBIS_COMMENTblock regenerated entirely from the DB tag rows.BinaryTag— one segment per storedAPPLICATION/CUESHEETblock, streamed from the DB at read time.ArtImage— onePICTUREblock per linked art row; the block framing is inline, the image bytes stream from the blob store.BackingAudio— the original audio frames, served by positioned reads at the storedaudio_offset/audio_length.
Structural blocks normally come from the structural_blocks store. A
database scanned before that store existed has no rows there; synthesis then
falls back to re-reading the file's front for every preserved block
(carrying APPLICATION/CUESHEET inline and suppressing the streamed
binary tags so nothing is emitted twice). A re-scan upgrades the track to
the streamed path.
Quirks & invariants
- The audio frames are never touched: the backing segment starts exactly at
the scanned audio offset, and the byte-identical-audio property is asserted
by
musefs-format/tests/proptest_flac.rsand the mutagen interop suite (musefs-core/tests/interop_emit.rs). - Synthesis re-parses its own inline output in tests
(
flac_tag_roundtrip_is_stable): the regenerated front must be a valid FLAC metadata region whose computed audio boundary equals the layout's header length. - Block-body sizes are bounded at parse time (
MAX_BLOCK_BODY); a crafted file cannot force a huge allocation. - The parser now rejects (at scan and synthesis) any FLAC whose metadata does not begin with exactly one 34-byte STREAMINFO block; a crafted store providing malformed structural rows fails synthesis with a controlled error rather than emitting decoder-rejected output.