-
Notifications
You must be signed in to change notification settings - Fork 0
Format
File type is always detected by content (a 2-byte magic), never by
extension — a .pm3 archive renamed to anything else still decodes.
This is what -k1 (the default) produces: one archive = one serial
arithmetic-coded stream.
byte 0-1 magic "MS"
byte 2 version byte (appversion, e.g. 20 = v2.0)
... header (MPEG version/channels/bitrate flags, frame count)
... arithmetic-coded: ID3/metadata, padding, block types,
scalefactors, side info, and the main spectral data
(Huffman big/small values re-coded with adaptive models)
Because it's one continuous arithmetic stream, decoding is inherently
sequential — frame N's decode depends on the coder state left by
frame N-1. This is what makes a single -k1 archive single-threaded.
This is what -k<n> for n > 1 produces: the source file is split at
MP3 frame boundaries into n independent byte ranges, each compressed
as its own self-contained "MS" sub-archive (its own arithmetic stream,
its own model state starting fresh). The container just concatenates
them with an index:
byte 0-1 magic "MK"
byte 2 version byte
byte 3 chunk count N
byte 4.. N x 4-byte little-endian chunk sizes
... N concatenated "MS" sub-archives, back to back
Because each chunk is a fully independent "MS" stream, chunks can be
encoded and decoded on separate threads with no shared state. list
detects "MK" and reports the aggregate (frames/format/channels/rate
summed or checked for consistency across chunks, plus the chunk count).
MP3 Layer III has a bit reservoir — a frame's spectral data can
borrow reserve bits from the physical space of previous frames. When a
chunk boundary falls where a frame would normally borrow from data
that's now in a different chunk, that frame is reconstructed through
the same "bad first frame" recovery path packMP3 already uses for
genuinely damaged real-world files (still 100% lossless, just slightly
less efficient for that frame). This — plus each chunk's model
statistics restarting from zero — is the entire cost of -k. See
Benchmarks for the measured trade-off.
- The version byte in the header is a single number:
v{n/10}.{n%10}(e.g.20→v2.0). - Archives are only guaranteed compatible within the same main
version. v2.0 changed the entropy models and format entirely — v1.x
.pmparchives are not decodable by v2.0 and vice versa. Trying to decompress an incompatible archive gives a clean error, never garbage output. - A sub-version string (when present, e.g.
v1.0g) marks smaller, format-compatible changes within the same main version.