From a3b59fcc7b6fe9f164c6f25ba6b83dd3887b0970 Mon Sep 17 00:00:00 2001 From: Davis Vann Bennett Date: Thu, 22 Oct 2026 00:26:06 +0200 Subject: [PATCH] =?UTF-8?q?feat(ir):=20virtualize=20MP3=20files=20through?= =?UTF-8?q?=20the=20Rust=20IR,=20as=20the=20MP3=20profile=20(=C2=A716)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the MP3 profile (spec/virtualize/mp3.md, §16 of spec/virtualize.md): an MPEG-1, MPEG-2 or MPEG-2.5 Layer III file, chosen by `ID3` or a frame header at byte 0, becomes a plain Zarr array `samples` of int16 [time, channel], the first non-image convention. The parser reads the whole file, walks the frames (a chain from each frame's end, a confirmed resync after junk), finds the ID3v2, ID3v1 and APE tags and the Xing, Info or VBRI frame, and rejects Layers I and II, free format and a stream whose parameters change. Each chunk is 256 frames, referenced with a 4-byte sample count and a lead-in: the two frames before the chunk and the fewest before them holding the version's largest bit reservoir, so that a decoder decoding the chunk's bytes in one pass gives the stream's samples; the bytes between frames are left out of the ranges. The root keeps the stream's parameters, the info frame's LAME fields and the ID3v1 tag; refkv_source is the file's IR mirror. The `mp3` Zarr codec (python/src/refkv/zarr/codecs.py) decodes a chunk with miniaudio, the new `audio` extra, keeping the last `keep` samples. Fixtures (fixtures/mp3, 21 accepted and 12 rejected, encoded by LAME and ffmpeg, with ffmpeg's samples as expected values) are checked by python/tests/ir/test_mp3.py (chunked decoding equals miniaudio's sequential decoding exactly, and ffmpeg's within rounding) and js/test/mp3/verify.py; the generator needs lame and ffmpeg, so `just fixtures` skips it as it does NDPI's. corpus_mp3.txt lists a LibriVox recording. Assisted-by: ClaudeCode:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 --- conformance/virtualize/HARNESS.md | 8 +- conformance/virtualize/compare.py | 4 +- conformance/virtualize/corpus_mp3.txt | 5 + demo/index.html | 2 +- docs/virtualize/README.md | 10 +- docs/virtualize/mp3/README.md | 161 +++++ fixtures/generators/mp3/write_fixtures.py | 301 +++++++++ fixtures/mp3/expected/mp3_abr_xing.npy | Bin 0 -> 25472 bytes fixtures/mp3/expected/mp3_crc_mixed.npy | Bin 0 -> 57728 bytes fixtures/mp3/expected/mp3_info_lavc.npy | Bin 0 -> 25472 bytes fixtures/mp3/expected/mp3_mpeg1_mono_vbr.npy | Bin 0 -> 48512 bytes .../mp3/expected/mp3_mpeg1_stereo_cbr.npy | Bin 0 -> 78464 bytes fixtures/mp3/expected/mp3_mpeg25_mono_8k.npy | Bin 0 -> 18560 bytes fixtures/mp3/expected/mp3_mpeg2_mono_16k.npy | Bin 0 -> 25472 bytes .../mp3/expected/mp3_mpeg2_mono_nores.npy | Bin 0 -> 25472 bytes .../mp3/expected/mp3_mpeg2_stereo_crc.npy | Bin 0 -> 57728 bytes fixtures/mp3/mp3_abr_xing.mp3 | Bin 0 -> 4320 bytes fixtures/mp3/mp3_crc_mixed.mp3 | Bin 0 -> 3918 bytes fixtures/mp3/mp3_id3v1_after_truncated.mp3 | Bin 0 -> 3224 bytes fixtures/mp3/mp3_id3v2_footer.mp3 | Bin 0 -> 3228 bytes fixtures/mp3/mp3_id3v2_padding.mp3 | Bin 0 -> 3258 bytes fixtures/mp3/mp3_id3v2_twice.mp3 | Bin 0 -> 3228 bytes fixtures/mp3/mp3_info_lavc.mp3 | Bin 0 -> 3392 bytes fixtures/mp3/mp3_junk_between_frames.mp3 | Bin 0 -> 3303 bytes fixtures/mp3/mp3_junk_false_sync.mp3 | Bin 0 -> 3194 bytes fixtures/mp3/mp3_mpeg1_mono_vbr.mp3 | Bin 0 -> 5232 bytes fixtures/mp3/mp3_mpeg1_stereo_cbr.mp3 | Bin 0 -> 7105 bytes fixtures/mp3/mp3_mpeg25_long.mp3 | Bin 0 -> 24192 bytes fixtures/mp3/mp3_mpeg25_mono_8k.mp3 | Bin 0 -> 2304 bytes fixtures/mp3/mp3_mpeg2_mono_16k.mp3 | Bin 0 -> 3168 bytes fixtures/mp3/mp3_mpeg2_mono_nores.mp3 | Bin 0 -> 3168 bytes fixtures/mp3/mp3_mpeg2_stereo_crc.mp3 | Bin 0 -> 3918 bytes fixtures/mp3/mp3_reject_channels_change.mp3 | Bin 0 -> 5760 bytes fixtures/mp3/mp3_reject_free_format.mp3 | Bin 0 -> 1248 bytes fixtures/mp3/mp3_reject_id3v2_outside.mp3 | Bin 0 -> 60 bytes fixtures/mp3/mp3_reject_id3v2_syncsafe.mp3 | Bin 0 -> 60 bytes fixtures/mp3/mp3_reject_layer1.mp3 | Bin 0 -> 408 bytes fixtures/mp3/mp3_reject_layer2.mp3 | Bin 0 -> 2016 bytes fixtures/mp3/mp3_reject_layer_change.mp3 | Bin 0 -> 4320 bytes fixtures/mp3/mp3_reject_no_frames.mp3 | Bin 0 -> 242 bytes fixtures/mp3/mp3_reject_only_id3v1.mp3 | Bin 0 -> 128 bytes .../mp3/mp3_reject_sample_rate_change.mp3 | Bin 0 -> 4603 bytes fixtures/mp3/mp3_reject_short.mp3 | 1 + fixtures/mp3/mp3_reject_version_change.mp3 | Bin 0 -> 5544 bytes fixtures/mp3/mp3_single_frame.mp3 | Bin 0 -> 144 bytes fixtures/mp3/mp3_tags_ape.mp3 | Bin 0 -> 3280 bytes fixtures/mp3/mp3_tags_ape_id3v1.mp3 | Bin 0 -> 3351 bytes fixtures/mp3/mp3_tags_id3v1_only.mp3 | Bin 0 -> 3296 bytes fixtures/mp3/mp3_tags_id3v2_id3v1.mp3 | Bin 0 -> 3565 bytes fixtures/mp3/mp3_truncated_last_frame.mp3 | Bin 0 -> 3096 bytes js/README.md | 17 +- js/src/virtualize/index.ts | 17 +- js/src/virtualize/ir/run.ts | 2 +- js/src/virtualize/profiles.ts | 3 +- js/test/mp3/verify.py | 112 ++++ justfile | 5 +- pyproject.toml | 2 +- python/pyproject.toml | 6 + python/src/lib.rs | 12 +- python/src/refkv/_extras.py | 2 + python/src/refkv/ir/__init__.py | 18 +- python/src/refkv/virtualize/profiles.py | 1 + python/src/refkv/zarr/__init__.py | 7 +- python/src/refkv/zarr/codecs.py | 63 +- python/tests/ir/test_mp3.py | 250 +++++++ python/tests/test_virtualize_refstore.py | 3 +- rust/refkv-ir/profiles.json | 15 + rust/refkv-ir/schema/mp3.json | 66 ++ rust/refkv-ir/src/lib.rs | 2 + rust/refkv-ir/src/mp3.rs | 503 ++++++++++++++ rust/refkv-ir/src/project/mod.rs | 2 + rust/refkv-ir/src/project/mp3.rs | 158 +++++ rust/refkv-ir/src/rules.rs | 6 + rust/refkv-ir/src/run.rs | 20 +- rust/refkv-ir/tests/parsers.rs | 13 + rust/refkv-ir/wasm/run.mjs | 2 + spec/TECHNIQUES.md | 1 + spec/conventions.md | 4 +- spec/generate_schemas.py | 79 +++ spec/virtualize.md | 9 +- spec/virtualize/mp3.md | 536 +++++++++++++++ spec/virtualize/mp3/schema.json | 616 ++++++++++++++++++ spec/virtualize/profiles.json | 15 + uv.lock | 135 +++- 84 files changed, 3160 insertions(+), 34 deletions(-) create mode 100644 conformance/virtualize/corpus_mp3.txt create mode 100644 docs/virtualize/mp3/README.md create mode 100644 fixtures/generators/mp3/write_fixtures.py create mode 100644 fixtures/mp3/expected/mp3_abr_xing.npy create mode 100644 fixtures/mp3/expected/mp3_crc_mixed.npy create mode 100644 fixtures/mp3/expected/mp3_info_lavc.npy create mode 100644 fixtures/mp3/expected/mp3_mpeg1_mono_vbr.npy create mode 100644 fixtures/mp3/expected/mp3_mpeg1_stereo_cbr.npy create mode 100644 fixtures/mp3/expected/mp3_mpeg25_mono_8k.npy create mode 100644 fixtures/mp3/expected/mp3_mpeg2_mono_16k.npy create mode 100644 fixtures/mp3/expected/mp3_mpeg2_mono_nores.npy create mode 100644 fixtures/mp3/expected/mp3_mpeg2_stereo_crc.npy create mode 100644 fixtures/mp3/mp3_abr_xing.mp3 create mode 100644 fixtures/mp3/mp3_crc_mixed.mp3 create mode 100644 fixtures/mp3/mp3_id3v1_after_truncated.mp3 create mode 100644 fixtures/mp3/mp3_id3v2_footer.mp3 create mode 100644 fixtures/mp3/mp3_id3v2_padding.mp3 create mode 100644 fixtures/mp3/mp3_id3v2_twice.mp3 create mode 100644 fixtures/mp3/mp3_info_lavc.mp3 create mode 100644 fixtures/mp3/mp3_junk_between_frames.mp3 create mode 100644 fixtures/mp3/mp3_junk_false_sync.mp3 create mode 100644 fixtures/mp3/mp3_mpeg1_mono_vbr.mp3 create mode 100644 fixtures/mp3/mp3_mpeg1_stereo_cbr.mp3 create mode 100644 fixtures/mp3/mp3_mpeg25_long.mp3 create mode 100644 fixtures/mp3/mp3_mpeg25_mono_8k.mp3 create mode 100644 fixtures/mp3/mp3_mpeg2_mono_16k.mp3 create mode 100644 fixtures/mp3/mp3_mpeg2_mono_nores.mp3 create mode 100644 fixtures/mp3/mp3_mpeg2_stereo_crc.mp3 create mode 100644 fixtures/mp3/mp3_reject_channels_change.mp3 create mode 100644 fixtures/mp3/mp3_reject_free_format.mp3 create mode 100644 fixtures/mp3/mp3_reject_id3v2_outside.mp3 create mode 100644 fixtures/mp3/mp3_reject_id3v2_syncsafe.mp3 create mode 100644 fixtures/mp3/mp3_reject_layer1.mp3 create mode 100644 fixtures/mp3/mp3_reject_layer2.mp3 create mode 100644 fixtures/mp3/mp3_reject_layer_change.mp3 create mode 100644 fixtures/mp3/mp3_reject_no_frames.mp3 create mode 100644 fixtures/mp3/mp3_reject_only_id3v1.mp3 create mode 100644 fixtures/mp3/mp3_reject_sample_rate_change.mp3 create mode 100644 fixtures/mp3/mp3_reject_short.mp3 create mode 100644 fixtures/mp3/mp3_reject_version_change.mp3 create mode 100644 fixtures/mp3/mp3_single_frame.mp3 create mode 100644 fixtures/mp3/mp3_tags_ape.mp3 create mode 100644 fixtures/mp3/mp3_tags_ape_id3v1.mp3 create mode 100644 fixtures/mp3/mp3_tags_id3v1_only.mp3 create mode 100644 fixtures/mp3/mp3_tags_id3v2_id3v1.mp3 create mode 100644 fixtures/mp3/mp3_truncated_last_frame.mp3 create mode 100644 js/test/mp3/verify.py create mode 100644 python/tests/ir/test_mp3.py create mode 100644 rust/refkv-ir/schema/mp3.json create mode 100644 rust/refkv-ir/src/mp3.rs create mode 100644 rust/refkv-ir/src/project/mp3.rs create mode 100644 spec/virtualize/mp3.md create mode 100644 spec/virtualize/mp3/schema.json diff --git a/conformance/virtualize/HARNESS.md b/conformance/virtualize/HARNESS.md index c3e7f79f..1b6ba84a 100644 --- a/conformance/virtualize/HARNESS.md +++ b/conformance/virtualize/HARNESS.md @@ -146,14 +146,14 @@ with the first's: files, and SAFE directories and Zarr v2, OME-Zarr and N5 stores, it runs the frozen Python profiles in `conformance/virtualize/reference/refkv_reference/` (what `refkv.virtualize` shipped before these formats moved to the IR, unchanged but for their import - paths); for every other profile, the shipped code. MRC and VSI were never - implemented outside the core, so they have no reference: their inputs - (`no-ref` in the corpus) compare `py` with `web` alone. + paths); for every other profile, the shipped code. MRC, VSI and MP3 were + never implemented outside the core, so they have no reference: their + inputs (`no-ref` in the corpus) compare `py` with `web` alone. - `py`: `python -m refkv.virtualize --allow-private-hosts`. - `web`: the browser code under Node, `js/conformance/virtualize.ts --allow-private-hosts`. -For TIFF (NDPI included), ND2, CZI, DICOM, NIfTI, MRC, IMS, VSI and SAFE files, and SAFE directories and Zarr v2, OME-Zarr and N5 stores, `py` and `web` are one implementation: the Rust core +For TIFF (NDPI included), ND2, CZI, DICOM, NIfTI, MRC, IMS, VSI, MP3 and SAFE files, and SAFE directories and Zarr v2, OME-Zarr and N5 stores, `py` and `web` are one implementation: the Rust core `rust/refkv-ir` (its parsers, schemas, read planner, projections and mirror), built natively for Python and as wasm32 for the browser, each with a thin host (the I/O, and the archive writer). Their `refkv_source` is the IR's mirror, diff --git a/conformance/virtualize/compare.py b/conformance/virtualize/compare.py index e0143a90..fb96c240 100644 --- a/conformance/virtualize/compare.py +++ b/conformance/virtualize/compare.py @@ -450,7 +450,7 @@ def check(item: tuple, impls: dict, out_dir: Path) -> dict: name, url = item[:2] if len(item) > 2 and item[2] == "py-only": # past the browser's limit: every implementation but web impls = {k: v for k, v in impls.items() if k != "web"} - if len(item) > 2 and item[2] == "no-ref": # a profile the frozen reference never had (MRC, VSI): py and web alone + if len(item) > 2 and item[2] == "no-ref": # a profile the frozen reference never had (MRC, VSI, MP3): py and web alone impls = {k: v for k, v in impls.items() if k != "ref"} results = {n: run(impl, url, out_dir / f"{name}.{n}.out") for n, impl in impls.items()} ref_name = next(iter(impls)) @@ -557,7 +557,7 @@ def corpus(proxy: Proxy, fixtures: Path, quick: bool, local_only: bool, large: b stores = store_fixtures(fixtures) files = [p for p in sorted(p for s in FILE_SUFFIXES for p in fixtures.rglob(f"*{s}")) if not any(p.is_relative_to(s) for s in stores)] - # a profile the frozen reference never had (MRC): its files compare py with web alone + # a profile the frozen reference never had (MRC, VSI, MP3): its files compare py with web alone items = [(f"fixture-{p.stem}", proxy.local(p.relative_to(fixtures).as_posix()), *(["no-ref"] if FILE_SUFFIXES[p.suffix]["reference"] is None else [])) for p in files] diff --git a/conformance/virtualize/corpus_mp3.txt b/conformance/virtualize/corpus_mp3.txt new file mode 100644 index 00000000..83b334ea --- /dev/null +++ b/conformance/virtualize/corpus_mp3.txt @@ -0,0 +1,5 @@ +# url|name|no-ref of the public MP3 files in the corpus (the frozen reference has no MP3 profile, so each +# compares py with web alone): a LibriVox recording on the Internet Archive (public domain): chapter 20 +# of "Public Opinion" by Walter Lippmann, MPEG-2 mono at 22.05 kHz, 64 kbps, with an Info frame and tags +# (archive.org redirects downloads to a mirror) +https://archive.org/download/public_opinion_1312_librivox/publicopinion_20_lippmann_64kb.mp3|librivox_lippmann_20|no-ref diff --git a/demo/index.html b/demo/index.html index 0b62e867..097e3d49 100644 --- a/demo/index.html +++ b/demo/index.html @@ -58,7 +58,7 @@

Image files to Zarr in the browser

Paste the URL of an image file, a Zarr or N5 store, or a .vzip archive. - TIFF, OME-TIFF, Aperio SVS, Hamamatsu NDPI, Nikon ND2, DICOM, NIfTI-1 and NIfTI-2, Imaris IMS, Zeiss CZI, MRC2014 and Olympus VSI files, N5, Zarr v2 and OME-Zarr 0.4 stores, and Sentinel-2 SAFE (Level-1C, Level-2A) products are supported; + TIFF, OME-TIFF, Aperio SVS, Hamamatsu NDPI, Nikon ND2, DICOM, NIfTI-1 and NIfTI-2, Imaris IMS, Zeiss CZI, MRC2014, Olympus VSI and MP3 (MPEG Layer III audio) files, N5, Zarr v2 and OME-Zarr 0.4 stores, and Sentinel-2 SAFE (Level-1C, Level-2A) products are supported; the format is detected from the file's first bytes, or the store's metadata. A service worker reads the input's structure with a few range diff --git a/docs/virtualize/README.md b/docs/virtualize/README.md index d07124a0..37186c85 100644 --- a/docs/virtualize/README.md +++ b/docs/virtualize/README.md @@ -32,6 +32,7 @@ who each one is for, what you get, and how to run it. | CZI | Zeiss CZI files | [convention](../../spec/virtualize/czi.md) | [§13](../../spec/virtualize/czi.md#part-2-the-profile) | | MRC | MRC2014 maps, image stacks, volumes and volume stacks (`.mrc`, `.map`) | [mrc](mrc/README.md) | [§14](../../spec/virtualize/mrc.md#part-2-the-profile) | | VSI | Olympus cellSens whole-slide images (`.vsi` with its tile files) | [vsi](vsi/README.md) | [§15](../../spec/virtualize/vsi.md#part-2-the-profile) | +| MP3 | MP3 audio files, as an array of samples (`.mp3`) | [mp3](mp3/README.md) | [§16](../../spec/virtualize/mp3.md#part-2-the-profile) | A format that reads a file takes a URL, or a local path. One that reads a @@ -39,7 +40,9 @@ store takes a URL ending in `/` that answers the S3 `ListObjectsV2` operation anonymously, such as a public S3 bucket. SAFE reads either: a product's `.SAFE` directory as a store, or its `.SAFE.zip` as a file. VSI is named by its `.vsi` file and reads the tile files beside it by name, without listing -the directory. +the directory. MP3 is the one format that is not an image: its archive holds +a plain Zarr array of audio samples, decoded from the file's frames when a +chunk is read ([mp3](mp3/README.md)). SAFE and CZI have no user-story page yet; their conventions describe the output. A Sentinel-2 product becomes a GeoZarr hierarchy (one group per @@ -234,6 +237,11 @@ each format's metadata is: metadata tree as JSON, the list of stacks and the file's size; each image keeps its stack's properties (scale, origin, channels, creation time, magnification) and its tile file's headers. +- **MP3:** the IR mirror on `refkv_source`: the ID3v2 tags, the Xing or + Info frame, every audio frame, and the ID3v1 and APE tags, so that the + file is rebuilt from the archive. The root keeps the stream's parameters + (version, sample rate, channels, frames, bitrate), the info frame's + counts and LAME fields, and the ID3v1 tag's fields. - **N5, Zarr v2 and OME-Zarr:** each node's own attributes and the layout members its `zarr.json` does not reproduce, on the node, as `{"attributes": ..., "metadata": ...}` (with `"unversioned"` for an diff --git a/docs/virtualize/mp3/README.md b/docs/virtualize/mp3/README.md new file mode 100644 index 00000000..b7695a8d --- /dev/null +++ b/docs/virtualize/mp3/README.md @@ -0,0 +1,161 @@ +# MP3 + +refkv turns a file into a Zarr dataset by writing a small archive of +references to the file's bytes, without copying its content +([overview](../README.md)). This page is about MP3 files: the one format +refkv virtualizes that is not an image. + +## Who this is for + +MP3 (`.mp3`: MPEG-1, MPEG-2 and MPEG-2.5 Layer III audio) is how a great +deal of recorded sound is stored and shared: speech corpora, field +recordings, podcasts, audiobooks, music. Someone who wants to read a +minute of a long recording lazily over HTTP as a NumPy array, put a +collection of recordings next to other arrays in a Zarr store, or run an +array pipeline over audio without first decoding every file to PCM on disk +has to convert it today. + +An MP3 file is a sequence of frames, each decoding to 1152 (MPEG-1) or 576 +samples per channel, with tags before and after them. refkv reads the file +once, finds every frame, and writes an archive in which every Zarr chunk is +a run of 256 frames, referenced together with the few frames before it that +a decoder needs (MP3 frames borrow bits from their predecessors). The +archive's `mp3` codec decodes a chunk when it is read, so the samples are +never stored: they stay in the file as MPEG frames. + +## What you get + +A group at the archive root with one array, `samples`. + +- **Shape:** `[samples, channels]`, with the dimension names `time` and + `channel`: one row per sample, one column per channel (1 or 2). +- **Data type:** `int16`, the decoder's 16-bit output. The array holds + every sample the frames decode to, the encoder's delay and padding + included (their counts are in the metadata, for a reader that wants to + trim them, as players do). +- **Chunks:** 256 frames each (294912 samples for MPEG-1, 147456 for + MPEG-2 and 2.5; 6.7 seconds at 44.1 kHz, 6.7 at 22.05), the last one + shorter. Reading a chunk reads its frames and a few before them (the + bit reservoir) in one request, and decodes them in one pass. +- **Codecs:** `mp3`, which refkv's `zarr` module registers and which + decodes with miniaudio (the `audio` extra). No other codec. +- **Metadata:** under `refkv_virtualized.mp3` on the root: the stream's + version, sample rate, channel count and mode, frame and sample counts, + duration and bitrate (constant or variable), whether frames carry CRCs; + the Xing or Info frame's frame and byte counts, encoder (`LAME3.99r`), + delay and padding; the ID3v2 tags' versions and sizes; the ID3v1 tag's + title, artist, album, year, comment, track and genre; an APE tag's + version and item count. The whole file (the tags, the info frame, every + frame and any bytes between them) is described on `refkv_source` by the + Rust core's IR mirror, from which it is rebuilt byte for byte. +- **No `ome` metadata:** the hierarchy is not an image, so OME-Zarr + viewers do not open it; zarr-python, xarray and any Zarr v3 reader with + the codec do. + +**What is not decoded.** The ID3v2 tag's frames (title, cover art, lyrics) +and an APE tag's items are kept whole in the mirror, not translated; the +samples a decoder gives are not bit-exact across decoders (the standards +allow a difference of a few units); a stream whose frames borrow bits from +frames that are not there (two files joined) decodes as the reader's +decoder has it. [spec/virtualize/mp3.md §7](../../../spec/virtualize/mp3.md#7-what-the-layout-does-not-express) +lists them. + +## Try it + +A LibriVox recording from the Internet Archive (chapter 20 of Walter +Lippmann's *Public Opinion*, public domain, 3.9 MB), from +[corpus_mp3.txt](../../../conformance/virtualize/corpus_mp3.txt): + +```bash +uv run python -m refkv.virtualize https://archive.org/download/public_opinion_1312_librivox/publicopinion_20_lippmann_64kb.mp3 lippmann_20.vzip +``` + +``` +{"format": "mp3", "version": "MPEG-2", "sampleRate": 22050, "channels": 1, "frames": 18576, "samples": 10699776, "duration": 485.250612244898, "bitrate": 64, "chunkFrames": 256, "chunks": 73, "info": "Info", "tags": ["id3v2", "id3v1"], "strayBytes": 0, ...} +``` + +The archive is 17 KB: 73 chunk references and the mirror's table of 18576 +frames. Read the recording: + +```python +import zarr +import refkv.zarr + +g = zarr.open_group(refkv.zarr.open("lippmann_20.vzip"), mode="r") +m = g.attrs["refkv_virtualized"]["mp3"] +print({k: m[k] for k in ("version", "sample_rate", "channels", "duration")}) +print(m["info"]) +print(m["id3v1"]) +a = g["samples"] +print(a.shape, a.dtype, a.chunks) +print(a[22050 * 60:22050 * 60 + 8, 0]) +``` + +``` +{'version': 'MPEG-2', 'sample_rate': 22050, 'channels': 1, 'duration': 485.250612244898} +{'tag': 'Info', 'frames': 18576, 'bytes': 3882212, 'quality': 57, 'encoder': 'LAME3.99r', 'delay': 576, 'padding': 1128} +{'title': '20 - A New Image', 'artist': 'Walter Lippmann', 'album': 'Public Opinion', 'year': '', 'comment': 'http://archive.org/details/p', 'track': 20, 'genre': 101} +(10699776, 1) int16 (147456, 1) +[11 -2 6 2 1 15 20 19] +``` + +The last line reads the samples one minute in: one request for the chunk's +frames (about 54 KB), decoded on the fly. The same samples, as +`ffmpeg -i publicopinion_20_lippmann_64kb.mp3 -f s16le -` gives them after +its gapless trimming, start `delay + 529` samples later in its output. + +**In the browser.** The service worker serves a virtualized MP3 as a Zarr +hierarchy like any other; the demo page does not display audio. + +## Supported and not supported + +Supported: + +- MPEG-1, MPEG-2 and MPEG-2.5 Layer III streams, mono and stereo (joint, + dual channel), constant and variable bitrates, with or without CRCs, + with or without the bit reservoir. +- Xing, Info and VBRI frames (read, not counted as audio), LAME tags, + ID3v2 tags (several, with footers), ID3v1 and APE tags. +- Junk between frames, a truncated last frame and bytes after the last + frame: skipped, kept in the mirror, counted in `stray_bytes`. + +Rejected: + +- Layer I and Layer II streams (`MPEG-2 Layer II (the frame at 0) is not + supported: only Layer III is`), and free-format bitrates. +- A stream whose frames change version, sample rate or channel count + (`the frame at 2016 changes the sample rate from 16000 to 22050`): two + files concatenated, for instance. +- A file with no audio frames, and an ID3v2 tag that runs past the file + or whose size is not syncsafe. + +## Performance + +- Virtualizing reads the whole file (an MP3 has no index), in one or a few + large range requests after one request for the size. The 3.9 MB file + above takes under a second over HTTP. +- Reading a chunk is one request of the chunk's frames and their lead-in + (two frames, plus the fewest frames holding 511 bytes of main data for + MPEG-1 or 255 for MPEG-2: about 3 to 8 frames, a few percent of the + chunk), then decoding them. +- The archive has one entry per chunk, and the mirror's table has a row + per frame, folded into one run when the frames are all of one length + (the file above: 17 KB in all), a few bytes per frame otherwise. + +## How it's verified + +`js/test/mp3/verify.py` virtualizes the synthetic MP3 files (including +inputs to reject) with the browser code, reads them back through +`python/src/refkv`, zarr-python and the `mp3` codec, and compares every +sample with miniaudio's decoding of the whole stream (exactly) and with +ffmpeg's (within a few units, where the generator stored it). +`python/tests/ir/test_mp3.py` does the same through Python, with chunks of +4 frames so that every file has several chunks and lead-ins. `compare.py` +checks that the Python and browser outputs are equivalent on those files +and on the public file of +[corpus_mp3.txt](../../../conformance/virtualize/corpus_mp3.txt). + +- Profile: [spec/virtualize/mp3.md](../../../spec/virtualize/mp3.md#part-2-the-profile) +- Rust core: [rust/refkv-ir/src/mp3.rs](../../../rust/refkv-ir/src/mp3.rs) +- Codec: [python/src/refkv/zarr/codecs.py](../../../python/src/refkv/zarr/codecs.py) +- Fixtures: [fixtures/mp3/](../../../fixtures/mp3/) diff --git a/fixtures/generators/mp3/write_fixtures.py b/fixtures/generators/mp3/write_fixtures.py new file mode 100644 index 00000000..9286c761 --- /dev/null +++ b/fixtures/generators/mp3/write_fixtures.py @@ -0,0 +1,301 @@ +"""Writes synthetic MP3 files to fixtures/mp3/, covering the rules of the MP3 profile +(spec/virtualize/mp3.md §16 +): MPEG-1, MPEG-2 +and MPEG-2.5 streams, mono and stereo, constant and variable bitrates, CRC protection, the bit +reservoir on and off, Xing, Info and LAME tags, ID3v2, ID3v1 and APE tags, junk between and +around frames, a truncated last frame, and the inputs the profile rejects (`mp3_reject_*`). + +The audio is a deterministic signal (tones, a sweep and seeded noise, so that frames use the +bit reservoir) encoded by LAME (`lame`, with ffmpeg's libmp3lame for one file, and ffmpeg's +Layer II encoder for a rejected one): both must be on PATH. Some files are then edited byte by +byte (tags added, frames cut, junk inserted). For each accepted file without junk, the +expected samples are ffmpeg's decoding of its audio frames (an independent decoder) in +`fixtures/mp3/expected/.npy`, int16 of shape [samples, channels]; the tests compare +the virtualized array with them within a small tolerance, and with miniaudio's sequential +decoding (the codec's own decoder) exactly. The files with junk have no expected samples: +decoders differ on what they do after junk. + +`just fixtures` does not run this generator (it needs lame and ffmpeg, as NDPI's needs the +network): `just fixtures-of mp3` does. + +Usage: uv run python fixtures/generators/mp3/write_fixtures.py +""" + +from __future__ import annotations + +import shutil +import subprocess +import sys +from pathlib import Path + +import numpy as np + +OUT = Path(__file__).parents[2] / "mp3" +EXPECTED = OUT / "expected" + +# MPEG audio frame headers (spec/virtualize/mp3.md §2 +# ): version bits -> +# name; sample rates by version then index; Layer III bitrates (kbps) by version then index. +VERSIONS = {0: "MPEG-2.5", 2: "MPEG-2", 3: "MPEG-1"} +RATES = {3: (44100, 48000, 32000), 2: (22050, 24000, 16000), 0: (11025, 12000, 8000)} +BITRATES = { + 3: (0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320), + 2: (0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160), +} +BITRATES[0] = BITRATES[2] + + +def header(b: bytes) -> dict | None: + """The fields of a Layer III frame header, or None when `b` does not start with one (a sync, + a version that is not reserved, Layer III, a bitrate index from 1 to 14, a sample rate + index from 0 to 2).""" + if len(b) < 4 or b[0] != 0xFF or b[1] & 0xE0 != 0xE0: + return None + version, layer = (b[1] >> 3) & 3, (b[1] >> 1) & 3 + bitrate, rate, padding = b[2] >> 4, (b[2] >> 2) & 3, (b[2] >> 1) & 1 + if version == 1 or layer != 1 or bitrate in (0, 15) or rate == 3: + return None + crc = not b[1] & 1 + mode = b[3] >> 6 + channels = 1 if mode == 3 else 2 + kbps, sr = BITRATES[version][bitrate], RATES[version][rate] + per = 144 if version == 3 else 72 + length = per * kbps * 1000 // sr + padding + side = (17 if channels == 1 else 32) if version == 3 else (9 if channels == 1 else 17) + return {"version": version, "rate": sr, "channels": channels, "crc": crc, "length": length, + "side": side, "kbps": kbps, "mode": mode} + + +def id3v2_size(data: bytes, at: int = 0) -> int: + """The whole size of the ID3v2 tag at `at`, footer included, or 0 if there is none.""" + if data[at:at + 3] != b"ID3" or len(data) < at + 10: + return 0 + size = 0 + for c in data[at + 6:at + 10]: + size = size << 7 | (c & 0x7F) + return 10 + size + (10 if data[at + 5] & 0x10 else 0) + + +def frames_of(data: bytes) -> list[tuple[int, int, dict]]: + """The chain of frames of an encoder's output: (offset, length, header) of each, from the + first header after the ID3v2 tags, until the chain breaks or the file ends.""" + p = 0 + while (n := id3v2_size(data, p)): + p += n + out = [] + while (h := header(data[p:p + 4])) and p + h["length"] <= len(data): + out.append((p, h["length"], h)) + p += h["length"] + return out + + +def is_info(data: bytes, offset: int, h: dict) -> bool: + """Whether the frame at `offset` is a Xing, Info or VBRI frame (§2).""" + tag = offset + 4 + (2 if h["crc"] else 0) + h["side"] + return data[tag:tag + 4] in (b"Xing", b"Info") or data[offset + 36:offset + 40] == b"VBRI" + + +def audio_region(data: bytes) -> tuple[int, int, int]: + """(start, end, channels) of the audio frames: the chain's frames after an info frame.""" + frames = frames_of(data) + if not frames: + raise ValueError("no frames") + if is_info(data, frames[0][0], frames[0][2]): + frames = frames[1:] + return frames[0][0], frames[-1][0] + frames[-1][1], frames[0][2]["channels"] + + +# ---- signals and encoders + +def signal(rate: int, seconds: float, channels: int, seed: int) -> np.ndarray: + """Deterministic audio: a tone, a sweep and noise per channel (int16, [samples, channels]).""" + n = int(rate * seconds) + t = np.arange(n) / rate + rng = np.random.default_rng(seed) + out = np.zeros((n, channels), dtype=np.float64) + for c in range(channels): + f0 = 330.0 * (c + 1) + sweep = np.sin(2 * np.pi * (f0 * t + (rate / 8) * t * t / (2 * seconds))) + tone = np.sin(2 * np.pi * (f0 * 3.5) * t + c) + noise = rng.standard_normal(n) + out[:, c] = 9000 * sweep + 6000 * tone + 2500 * noise + return np.clip(out, -32768, 32767).astype(" bytes: + """LAME's encoding of raw little-endian int16 `pcm` at `rate` Hz with `args`.""" + channels = pcm.shape[1] + raw = Path(f"_{name or 'in'}.raw") + out = Path(f"_{name or 'out'}.mp3") + raw.write_bytes(pcm.tobytes()) + cmd = ["lame", "-r", "-s", f"{rate / 1000:g}", "--bitwidth", "16", "--signed", "--little-endian", + "-m", "m" if channels == 1 else "j", "--quiet", "--noreplaygain", *args, str(raw), str(out)] + subprocess.run(cmd, check=True) + data = out.read_bytes() + raw.unlink() + out.unlink() + return data + + +def ffmpeg_encode(pcm: np.ndarray, rate: int, codec: str, kbps: int) -> bytes: + """ffmpeg's encoding of `pcm` with `codec` (libmp3lame writes an ID3v2 tag and an Info + frame with a Lavc LAME tag, the frame only to a file it can seek back in; mp2 is Layer II).""" + out = Path("_ffmpeg.mp3") + cmd = ["ffmpeg", "-v", "error", "-y", "-f", "s16le", "-ar", str(rate), "-ac", str(pcm.shape[1]), "-i", "pipe:", + "-c:a", codec, "-b:a", f"{kbps}k", "-f", "mp3" if codec == "libmp3lame" else "mp2", str(out)] + subprocess.run(cmd, input=pcm.tobytes(), capture_output=True, check=True) + data = out.read_bytes() + out.unlink() + return data + + +def ffmpeg_decode(audio: bytes, channels: int) -> np.ndarray: + """ffmpeg's decoding of a run of MPEG audio frames (no tags: nothing is trimmed) to int16.""" + cmd = ["ffmpeg", "-v", "error", "-f", "mp3", "-i", "pipe:", "-f", "s16le", "-c:a", "pcm_s16le", "pipe:"] + pcm = subprocess.run(cmd, input=audio, capture_output=True, check=True).stdout + return np.frombuffer(pcm, dtype=" bytes: + return bytes([(n >> 21) & 0x7F, (n >> 14) & 0x7F, (n >> 7) & 0x7F, n & 0x7F]) + + +def id3v2(body: bytes, footer: bool = False, version: int = 4) -> bytes: + """An ID3v2 tag holding `body` (padding is fine), with a footer when asked.""" + flags = 0x10 if footer else 0 + tag = b"ID3" + bytes([version, 0, flags]) + syncsafe(len(body)) + body + if footer: + tag += b"3DI" + bytes([version, 0, flags]) + syncsafe(len(body)) + return tag + + +def id3v1(title: str, artist: str, album: str, year: str, comment: str, track: int, genre: int) -> bytes: + text = lambda s, n: s.encode("latin-1").ljust(n, b"\0")[:n] # noqa: E731 + return (b"TAG" + text(title, 30) + text(artist, 30) + text(album, 30) + text(year, 4) + + text(comment, 28) + bytes([0, track, genre])) + + +def ape(items: dict[str, str], with_header: bool = True) -> bytes: + """An APEv2 tag with a footer and, when asked, a header.""" + body = b"".join(len(v.encode()).to_bytes(4, "little") + bytes(4) + k.encode() + b"\0" + v.encode() + for k, v in items.items()) + size = len(body) + 32 + + def block(is_header: bool) -> bytes: + flags = (0x80000000 if with_header else 0) | (0x20000000 if is_header else 0) + return (b"APETAGEX" + (2000).to_bytes(4, "little") + size.to_bytes(4, "little") + + len(items).to_bytes(4, "little") + flags.to_bytes(4, "little") + bytes(8)) + + return (block(True) if with_header else b"") + body + block(False) + + +def raw_header(version: int, layer: int, bitrate: int, rate: int, channels: int, crc: bool = False, + padding: int = 0) -> bytes: + """A frame header from its fields (layer bits: 1 III, 2 II, 3 I).""" + b1 = 0xE0 | version << 3 | layer << 1 | (0 if crc else 1) + b2 = bitrate << 4 | rate << 2 | padding << 1 + b3 = (0xC0 if channels == 1 else 0x40) + return bytes([0xFF, b1, b2, b3]) + + +# ---- the files + +def write(name: str, data: bytes, expected: bool = True) -> None: + (OUT / f"{name}.mp3").write_bytes(data) + if expected and not name.startswith("mp3_reject"): + start, end, channels = audio_region(data) + np.save(EXPECTED / f"{name}.npy", ffmpeg_decode(data[start:end], channels)) + print(f"{name}.mp3: {len(data)} bytes") + + +def main() -> None: + for tool in ("lame", "ffmpeg"): + if shutil.which(tool) is None: + sys.exit(f"{tool} is not on PATH") + OUT.mkdir(exist_ok=True) + EXPECTED.mkdir(exist_ok=True) + for old in list(OUT.glob("*.mp3")) + list(EXPECTED.glob("*.npy")): + old.unlink() + + # MPEG-1 at 44.1 kHz: a stereo CBR stream without any tag, and a mono VBR one with LAME's + # Xing frame (its frames differ in length) + write("mp3_mpeg1_stereo_cbr", lame(signal(44100, 0.4, 2, 1), 44100, "-b", "128", "-t")) + write("mp3_mpeg1_mono_vbr", lame(signal(44100, 0.5, 1, 2), 44100, "-V", "5")) + # MPEG-2 at 22.05 and 16 kHz: CRC-protected stereo frames, and a mono stream whose encoder + # did not use the bit reservoir + crc = lame(signal(22050, 0.6, 2, 3), 22050, "-b", "48", "-p", "-t") + write("mp3_mpeg2_stereo_crc", crc) + write("mp3_mpeg2_mono_nores", lame(signal(16000, 0.7, 1, 4), 16000, "-b", "32", "--nores", "-t")) + # MPEG-2.5 at 8 kHz: a short mono stream, and a long one of more than 256 frames (the + # chunk size), whose expected samples would be large and which the tests decode themselves + mono8 = lame(signal(8000, 1.0, 1, 5), 8000, "-b", "16", "-t") + write("mp3_mpeg25_mono_8k", mono8) + write("mp3_mpeg25_long", lame(signal(8000, 24.0, 1, 6), 8000, "-b", "8", "-t"), expected=False) + # tags: LAME's ID3v2 and ID3v1, ID3v1 alone, an APE tag, ffmpeg's ID3v2 and Info frame, and + # LAME's ABR Xing frame + plain = lame(signal(16000, 0.7, 1, 7), 16000, "-b", "32", "-t") + write("mp3_mpeg2_mono_16k", plain) + text = ["--tt", "A title", "--ta", "An artist", "--tl", "An album", "--ty", "2021", "--tc", "Some comment", + "--tn", "7", "--tg", "Blues"] + # (the tag variants hold the frames of mp3_mpeg2_mono_16k, whose expected samples serve them) + write("mp3_tags_id3v2_id3v1", lame(signal(16000, 0.7, 1, 7), 16000, "-b", "32", "-t", "--add-id3v2", *text), + expected=False) + write("mp3_tags_id3v1_only", lame(signal(16000, 0.7, 1, 7), 16000, "-b", "32", "-t", "--id3v1-only", *text), + expected=False) + write("mp3_tags_ape", plain + ape({"Title": "Ape title", "Artist": "Ape artist"}), expected=False) + write("mp3_tags_ape_id3v1", plain + ape({"Title": "Ape title"}, with_header=False) + + id3v1("V1 title", "V1 artist", "V1 album", "1999", "comment", 3, 17), expected=False) + write("mp3_info_lavc", ffmpeg_encode(signal(16000, 0.7, 1, 8), 16000, "libmp3lame", 32)) + write("mp3_abr_xing", lame(signal(16000, 0.7, 1, 9), 16000, "--abr", "40")) + # hand-made ID3v2 tags: one with a footer, two in a row, and padding after the tag + write("mp3_id3v2_footer", id3v2(b"\0" * 40, footer=True) + plain, expected=False) + write("mp3_id3v2_twice", id3v2(b"\0" * 16, version=3) + id3v2(b"\0" * 24) + plain, expected=False) + write("mp3_id3v2_padding", id3v2(b"\0" * 16) + b"\0" * 64 + plain, expected=False) + # the frames alone: one frame (which ffmpeg does not decode from a pipe), and CRC-protected + # frames followed by plain ones, from two encodes of one signal without the bit reservoir + # (so that no frame reaches into the other encode's) + frames = frames_of(plain) + write("mp3_single_frame", plain[frames[0][0]:frames[0][0] + frames[0][1]], expected=False) + with_crc = lame(signal(22050, 0.6, 2, 3), 22050, "-b", "48", "-p", "--nores", "-t") + without = lame(signal(22050, 0.6, 2, 3), 22050, "-b", "48", "--nores", "-t") + crc_frames, plain_frames = frames_of(with_crc), frames_of(without) + mixed = b"".join(with_crc[o:o + n] for o, n, _ in crc_frames[:5]) + b"".join(without[o:o + n] for o, n, _ in plain_frames[5:]) + write("mp3_crc_mixed", mixed) + # junk: between frames, after the last frame, and a false sync (a header-like byte pair + # followed by garbage) between frames; a truncated last frame + o5, n5, _ = frames[5] + junk = bytes([0x00, 0x01, 0x02, 0x7F, 0x10]) * 7 + write("mp3_junk_between_frames", plain[:o5 + n5] + junk + plain[o5 + n5:] + b"\x55" * 100, expected=False) + false = b"\x00\x00" + raw_header(2, 1, 5, 2, 1) + b"\xaa" * 20 + write("mp3_junk_false_sync", plain[:o5 + n5] + false + plain[o5 + n5:], expected=False) + last_o, last_n, _ = frames[-1] + write("mp3_truncated_last_frame", plain[:last_o + last_n // 2], expected=False) + write("mp3_id3v1_after_truncated", plain[:last_o + last_n // 2] + id3v1("t", "a", "b", "2000", "c", 1, 2), + expected=False) + + # rejected: other layers, free format, a parameter change confirmed by the chain, no + # frames, and bad ID3v2 tags + write("mp3_reject_layer2", ffmpeg_encode(signal(16000, 0.5, 1, 10), 16000, "mp2", 32)) + layer1 = raw_header(3, 3, 4, 0, 2) # MPEG-1 Layer I, 128 kbps, 44.1 kHz: 12 * 128000 / 44100 * 4 = 136 bytes + write("mp3_reject_layer1", (layer1 + bytes(132)) * 3) + write("mp3_reject_free_format", (raw_header(3, 1, 0, 0, 2) + bytes(412)) * 3) + lo = lame(signal(16000, 0.5, 1, 11), 16000, "-b", "32", "-t") + hi = lame(signal(22050, 0.5, 1, 11), 22050, "-b", "32", "-t") + st = lame(signal(16000, 0.5, 2, 11), 16000, "-b", "48", "-t") + m1 = lame(signal(32000, 0.5, 1, 11), 32000, "-b", "48", "-t") + write("mp3_reject_sample_rate_change", lo + hi) + write("mp3_reject_channels_change", lo + st) + write("mp3_reject_version_change", lo + m1) + l2 = ffmpeg_encode(signal(16000, 0.5, 1, 10), 16000, "mp2", 32) + write("mp3_reject_layer_change", lo + l2) + write("mp3_reject_no_frames", id3v2(b"\0" * 32) + bytes(200)) + write("mp3_reject_only_id3v1", id3v1("t", "a", "b", "2000", "c", 1, 2)) + write("mp3_reject_id3v2_outside", b"ID3\x04\x00\x00" + syncsafe(100000) + bytes(50)) + write("mp3_reject_id3v2_syncsafe", b"ID3\x04\x00\x00" + bytes([0, 0, 0x80, 0]) + bytes(50)) + write("mp3_reject_short", b"ID3") + + +if __name__ == "__main__": + main() diff --git a/fixtures/mp3/expected/mp3_abr_xing.npy b/fixtures/mp3/expected/mp3_abr_xing.npy new file mode 100644 index 0000000000000000000000000000000000000000..5fd8f385f23b57c7c905ff444ba2d41e32040bef GIT binary patch literal 25472 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%0D?0({Ci7n?5EbHk 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 literal 0 HcmV?d00001 diff --git a/fixtures/mp3/expected/mp3_crc_mixed.npy b/fixtures/mp3/expected/mp3_crc_mixed.npy new file mode 100644 index 0000000000000000000000000000000000000000..f2f496a8a8812b630cfe9dc2984a1201d83bfbe5 GIT binary patch literal 57728 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 D9!Q5j literal 0 HcmV?d00001 diff --git a/fixtures/mp3/expected/mp3_mpeg1_mono_vbr.npy b/fixtures/mp3/expected/mp3_mpeg1_mono_vbr.npy new file mode 100644 index 0000000000000000000000000000000000000000..55501b969f75e7354e04aa815a181ef92ec26e8f GIT binary patch literal 48512 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

!CQj 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 QR|Egmz<)LH|7+lX0SQ>+mjD0& literal 0 HcmV?d00001 diff --git a/fixtures/mp3/expected/mp3_mpeg1_stereo_cbr.npy b/fixtures/mp3/expected/mp3_mpeg1_stereo_cbr.npy new file mode 100644 index 0000000000000000000000000000000000000000..90c28ef5d9d32603ca6ea5f18cf83ee8eb509bd3 GIT binary patch literal 78464 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%0DLR<$2ZD$j$M*h3FZLlwE`}s>8Wke@=Hrx1y0} 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 Y+Kr(wF}y>SSPlIL8GO| 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

Yg!f@gV;u?s{u!GstGSP(}G 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 literal 0 HcmV?d00001 diff --git a/fixtures/mp3/expected/mp3_mpeg25_mono_8k.npy b/fixtures/mp3/expected/mp3_mpeg25_mono_8k.npy new file mode 100644 index 0000000000000000000000000000000000000000..cfa4150553f2c685ced8cdef196bd7b086cfc5aa GIT binary patch literal 18560 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 Q0?`0Y|F`~>|7ZV(|IGImFaQ7m literal 0 HcmV?d00001 diff --git a/fixtures/mp3/expected/mp3_mpeg2_mono_16k.npy b/fixtures/mp3/expected/mp3_mpeg2_mono_16k.npy new file mode 100644 index 0000000000000000000000000000000000000000..576eb0b35841e0a3ab3229da45e395050345eafd GIT binary patch literal 25472 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 O&v?PO1W+Q!0sjw=DQffp literal 0 HcmV?d00001 diff --git a/fixtures/mp3/expected/mp3_mpeg2_mono_nores.npy b/fixtures/mp3/expected/mp3_mpeg2_mono_nores.npy new file mode 100644 index 0000000000000000000000000000000000000000..37a80f42dc23a6a07a2d25602f2037bf846ca6fe GIT binary patch literal 25472 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 Yhk*4E{=ZJcf0Y;h+x~Bi|Ee?m4~em{p#T5? literal 0 HcmV?d00001 diff --git a/fixtures/mp3/expected/mp3_mpeg2_stereo_crc.npy b/fixtures/mp3/expected/mp3_mpeg2_stereo_crc.npy new file mode 100644 index 0000000000000000000000000000000000000000..9e11218d2bbf17cd1a7ad98bece623155452b679 GIT binary patch literal 57728 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

G?U1VxdL1a@{ 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 literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_abr_xing.mp3 b/fixtures/mp3/mp3_abr_xing.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..1438259282bc2a7fad5efcfc5522cd2dc2570ade GIT binary patch literal 4320 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 BN0R^m literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_id3v1_after_truncated.mp3 b/fixtures/mp3/mp3_id3v1_after_truncated.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..a11c8a4f340702683d46cff4e7c3eac58bd7358b GIT binary patch literal 3224 zcmbWx`6CmK8wYT6jFkIG%(cdhuoxl7+_y5-Om4DK?l!8AD_6@E zLMFGOeB$G*Nc*;bpdY^PpPuJ=KR>(}yB57HX9^V?VU|c1Ie|*E`{J5wy6!40U1DrJ zgjPN-qce>4(#n6hS>uEONHi8Y_=@hrV7vyq9CaSOdeynfU@!*T8H``;o8SLT8DjBS z2EVz0a2x46NWM;ifB4yDl06vwY->Al@k9LV0L~L^+|F@wLUQR~8I~|}iAahyZLte{ z*2sOPRXKeK!1&_SyJqQy4DwO_fJ6A59$vzdUiixPlaXDknuwPDuUjG4r$M*p ztS|3BY;~5~Em@R^Bi@;&8r%<3|AJc36YPv_?>y#NecfCk$OC-&2;P?ZYK$?-^zh1@ zA72h1^bXfbPiVWD-WK^-+J`sG1J2@4O5|CR_|~6_xZM>bYGGN zRs~nf2)TgRv81|E{^>F<3(Qd_Ub%6a5-euN<3lpx@d>h3;>T~ygznGJIWv6gXgrji zdY#2D(pB{6ttdLW>)w`sq*Zmeh|9>%PGpKereSHeauB4+7XyRh9Lgy@LlCxxe zWD-_?(?_`!5&YolSqhZYY`3^3I-$AH2?Hv9yYlwsb?xD~js69LOt-|?Vkc?c`4gtL zHn`LyvGZTrXQSKpe=lLLa7F6sJ2l|cM!f}X7y@!dTYfGx(Q~s$o?{z#KR+{V6D~J# zvt)W?q+G@4)o`gMF^<;lL+Jf_j)~)&FTU0Hxyw2Km)z1-_{sJ*L41a%Zhu%-R_Tj% zrbT(}uIHfEy=!KHV(x=na)FI9Wm;&Yhp1U;UQarLq$uwuM%5&NOs=X=(py`K%M}Y_ zun;#bf~r;rR2Qiv?L3)bQDCWPrKtZYu0**fjru^nZbXmr^5ILS2PWYmzKpW&U*Gz5 zt2*Fr&Ej_*3@_Kkyw7PHHag2M( zqdvNaI@wh+=y5@HugX`dn=*^jDZq|^=ZW)G>?8#6ERVuAsbtj(cFfts-+sc-gbfho zAD8$`6|Ax%AwCBfzI~-b|0aL~X{hqgu+kA1?C8JugPF`tY?+xds=b z{Y$D2b~TQHwO|mePVcUHR-dL?`6jtEy4<_%lix>ON*%50h6Nc84uX}u&t5ZfYen3t z_@;h%RD*##xKXeU1k^S2rqO4yQha&+H_P8nE43JWxVN@HsnbWFo;@9x#joIQx6|X3 zfZ>0P)=(f)EZvzN6i7R79%Vhi-iXiQa+Fq-wc+~A4Y|gvmCpSvOuT$h-*wCG=K()F z^=Wik1mD5oY=BvyMH2GeS;SLth0GE?FlG>1nq5$m<7!yPC#?Vd$gQIcQ;eVvTWLWN zsOAq>vw&e@$#^`6rWZ0SfMfkJl;zVo_A&c00*v%*%0`?RL={ z&7ZP*Sc$M1d|cA8U9@$uIc5CO$;Y9sM_E2Dr$%H>tudznaVJ#a%IhIV3rcFGdL2)_ ztxgw0xjGlqa7x&g#dy7)Gf!nK<(=0+6y=L!Zpan4V5TP=1hbmAP#=JtgsZF2SO=Gq zSSKQ&$)2z1a5JH>5SIvLHU}O1{AYKT)%^{1^mBfUem`(Zl+YY2PAiPea7PUpWdPjD+YtJnF zE=!|g!EFBLRiV)4*Y|bbXw5M_sUQK*dDI^dvMRf^ZJVS}`!#7y6*r>;?6MG*zBDBo z{a{tdTl|%^f{Cvqk^O$krbqc+90zs6FvnTJ8Cn1)JL3ZQ7;h$-rOTDOVz)Qm>(kTd(;w&h zar1!bA%dF3=h5m{WF{)(+c=T$(Cpoklaq|T@8NwLJ=t@U!`6Pj8-~In=YTA%11X&D z`(?J8lKJgq0PkF0rEPnm#$!C5yjE7d)1Q+GTB5b0cXLeJq#m*g`$A}1 zJ`S=hfhG_EKB0U+svcXUokyyN#MO!TsgVR^%wP7%(|zep zBnc8t_0rBdgN%TMyh(A$o5D8T{dRmHo8_L@eO}2^Xkhu?=MWCg({|5u&7NGfo|c`YIaL`}*vN^L-4e0CU;SVT3a>1aOhZOao) z9pCLrW8{R^x2_~JVAQLU_*z4{je#s-r+MB~)Y zk@x(HKer47xuSB81l!WnEn2i;Z2nw4UT&=P6IpD%J+A@|E|QL71KeS!?jr zI>uaiiOqnhZbYu8!~C(T<1g^<^;|r`E+TF_PSqb>qZhN@lxj@cmg;70O30Sse*OBv zmDUH&xvCfKsvcf75cCFs26r}*&!q<3PIz76q@n3}x#MR8yZVo7r^Q-=M>883_uGQJ zI};_u=VO0NozDz%3D(Y*)lizuncF0`LmVUExYKG(&qv5?%D6>Lf4go4taLn?>nK8% zc4?(3?~-OI4)o^W9j&N&(=4*1u-ax!B*rSAW+~P{ROLNH_aAJndu=?D2#q6kU|><6 zwZpv=an8j&Me_Vq`aV9`Ap)t1Hqf=GgUWY~AvOj*w?Tvr&gr zO{LE*Ii#z|=$WnJ{oX7dre{!gc4`W4J)j()Le_r$qoYnE=J&nn`3UNkb2Fo_VfwDl z;ezyt@;+5y-0vx|W_DZEXt;Kn+$?m4F|14CY27T~ZlrOhJLkx>G(rSY5|OQ0Z@rEg z9F8bE;}FKFZgVkz0mjKY66CDlvLxVp1`PWtr4u@m@ I_5oo19|f-Kp#T5? literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_id3v2_footer.mp3 b/fixtures/mp3/mp3_id3v2_footer.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0fa9ab1e7a8bdc43c94c705fb3b1c42414ff7b44 GIT binary patch literal 3228 zcmc)E`7;!Z9|v&DI#TW$>)-KiK zzS`V`tlUC*;>lH!XTR;t_Ye5~_I=NMWM!|t>f^2MTN`K~m3LJ(0?+0_& zqKEBFfpP;3jbu|0sxW^bslBf6rpDGG!NEst7T_^C!`vvT_=}f4P85K|;-CX>8O}^* z7uflz{pju6_AMrpInc^v{%+m+@n_4Bh|e z?{@POmkh#JzCRn@wXBYKx&L)LWkQw6#HvTy00#yqyX4h} z&lPV!e)p8+5tN0gF|NS-8vlOvU0Jp_NeicjuVIEKjO_(iso5xpJ7z;@i<_K&oz3Kw%8-r0#v z5vmvwaQ3}1ho+fC{a7i$FKshR6h?I7L>;(6yf3rZ75$TiZ_6h`cjGEp9&s6YTb5@? zE%m!aKbN5)m26wwR=|aFHdTda{mLP&3UOP*LlACN7*TpBa7usQ5 zD&MZYe{(~3Xl}D_!6?%;F}BE2R)7A4nT<6*^+@9Um)6R1a94RE^$i{C@tPyv z!q!Y7g~Dw==b7la*&~m!&3kJv%vwatP_Af}M^45?a$Xakii&ZtY8}Mx*Ktl9-+KM6 zuGdY$>7V469R;6l?hqws_-gluJZg++MxPK6YGPzSRR;^yW}#)s&8Za_wA~Hd)13S^gQ`_F6OPJP3dO>6K>8j$R`&l z4xut-PUaLYgR&J%MB{YkXv(xi)6*EY;>W!VcR0mGI_T+>svfnkG*?wN$5VhEA&(R1 zD}iJL*I7QL@8sfDOV}}Yw_xiDV-yD<%0Djgx7tzu`SS)lu@M?~ujevy1C9Wn&v~;v zhEg>d%MO|;8-Do6pZC3(Mew2PpL2~aM*A069_(rzbJc)Buv&wAm$G`bHOsarCDCQx zEuZ~9=~HXzl{YOY8sH#U@rUen6W3< z_tPpbjXvIA-=Ea$WlYbWj>{5MaUZK>IXIuvUnV1 zmF2B@)_5V;`E}BHUxZ1P4H&v?+x|Kb)JT0EofaW*a5x)a9%zw-96gJ84lb8lVg$wv zKufZp6z8}Y*9wRl{y1`NEA=cw(1t8^pa@LU$7@+!VG_v%0;jeYGAw{|<0+Kw^Eu#{ z-53!@elcY&NeZHgEkaP_*&nwqvphJEXBf8(((LiCzIQ~JCdjIu;7e1kd1x+yOV!RO{rSw5;jSPwicZu?%ieXuoU`pMD9zNK4L zF)pWCY)-Qw=LzC&sM6K0K?e(JY6ZNOug*rV1EE@#>sfzF)P~J;qm?^PZ7gNft3QhR z#UVH3s%tRI6Apq|&Rf9yAtyE9YIOF2r6l%=2xzj$TZV?YNLYw-ger%~rL**Ta#w8k#(R9a8+`iWTt00buskGCqvSjmepPOwBEE$iIf?~#N>5HQ zdw+!YZgywSO%7T4`EDAEik;(PWA9JlcH1wt(U#6{r2zQn@+xfVO(f#;zM<$;;Eelt zJY~JKYNszJ6SPEc#_r~rwa7eT7xjhEb$smQ*#c1zApwzmKbiqYq^*0ZyVUyOo4IBN zVQE7ekYIX)uWdD&<*AkiWXxZ2&(nY7O(F}E%nZ`bI)O~M3iy-akheswJNs+}K-SCM zUA8d42$n56f~U5iVNW-3;I+a=1Rr zaPc}dbbTaJOb|GDxLg=9QyBLAmrOi_$0U9={B?@+suHnSJ=JlFnzEMKeQvkqE0E=B zk*ZEv#%T5{jn5825({aU=z7|(dRp?tQ^$8Z5;=>aKekG|#%aVx%g$t%DVf+OIv~6{ z+57@U_B|CuHsVO3mH5KmDJ?O-g8%g(Hk$+szal``?PmI?wobZ36o7Gxcjd=#YqdhnjJyytQ1FnPC#yop^cicU!XL zV73A&g6=;Ojg0PWz2&%&Eu(+~CaZtjY{fJmR#CGU|ER}o2ZJ7rg@_RJ#n~5^1Y%>C zE^j3H*Lo1UI2nF<|~U_3_t)4+hR2U}rJc z9mlFqF42ow?@F{LZA$dBwxr}s@xOon1)+5hn0*c^BhH}(=V?S=3Uk1c_1k~;q(w(nqj!)x=gRA?Nz%@Y>oQ8Of3S-Ao8a9gR6!4=}tLvFB>32DT&DDtoL5WOil-kt!W7JROclLe<9|{yHb>_;L;?n56E%x zM?6s`?nLO8N7{W;WA8_2>_YPix;qdpdO6F}C)0>wpv|KIJ~&Q9N1|{wv7*|sj=&+; z`3?}u{mJWO7S7Q0K!mWcBT3LhnR{s>i$OcQH!D2BlEzlg)PF^F5Y%#n6?K=_&k;zR-*cg9c- zo$TL(3oYt!Gz!Zztj$q3E&JpNfPQ8IYL^}kL|2_0JgnIYfxH@5Is~I0g3xNdVAP+| z*kdtlr;MK-o~+#e#V$ka-b13qxiS)-#oL!o^mI<9l-rj> z)8oraYyKR@7O|4bym_2%;FwtE4!nlbHt|xt=ftyI6>DP~GlZIkqoX6sgO_?uf6URL K!S<*Bzw;j}i2_vs literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_id3v2_padding.mp3 b/fixtures/mp3/mp3_id3v2_padding.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..1d3a587e588c0fd9c4c10168738f93af4ad5a376 GIT binary patch literal 3258 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 literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_id3v2_twice.mp3 b/fixtures/mp3/mp3_id3v2_twice.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..00d0727f3c61e681d534bd9a59e096e035457c6a GIT binary patch literal 3228 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 literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_junk_between_frames.mp3 b/fixtures/mp3/mp3_junk_between_frames.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..25d0fca28662ecb5e48101333269016b6330fc8b GIT binary patch literal 3303 zcmd_k`9Bkm9|v%Ar`$(kIo6nw5hLW7+gxR?g$_)v+&M<&zKL0m$xSxO-A46smnIsU zq4$TAUD;CdA%eG){~tb9sYF*gAIrvWOzaRJD}dt+3ztKTjG#;^NQx=MR6Lw)L0#$s zT{3W)ZB1?VYFGYwwyX1i0DXJXLN>emhQ|Vt9C@ zu1u_ij(RbLa+PxTk~$OM$~3|~!>MokSA@9p3S|!Pf}XI#xZWxg6;cJs*#+51o5KVx|KB%v_c4b}dp|GfGkFWHx% zhJj&g=|NZFyGV)?`JXPsGXHEv!p*zq$$_HQ++IW@Zm$3<1wP!?Z1BOtyaV04j>=8m zt=C%mDp^H~+=-x}yB_cOhMQN13OkPM?uIAvSB~;Jdf%BxQVb$~t`=gKcj%=uqZ%&DKjBB9rQioltg#?>9fZxuZEeztz8}m+l-NU2HF@y>Q0Z z$`YG=B6{U(`&?w(!JlQ!P0ny_UHb;C%BZJ+C7oZUXvfEKHgbOM#BF@*(fUi{HlcDO zXC%WTCE+Btpn^>{in6n4A3`70vrV4fd;Pt>&qc=J-^7-#!Y@`2@M5#vbqB-J(h6TK z(#^_i_uK|G9^W?c7j+rrl<{wrD$_tCTt!Su^LkR@M0r_fQHnYdXmm?;iq_gvTrOW2 zg#kNj;FUBwAle88Nr$O4vjU{NxxDU|m=eXF6v`9Tx)B}no18aH0On}E{~Zi6RNPf; z1!d8{x%2yewcn$frJq{vJe=3^)>Edn(^=#0&e4cx7fE)(66FpiBzB$hRdaaLO!`>T zjA-+-D3_9_eKc29lGDY2X9d;0ux}J+MJD@mfL(sKGgqouiE#Ey+;TsNC2Qu;Q;r_K z_A~lMEPx2#nE2nYll&`Jbatb|lpo&CrRDma0KQ!IWO#JNYtvTjRFXD*u;ITRd(ewj zhi`w$)w>qyTT*qnr*_I-3j#vxbRL;z^r@?qZ<9(R%RSq^_EE&((0ql%$<+P z;FEK)-tF;*fp7C@q;kCs5i1|m zb=t8$I^-+OICqq} z7sDyT<{A(!Jy-2)Ng$F}(l!t~`b>$uH09!h*UZ7D_wpa?I4jfitU z?_FnjFhKVZ4he+u)1&_Pc&G}{q5&XPm2k_!XC)m!igpgSrwu>bd)c=2D9XlU*9gz6G-emT9|p_ad^cog zMoz9&t>dn@(&~aMR_D4moD;HQGTdzE$b*e1jd=`2kiXjH2HkWHWOzb>Q1b;d)dBEX zWmOoJd2l&_c`^)===PSTY$6yE-~vd zubxJ){urmv+lLGf0oWwAfL6UJHCY+k#(@|^vvyycnxgmp4DH+M$(o-Uw(#-Z(ialG z%+AC-ki_9~P-dlmF~6Mz;F-^>v}!OAjm`URL?yG%x=zHBHp;4Z`?J%5%hXo%Ubb3(Zv^J&70mac=&*!ayC%DeZydjwZ>8auH!lL>4DWDvtVJ?BH5UPC z3pZTzwBL9Vhyny-os>%sKm+zdo`e|0Jt52PersN!UMi7g0>9 zTI#QQ+ww$`C-%DH*@`1SwTr&SC`U(1&SsU%8Q8|#!9BW}eEbCu++_qeV+g@j*rL8^ zHDRAaKj#1!t!qk<%G@_y)T<7YL%IGf>9_oIt?xp*eOTqx^%s;^am96}qZ%2r`}MB} z4E3gV35Ln*;g5Zazc@|l?;kKcL*hsM49~fZ;-iJ={h|%rzk`@ixE^$;m4spbk8GmG zbDljbzX9xQ!+I|=D6GM*b^;=8DOGK(n?Q8MUtjv&ktjBlB|`|K`i@2-BD>q~*)L{E z$Y59#mA-Gaqgs!v$r-eNm7;b6ftlk$f;epv=A~uc=;-C^n+d*kZn8v;Vol&0Z+V{y znBiHJwg63Ux|=F4v*;024M^2As4qro;x+E0j-wmMQP_FczWTFMTQ~E&Jw{#+%R70x<0^S4Apw1@JdsGFI z1icKHi#VQcDt(1yldK}4XLpJZdNa5go1kz)0maxPlIFW#9d&9^e;&^)gi&@J zn(2KFGmo^67bQm&4=DT-J}(G0b3c>}hHFw~14Pr)dQ7 zp)|~(5I7FxdEt_?`X{`I?^IQc>eJf))OxfPvp5eiYzotHA=~8C;+y5W#zu!P5j{pDw literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_junk_false_sync.mp3 b/fixtures/mp3/mp3_junk_false_sync.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..cc4ac823f06cbfdde5c650b0e3769af3da89532d GIT binary patch literal 3194 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 literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_mpeg1_mono_vbr.mp3 b/fixtures/mp3/mp3_mpeg1_mono_vbr.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..c72a02b5d00c81580f503f4fc4940b9973bed71a GIT binary patch literal 5232 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 literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_mpeg1_stereo_cbr.mp3 b/fixtures/mp3/mp3_mpeg1_stereo_cbr.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..7fbeb53c1332dc969c905b69e1beaacb89d57619 GIT binary patch literal 7105 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 A;s5{u literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_mpeg2_stereo_crc.mp3 b/fixtures/mp3/mp3_mpeg2_stereo_crc.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..a6432516aea826aa091398b365b4ecac8b5887e6 GIT binary patch literal 3918 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 PxSpUd-R%G0^$YbMCx-Vi literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_reject_free_format.mp3 b/fixtures/mp3/mp3_reject_free_format.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0ee5f42fe0e05e5856036b9bc1f3136522f37f05 GIT binary patch literal 1248 gcmezWo56u$6b#xB_&*vygEnqJ4jYZ1K^;8|0JdrduK)l5 literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_reject_id3v2_outside.mp3 b/fixtures/mp3/mp3_reject_id3v2_outside.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..cc15e4abba56b9b7d1e30247bd8e96d565453b99 GIT binary patch literal 60 UcmeZtF=k<4U|{1_0FopE05`Y*_y7O^ literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_reject_id3v2_syncsafe.mp3 b/fixtures/mp3/mp3_reject_id3v2_syncsafe.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..14d374d63937b03a0999e7f18ac39f71061dcc8f GIT binary patch literal 60 ScmeZtF=k-^f(8&lA^-qKb^%2I literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_reject_layer1.mp3 b/fixtures/mp3/mp3_reject_layer1.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..8817f7e47471ef975856ecfed6261a917590cdb2 GIT binary patch literal 408 UcmezW-@$=l5P<)q?m&qJ0PN%kdjJ3c literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_reject_layer2.mp3 b/fixtures/mp3/mp3_reject_layer2.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..d8b685d630ed21e14696c20def5ae7eec2aae5b6 GIT binary patch literal 2016 zcmZA1dpy$%1IKaINbU|Mpg`vyY=@4QQcFANYmr-oV z+~x9Un_^43x6p}WIx3{3Q=RkF^SsXK`QtqQe*b*GKCkcBEurDWuKu-8_B(WUejh)w=d$t{I~lX(g&u=av6Q@ed-vq!t&A`x9L(InRfu&)=@~<> z+|@Om^DIVtV-`ejV|#lISE`eu@~FQkV`9V^O{H-=MpgL|RxSLLYX#Z8awM($yfS9m zMe8^jsh%q)9IKOH(@5Gc*cujE|Bp2xyg9oI<7?l?n|-Gg9Hd$WvFPVzX3yNmj*h9xV@PmD6u z8~BTNV14^Kqk!Vspn}eAQx3;GSG?J&tmtQX6w{{(9h6dg;$>DDWU-F;!4X?_C)(B9 zi7E-q! zzjaq&e|xGDyVdzn+vJWKdpYm$-TklJK1p!Qll|Vq^3_e71ML=#7MK&!Uvy!tfWXZJ zs>r#|nBw>Dv4(_@PX;>1jCu}0LJWxo&5HQIAe3fe`N9&-Y*a_A!*PF`MhUm} z1o8f$M6*KH8u*=BK5bUfK26aefh3s_^Bm!JY@68` zFNdjmXrG`cXRXPLX@v-Fs05d@)*vS?QgH~6@GQHWsWU-c31fNYO-WvIMSTH;FLiss zKO8x9PbbNAP%^63sUREH=KUnbrp^ARC$FJg9UlE~ zc_uh{`$El?4iKT;S?k{^Ae-i#eDmD*CAmnA+na*bJ1Wl4+d7J8Mb}`o#&mPzGgXu^ znd`iODpQNNL^~{%ik1cF!quEGY3>2@zz$SS|eXd9r?YscIHBx{rY>gU`47=*fphpF<) z;d`08_Fl5)vD9i=K}{oSNv}c*((wE4tz5eBFTdz~P$=$!o`@ef@4-*4sSOSkBr;ko zGK9H;C6D$AbWndmO-=CZ49yo+F^rmosY$MSX~aCZVOgRYI56#dT9!Iwi{9i(4-NL~ z-(Yw=(rabcBRB+v_H$6%Z@L5BTP9@GL>w<(7bkBdhR=TS!P@E?8DBK>SDVaS^+gQB zQAH+wAywXMqAuS<5BWSr*&2&Nl8TFE>=Y zXu%W|zDD}tO^Y6}d3Z}om|MNQ78|>fF8AT)#sJ_$nc>Y8rlfSxk+G*R2A4(1$uWMY z-w8mHqgKFu_0WT_W5l12xsoGpiKT$KDhqYN4BllRYg^{F_$^S6-0kGTN`vdK9<<_n-w{_C5Z`;yED@M#xK|P$A14anLO@JTGla9%VVg4rpUr=^Jw*0U zF+i+-AG_%Eb6ra3&=)ftG7~dW=u-umfRj#mBp*<@5CzRXF-N8J;}3Ve9q(uojRg8j f@SyeumunBNfciUhI2?~SksNU6%TPxAC_w2yB$~dS literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_reject_layer_change.mp3 b/fixtures/mp3/mp3_reject_layer_change.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..dc0bd6fbe1d1c6d88b548de4b33fa5ef365a8c7b GIT binary patch literal 4320 zcmcK4X*d)L+Xrw7*_X0}u}`uy_9e2V*)W!2jHSpr$eu(eW#4Cp27?MSwn2765@Q{* z?@?I_p(5HG^B(VWzC7>u_x||5zx=NMbze9A08C}zlWd^6TJSR5WKY4&MMg%_8*Zvy zbTVj5P98fky|B;A@XxGEJm8J7VvP!==bk%$CiU~`3C~kn+^1uSt8}?AIi4gsoi4`; zpnfLX0s|m&ZdvVoi_cf9aVt4BmP4b)@h7MLqdgqkz)Q zTo?^aKxsSU`kZO&4fKCJMoK-i`}C~XGvAId3ymVVf+Qb~e%1-|EnRC_7mJ%@;KRz< zE1N2=PE!@OK6dI@b@<3hNNO5d2}dN{(0%j;!Z!R)(|G#r?`2;Vl3R#BrYL~Y?2j&j z*y*%mz|%m`G@HUuO>44f*N!)_&wT2f>>SJ*0Nbn+Q z1-}4w-K$#A%<;JIXn9HBf4jV51b&gNFSAG}*rDH$U7QarJK(WnnR5P!=jNYVvkB78 zga+s+vU)fD-eS%TEDV{U9XoQf2a}WinFZ+KKWTH`FhKd#!!ItkJu9ctUr)Ul!fm^w z%iUyjFS=n#b>*m?`KYxzrkW{arXC8o*IJr<-?q$W*m)WBGz%Rw&u!w-c_8RWnw%fs_F8Bj*d^>w^%QJ2u`drdw z(2z)%j_=6yn3-wbLtV7H0U|?jA|M#Yemm~NULmZe}8_MOdg#*+F)b7 zua)YEqC-6qzav%cWb{mn^Y=|1RGgNF1M@p39i>Hgo>WkBm4Q>V=tETPkziF&*p{Yr z^xq@LW6*0;$x#BPTN_TyB@zo~8w=;;Qy}3C(D*^gs0W-_0NWtm&VynKJ6E=|_XUXpr?|Fs}e}O8kq5W_>@r zBdt&1@z?JT<6JGt4s-$MsGttjcefkp182s*8%JKdDt5!=&D8^;5T@(O;w@t2@_fQf z05oF0`X>4XOhyi)@XYXxtdMj0<@0%gT&7CU5LNjHcYwODBr|#K76JE9J@NpM;0gjZ z$`s`2RA7xhn!Q)QBTDeBbdML*REkfBq0YLWRr4DRbxdWo94tA!6vR%xo|5-MHj(CX zSa^GCYcJFnQPVzv9gi1{2Cfh+8uBg4IT5I852mp~UGpbwGN{#ear(?4$*cLJ z*7ArEtR>55+IG(LMRWc~r4jvQ)|Cr%5qXE@Q;&gYRR5~2#yOy+ji}7Nk&gD?J@TM# zluLF|T3dOmy#Lo)1?!S2zPK zaM$(rlVe;PQUTw1ubw&eAOL)~|M9To0d5G_bJcJ2U%pPp;HngUq~X$Ywk=${8rDeO)8TKB1&m7C$qOM0owLCJu_U-r!=?TU-#r%CN zQ*6GDE&Zn^rscbS9#*ZW0!&O`OXTJkQJJy?_6IqyQcE&JSM)=aMLu8Ll6@C-_fN^h zsmB9=vs$%<4#@ddnDn_-O)c5TWss9r&&DGM9w(i6iaqaOUxSn>&S?v{%2ZzzV;a_^ zO?qBp#LZPjs+^zZZ)2P|o}(YPoZZZUGsR{a%+;=*_d4KCthZ{dUX|Ksh|P0ib85d_ zToPioh3-aA7uYAYq4#yB!~YD$)QHe+H-1lgHYDZ=FaXzb{7yZgfP9am<0t|OTHxnj z7kX$m!UbWlmCN_u+N#_b(foVAM%ro*df$LAdi<5Qk9Y3!mz^K4?)%5%2iZA>y2ryy z=O6sCeM$ec!QqnHsn-yd6Yn_k&b6|BF0<|xzS78XAulVAhVG?u`SwjMK>O zjgc?=5U)@0<9ZmEu-2CAt>#%@y;AOGBL3xJe6HnCR7Xv z&q!+)#ie~LJN4j1zwNKu!mg{OWNN-{L0Dx=e}=%!CyLNNx^_16@TBCP46`QqQ1}iR zQv*SGX|yjt#rRu=Ci4;DkbHg??Ft(F%7~3Q|KFTteb!ySYXkM?DetC!E>=|%??$C0 zYasaAOBQSTSA89YhoD1ubbB?s)sYo&0pVi;=q-=*BKg)eP#Y1l{^rm(>eNF5@b!PR zv+!lWa~aHPhs}(AQAOOF#X~w*GxyqYdoy*pFl&`Hh08(Hf{6gm?}z;?i1)!OAK+0$ zPiReIZq}Lpm`UbV%h5Lc-gfF_6v`>G`uao2H(3uy<%JB1uoW?*Ah3QX`=nSax-YAO zFj{P~qG)&^5+vc+_Z$d8?CPLm1MUMwp|c%?<~m&C&G|^~jR7nmmW@+8_Ir5sKilU=&CT3F++ok3o}d?x zj`iMrc-!*oXV}YE&CTEFrydXSo=GC?HHzW5mC({9cCr|s5o&Q$-E=|3CCYFg3#7vh3You?!6Sj>x$Qs$7&jf2bc250fP-0ZZhi|9t7_=%~pe z^wsarwu_*sBuI~TxW4cC=GM_6wE4{6F(GD^ z8Rps>QT5pU>?kXRiZ3zu(JBbgDI5xIi(-b&XmZ~O0CU9mdRj?q&QHeP;49_}DCWeh z_Y{|UP3Q>k&mXCVED^TC&+z~_JM=DA!ItKR&HnO|lH1W4q^qHO`8vU8_$kkZK*KRz zFhQ}@Cj!o*qPNYVMkct&IR)uI7m_(H5Pk;3Tp0e-kIjGj5fDJm*vj*!kj~@%fT{Ap zR4^%~J zIZ!XU3;8MySnDZEM);`DyHj;EIV#H5WMzI~b0J^MKkf_iE0+pi%UrZfZaFip;-a@{ zkR5_YFDHbFE%-HuJy!Ng#OEr0DD^s0L*_n5YZ<6}E+NaKbR{?%hBJ(E-^JRrcJ?g0 zd#0zPibh%zNuQuRbB=m|_&PIexvw9$pZ2dU#thRvE#Rf55QgjqjVp~)XN#5RNyhD$ zwzYpzQ8@3H27~iE2lAJjq${Oi9_SN36Z|#!fnQ9IMyIaRmS`0y&h-5YZt-i=6L2SfsjnhWK$usso=6lVA6~C@Kg&2%EO$L*b~+2V(8%~lNBk$+5;40hrZXm{$kzKQSKJ*;pDp} z5T3~f3&GJy$nF1gKR1xbPpH#cOFDb?VI}Q<hNI$3TZM~ASI@f9e`YbX!LC8?-2#VXA0^yGQW;Nm)vjx+d`He{Vn?U z9klApq-UD+O%OYjBH=SYmJTJ{SzsWK?|=Ot0UIqlTUJuOxj2qZ{E-|9&t8JJtQunX z-$o>dI!nCXe01-XDLRSC1~qV@hXQ}AO9?41v4&S;uyxWA_3_nfx=oW%%a_T;#ny|n zDMpZjLCBN|J2gk2({EYdO#Y!(*2VEDOUH*g@$ah1;NvT=N(hy z55BIpLqGsz(w%gR4>e!uWw&@@h*aPc7X3@ojD70Pj*-QnIV1zni6}DI^?facRkYl8 z%QuQg_PJCx1MNTx8*N7^?-XFfNzdMMxC<;Q`Y+AwdaTQYC^uRubtX=V&Vr4$ppN0{ zN%a>wZk1xX6yYr9U2h(eWuuwFF!Oq(=1`bMo7~!cal5n$yj3^DzxVU+e-=Q#M%qG3 za1dS`s~p-_7B5$V2UC3R9B|3d?13gRZ|Br756#t71s#+DGpJ=z<$ z3gO@``_{`m?2u_GMQC%{CI)^j+=}~7X<@+E*%aRmG0$<&qAyGL#A9?E@617%nWGCrZR3@teh*ND+3GN+iiX{4zrxY)8BGZPzhb6%Q*aS?@0L+n()$Ofq?6_(_Y)HTGQOoql zXfEln%Etb8KYS4(NL%@5C14;_j+nwG2?duBeM@CB6&e;RMe_57)<4$4lG8qeO`XLu z-ei-UWx{N=$;#Z>$gkn^hQxSRpx~7|cC}$R>f>%TtVo(GD%LYDPIQF71*jP4xGC64 z2C05_?fvbd6<}Y{I}DU!#Y65%nzstj8aIe_rtf2{+Fu%xee+P54hc@}wb#SKq2~NM zsA=&LaidQ)^8KdRXsy+GpaLF(|gUl ak#we)&AbGHu6xfsP=`W;2vZz^4F3bGh9(UF literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_reject_no_frames.mp3 b/fixtures/mp3/mp3_reject_no_frames.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..a89ac1ff68a65411fbad5cb24258dab255033165 GIT binary patch literal 242 ScmeZtF=k-^0R=EQ0tf)sqyXgr literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_reject_only_id3v1.mp3 b/fixtures/mp3/mp3_reject_only_id3v1.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0c60197578552eaaa5542415a4d210942d9fa7ed GIT binary patch literal 128 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 Jp8R*W{txm!->v`v literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_reject_short.mp3 b/fixtures/mp3/mp3_reject_short.mp3 new file mode 100644 index 00000000..7df777e0 --- /dev/null +++ b/fixtures/mp3/mp3_reject_short.mp3 @@ -0,0 +1 @@ +ID3 \ No newline at end of file diff --git a/fixtures/mp3/mp3_reject_version_change.mp3 b/fixtures/mp3/mp3_reject_version_change.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..6e9c99c432b6bb73cd80a44c081b47824dad9fff GIT binary patch literal 5544 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 y1R#ZB{}2P`@_>QN5Cj1S2?GjNfF%9J*N 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 bct!;LX9!T!(b2&K1q65n{`YSHtHA#NS|Apj literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_tags_id3v1_only.mp3 b/fixtures/mp3/mp3_tags_id3v1_only.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..f17661f306382aa2ba4e0175c92dee88b6739ec1 GIT binary patch literal 3296 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 DD0NGs literal 0 HcmV?d00001 diff --git a/fixtures/mp3/mp3_truncated_last_frame.mp3 b/fixtures/mp3/mp3_truncated_last_frame.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..f235a0c38d6f42af8015877a8b25fe5fb885df94 GIT binary patch literal 3096 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 literal 0 HcmV?d00001 diff --git a/js/README.md b/js/README.md index ca8019f1..8b0b0721 100644 --- a/js/README.md +++ b/js/README.md @@ -185,6 +185,18 @@ MRC (MRC2014 files): Not supported, and refused with HTTP 422: gzipped maps (`.map.gz`), pre-2000 files without `MAP` at byte 208, and modes 3 and 101. +MP3 (MPEG-1, MPEG-2 and MPEG-2.5 Layer III audio): + +- The one format that is not an image: one array `samples` of int16, + `[time, channel]`, in chunks of 256 frames, each referencing the frames a + decoder needs before it (the bit reservoir); the `mp3` codec decodes a + chunk when it is read (in Python, with miniaudio). +- The stream's parameters, the Xing or Info frame's fields and the ID3v1 + tag under `refkv_virtualized`; the ID3v2 and APE tags in the mirror. + +Not supported, and refused with HTTP 422: Layer I and II streams, free-format +bitrates, and files whose frames change sample rate, version or channel count. + Olympus VSI (cellSens slides): - The `.vsi` file's URL names the slide; the tile files beside it @@ -262,6 +274,7 @@ uv run python js/test/dicom/verify.py # DICOM fixtures vs uv run python js/test/nifti/verify.py # NIfTI fixtures vs nibabel uv run python js/test/mrc/verify.py # MRC fixtures vs mrcfile uv run python js/test/vsi/verify.py # VSI fixtures vs their pixels (and Bio-Formats) +uv run python js/test/mp3/verify.py # MP3 fixtures vs miniaudio and ffmpeg uv run python js/test/ims/verify.py # IMS fixtures vs h5py uv run python js/test/czi/verify.py # CZI fixtures vs czifile (and libCZI) uv run python js/test/safe/verify.py # SAFE fixtures vs GDAL @@ -287,7 +300,9 @@ node demo/e2e_examples.mjs [example id …] # every demo example, their synthetic files, against pydicom, nibabel (unscaled data), mrcfile and h5py (cropped to the image size); `vsi/verify.py` serves each synthetic slide with its tile files, compares every stack with the pixels the generator wrote and, when a - JVM can be started, every level with Bio-Formats (bioio-bioformats). + JVM can be started, every level with Bio-Formats (bioio-bioformats); `mp3/verify.py` + reads each file's samples through the `mp3` codec and compares them with miniaudio's + decoding of the whole stream, and with ffmpeg's where the generator stored it. - `compare.py` runs three virtualizers (`ref`, the frozen reference, which a format added since the core, such as MRC, does not have; `py`, the Python command; `web`, this code under Node) on the synthetic files, every diff --git a/js/src/virtualize/index.ts b/js/src/virtualize/index.ts index 707fb011..29424fc4 100644 --- a/js/src/virtualize/index.ts +++ b/js/src/virtualize/index.ts @@ -76,7 +76,7 @@ export function isDicom(head: Uint8Array): boolean { const HDF5 = [0x89, 0x48, 0x44, 0x46, 0x0d, 0x0a, 0x1a, 0x0a]; -type ImageDesc = ArchiveDesc & { format: "tiff" | "ndpi" | "nd2" | "dicom" | "nifti" | "ims" | "czi" | "safe" | "mrc" | "vsi"; summary: object }; +type ImageDesc = ArchiveDesc & { format: "tiff" | "ndpi" | "nd2" | "dicom" | "nifti" | "ims" | "czi" | "safe" | "mrc" | "vsi" | "mp3"; summary: object }; /** `exact`, when given, reads exactly the ranges asked for, past `read`'s block cache: the * Rust core's requests, which it plans itself, are read with it. @@ -168,15 +168,28 @@ export function irFormat(head: Uint8Array): IrFormat | undefined { // `MAP` at 208: an MRC2014 file (spec/virtualize/mrc.md §14.1 // ) if (head.length >= 212 && head[208] === 0x4d && head[209] === 0x41 && head[210] === 0x50) return "mrc"; + // `ID3` at 0, or a valid MPEG audio frame header: an MP3 file (spec/virtualize/mp3.md §16.1 + // ) + if ((head[0] === 0x49 && head[1] === 0x44 && head[2] === 0x33) || isMpegHeader(head)) return "mp3"; return undefined; } +/** Whether `head` starts with an MPEG audio frame header (§1.2 + * ): the 11-bit sync, a + * version and a layer that are not reserved, and a sample rate index from 0 to 2, of any layer + * and bitrate index (the MP3 profile rejects Layers I and II, and a free-format bitrate, by name). */ +export function isMpegHeader(head: Uint8Array): boolean { + if (head.length < 4 || head[0] !== 0xff || (head[1] & 0xe0) !== 0xe0) return false; + const version = (head[1] >> 3) & 3, layer = (head[1] >> 1) & 3, rate = (head[2] >> 2) & 3; + return version !== 1 && layer !== 0 && rate !== 3; +} + async function virtualizeFile(url: string, { read, size: fileSize, exact, source }: Input): Promise { const head = await read(0, Math.min(552, fileSize)); if (isDicom(head)) return virtualizeIr("dicom", url, source); const ir = irFormat(head); if (ir === "tiff" || ir === "nd2") return virtualizeIr(ir, url, source); - if (ir === "nifti" || ir === "ims" || ir === "czi" || ir === "safe" || ir === "mrc") return virtualizeIr(ir, url, source); + if (ir === "nifti" || ir === "ims" || ir === "czi" || ir === "safe" || ir === "mrc" || ir === "mp3") return virtualizeIr(ir, url, source); throw new ImageError(NOT_SUPPORTED); } diff --git a/js/src/virtualize/ir/run.ts b/js/src/virtualize/ir/run.ts index c7fc9ff1..966e519c 100644 --- a/js/src/virtualize/ir/run.ts +++ b/js/src/virtualize/ir/run.ts @@ -12,7 +12,7 @@ import type { RangeSource, Span } from "./source.ts"; import { ir, type IrExports, out, put } from "./wasm.ts"; /** The formats of the core's file runs (`Format::from_name` in rust/refkv-ir/src/run.rs). */ -export type IrFormat = "nd2" | "tiff" | "czi" | "dicom" | "nifti" | "ims" | "safe" | "ndpi" | "mrc" | "vsi"; +export type IrFormat = "nd2" | "tiff" | "czi" | "dicom" | "nifti" | "ims" | "safe" | "ndpi" | "mrc" | "vsi" | "mp3"; // (`vsi` is sniffed as a file but virtualized by the store run of vsi.ts; its file run only rejects.) export interface IrOutput extends ArchiveDesc { diff --git a/js/src/virtualize/profiles.ts b/js/src/virtualize/profiles.ts index 3484cb32..892dc4a6 100644 --- a/js/src/virtualize/profiles.ts +++ b/js/src/virtualize/profiles.ts @@ -1,6 +1,6 @@ // The profile registry: generated from spec/virtualize/profiles.json by spec/tools/profiles.py; edit the registry, not this. -export type Profile = "tiff" | "ndpi" | "nd2" | "dicom" | "nifti" | "mrc" | "mrc-dataset" | "ims" | "n5" | "zarr2" | "ome-zarr" | "safe" | "czi" | "vsi"; +export type Profile = "tiff" | "ndpi" | "nd2" | "dicom" | "nifti" | "mrc" | "mrc-dataset" | "ims" | "n5" | "zarr2" | "ome-zarr" | "safe" | "czi" | "vsi" | "mp3"; export interface ProfileEntry { name: Profile; @@ -31,4 +31,5 @@ export const REGISTRY: ProfileEntry[] = [ {"name": "safe", "section": 12, "title": "Sentinel-2 SAFE", "uuid": "ef81346c-19e8-42ad-93b0-a279ccaf44c1", "version": 0, "kind": "both", "suffixes": [".zip"], "reference": 25, "source": "Sentinel-2 SAFE (Level-1C, Level-2A)", "inputs": "Sentinel-2 Level-1C and Level-2A products: a `.SAFE` directory (a store) or a `.SAFE.zip` file", "for": "Sentinel-2 Level-1C and Level-2A products, as a `.SAFE` directory or a `.SAFE.zip`"}, {"name": "czi", "section": 13, "title": "CZI", "uuid": "7a0733c7-d4be-4482-a64f-6904d9354ea5", "version": 0, "kind": "file", "suffixes": [".czi"], "reference": 20, "source": "Zeiss CZI", "inputs": "Zeiss CZI files (ZISRAW, file version 1), with uncompressed, JPEG, JPEG XR and Zstd subblocks, mosaics and pyramids", "for": "Zeiss CZI files"}, {"name": "vsi", "section": 15, "title": "VSI", "uuid": "c0a1d4e6-5b7f-4f3a-9c2d-8e1f6a7b3c45", "version": 0, "kind": "file", "suffixes": [".vsi"], "reference": null, "source": "Olympus VSI", "inputs": "Olympus cellSens VSI slides: a `.vsi` file and the tile files beside it, probed by key (uncompressed, JPEG and JPEG 2000 tiles)", "for": "Olympus cellSens whole-slide images (`.vsi` with its tile files)"}, + {"name": "mp3", "section": 16, "title": "MP3", "uuid": "b6cb0047-9448-4fdc-b03e-10dd3d6aa829", "version": 0, "kind": "file", "suffixes": [".mp3"], "reference": null, "source": "MP3 (MPEG Layer III audio)", "inputs": "MPEG-1, MPEG-2 and MPEG-2.5 Layer III audio files (`.mp3`), with their ID3v2, ID3v1 and APE tags; one array of samples, not an image", "for": "MP3 audio files, as an array of samples (`.mp3`)"}, ]; diff --git a/js/test/mp3/verify.py b/js/test/mp3/verify.py new file mode 100644 index 00000000..aa90d806 --- /dev/null +++ b/js/test/mp3/verify.py @@ -0,0 +1,112 @@ +"""Checks the browser MP3 virtualizer's output against miniaudio and ffmpeg. + +Each fixtures/mp3/*.mp3 is served over local HTTP and virtualized by +js/conformance/virtualize.ts (the browser code, run under Node). The array is read +through the reference reader, zarr-python and the `mp3` codec, and must equal miniaudio's +decoding of the audio frames in one pass, sample for sample (spec/virtualize/mp3.md §4.1 +), and ffmpeg's +(fixtures/mp3/expected, written by the generator) within a few units where the generator +stored it. The root's metadata must agree with the array, and the file must be rebuilt byte +for byte from the archive's IR mirror (refkv_source, §5.2 +). +`mp3_reject_*` files must be rejected. + +Usage: uv run python js/test/mp3/verify.py [

] +""" + +from __future__ import annotations + +import subprocess +import sys +import tempfile +from pathlib import Path + +import miniaudio +import numpy as np +import zarr + +HERE = Path(__file__).parent +ROOT = HERE.parents[2] +sys.path.insert(0, str(ROOT / "conformance" / "vzip")) +from http_server import Server # noqa: E402 + +from refkv.policy import Policy # noqa: E402 +import refkv.zarr # noqa: E402 (a vzip archive as a zarr store) + +sys.path.insert(0, str(HERE.parent)) +from ir_mirror import mirror_problems # noqa: E402 + +# The sources are served on 127.0.0.1, which spec §6.7 +# rule 3 refuses by +# default. +LOOPBACK_SOURCES = Policy(allow_private_hosts=True) +FFMPEG_MAX, FFMPEG_MEAN = 8, 1.0 + + +def audio_frames(path: Path, out: Path) -> bytes: + """The audio frames' bytes, one after the other, from the archive's mirror: its data + elements (spec/virtualize/mp3.md §5.3 + ).""" + from refkv.ir.cmirror import Archive, load + + data = path.read_bytes() + ir = load(Archive(str(out), lambda o, n: data[o:o + n])) + cols = ir.columns() + kind = np.frombuffer(cols["kind"], np.uint8) + start, length = np.frombuffer(cols["start"], " list[str]: + root = zarr.open_group(refkv.zarr.open(str(out), policy=LOOPBACK_SOURCES), mode="r", zarr_format=3) + meta = root.attrs["refkv_virtualized"]["mp3"] + got = root["samples"][...] + problems = [] + if got.dtype != np.int16 or got.shape != (meta["samples"], meta["channels"]): + problems.append(f"shape {got.shape} {got.dtype} is not {meta['samples']} x {meta['channels']} int16") + return problems + audio = audio_frames(path, out) + info = miniaudio.mp3_get_info(audio) + d = miniaudio.decode(audio, miniaudio.SampleFormat.SIGNED16, nchannels=meta["channels"], sample_rate=info.sample_rate) + want = np.frombuffer(d.samples, dtype=np.int16).reshape(-1, meta["channels"]) + if info.sample_rate != meta["sample_rate"]: + problems.append(f"sample rate {meta['sample_rate']} is not miniaudio's {info.sample_rate}") + if want.shape != got.shape or not np.array_equal(got, want): + problems.append(f"samples differ from miniaudio's ({got.shape} vs {want.shape})") + expected = path.parent / "expected" / f"{path.stem}.npy" + if expected.exists(): + w = np.load(expected).astype(np.int32) + diff = np.abs(got.astype(np.int32) - w) if w.shape == got.shape else None + if diff is None or diff.max() > FFMPEG_MAX or diff.mean() > FFMPEG_MEAN: + problems.append(f"samples differ from ffmpeg's ({'shape' if diff is None else (diff.max(), diff.mean())})") + return problems + mirror_problems(out, path) + + +def main(fixtures: Path) -> int: + server = Server(fixtures) + failures = 0 + with tempfile.TemporaryDirectory() as tmp: + for path in sorted(fixtures.glob("*.mp3")): + out = Path(tmp) / f"{path.stem}.vzip" + p = subprocess.run(["node", str(ROOT / "js" / "conformance" / "virtualize.ts"), "--allow-private-hosts", + server.base + path.name, str(out)], capture_output=True, text=True) + if path.stem.startswith("mp3_reject"): + ok = p.returncode == 3 and not out.exists() + failures += not ok + print(f"{path.name:40s} {'rejected: ' + p.stderr.strip()[-80:] if ok else 'NOT REJECTED ' + p.stderr[-200:]}") + continue + if p.returncode: + failures += 1 + print(f"{path.name:40s} FAILED: {p.stderr.strip()[-300:]}") + continue + problems = problems_of(path, out) + failures += bool(problems) + print(f"{path.name:40s} {'ok' if not problems else problems}") + print(f"\n{failures} failures") + return 1 if failures else 0 + + +if __name__ == "__main__": + sys.exit(main(Path(sys.argv[1]) if len(sys.argv) > 1 else ROOT / "fixtures" / "mp3")) diff --git a/justfile b/justfile index 1fd0d1ac..537ed7c9 100644 --- a/justfile +++ b/justfile @@ -96,12 +96,13 @@ conformance out="conformance/results/latest": impls::build --impl rust=conformance/impls/rust/vzip --impl typescript=conformance/impls/typescript/vzip --impl python=conformance/impls/python/vzip # Regenerate the synthetic files and stores in fixtures/: every generator -# fixtures/generators//write_*.py (all but NDPI's, which needs the network: `just fixtures-of ndpi`) +# fixtures/generators//write_*.py (all but NDPI's, which needs the network, and MP3's, which +# needs lame and ffmpeg: `just fixtures-of ndpi`, `just fixtures-of mp3`) fixtures: #!/usr/bin/env bash set -euo pipefail for g in fixtures/generators/*/write_*.py; do - case "$g" in fixtures/generators/ndpi/*) continue ;; esac + case "$g" in fixtures/generators/ndpi/*|fixtures/generators/mp3/*) continue ;; esac uv run python "$g" done diff --git a/pyproject.toml b/pyproject.toml index 256f99e5..c955ce6a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ dependencies = [] # HDF5 parser (h5py), and xarray reading netCDF files over HTTPS (h5netcdf, fsspec, aiohttp) dev = [ # the package (python/, a member of this workspace), built from this checkout, with its extras - "refkv[zarr,images,virtualizarr,obstore]", + "refkv[zarr,images,audio,virtualizarr,obstore]", "aiohttp>=3.14.3", "czifile>=2026.8.16", "fsspec>=2026.9.0", diff --git a/python/pyproject.toml b/python/pyproject.toml index 8ea724bf..4f90490c 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -56,6 +56,11 @@ images = [ "refkv[zarr]", "imagecodecs>=2026.8.16", ] +# the MP3 decoder (miniaudio) of refkv.zarr's mp3 codec, which reads virtualized MP3 files +audio = [ + "refkv[zarr]", + "miniaudio>=1.59", +] # obstore's stores, such as S3Store, to pass as registry= for s3://, gs:// and az:// sources # (refkv takes any obspec store, and does not import obstore itself) obstore = [ @@ -92,4 +97,5 @@ cache-keys = [ { file = "../rust/refkv-ir/Cargo.toml" }, { file = "../rust/refkv-ir/src/**/*.rs" }, { file = "../rust/refkv-ir/schema/*.json" }, + { file = "../rust/refkv-ir/profiles.json" }, ] diff --git a/python/src/lib.rs b/python/src/lib.rs index 962b1a76..557af7da 100644 --- a/python/src/lib.rs +++ b/python/src/lib.rs @@ -754,7 +754,7 @@ fn project<'py>(py: Python<'py>, format: &str, ir: &PyIr, facts: &str, url: &str out_py(py, &o) } -/// The mirror of an IR (for the profile "nd2", "tiff", "czi", "dicom", "nifti", "ims", "ndpi" or "mrc"): its entries and +/// The mirror of an IR (for the profile "nd2", "tiff", "czi", "dicom", "nifti", "ims", "ndpi", "mrc" or "mp3"): its entries and /// references under `refkv_source` (`out_py`'s form, the url empty), and what the /// table folded (JSON). #[pyfunction] @@ -810,6 +810,15 @@ fn _set_copy_threshold(n: Option) { refkv_ir::out::set_copy_threshold(n); } +/// For tests: the frames of an MP3 chunk (None: 256), so that small files have several chunks, +/// each with its lead-in (spec/virtualize/mp3.md §16.2 +/// ). +#[pyfunction] +#[pyo3(signature = (n=None))] +fn _set_chunk_frames(n: Option) { + refkv_ir::mp3::set_chunk_frames(n); +} + #[pymodule] #[pyo3(name = "_core")] fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> { @@ -822,6 +831,7 @@ fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(rebuild_store, m)?)?; m.add_function(wrap_pyfunction!(plan_spans, m)?)?; m.add_function(wrap_pyfunction!(_set_copy_threshold, m)?)?; + m.add_function(wrap_pyfunction!(_set_chunk_frames, m)?)?; m.add_function(wrap_pyfunction!(project, m)?)?; m.add_function(wrap_pyfunction!(mirror, m)?)?; m.add_function(wrap_pyfunction!(canonical_problem, m)?)?; diff --git a/python/src/refkv/_extras.py b/python/src/refkv/_extras.py index d349fadd..3c47f659 100644 --- a/python/src/refkv/_extras.py +++ b/python/src/refkv/_extras.py @@ -8,6 +8,8 @@ archives of virtualized image files and stores use (`refkv.zarr.codecs`); - `images`: the JPEG, JPEG 2000 and JPEG XR decoders of those codecs (imagecodecs), with the `zarr` extra; +- `audio`: the MP3 decoder (miniaudio) of the `mp3` codec, which reads virtualized + MP3 files, with the `zarr` extra; - `obstore`: obstore, whose stores (`S3Store`, `GCSStore`, `AzureStore`, ...) an application passes as `registry=` to read `s3://`, `gs://` or `az://` sources. refkv does not import it: a registry takes any obspec store, and diff --git a/python/src/refkv/ir/__init__.py b/python/src/refkv/ir/__init__.py index f4185de5..03087d38 100644 --- a/python/src/refkv/ir/__init__.py +++ b/python/src/refkv/ir/__init__.py @@ -35,10 +35,22 @@ def nifti_version(head: bytes) -> int | None: return None +def mpeg_header(head: bytes) -> bool: + """Whether `head` starts with an MPEG audio frame header (spec/virtualize.md §1.2 + ): the 11-bit sync, a + version and a layer that are not reserved, and a sample rate index from 0 to 2, of any layer + and bitrate index (the MP3 profile rejects Layers I and II, and a free-format bitrate, by + name).""" + if len(head) < 4 or head[0] != 0xFF or head[1] & 0xE0 != 0xE0: + return False + version, layer, rate = (head[1] >> 3) & 3, (head[1] >> 1) & 3, (head[2] >> 2) & 3 + return version != 1 and layer != 0 and rate != 3 + + def sniff(head: bytes) -> str | None: """The IR format a file's first bytes give, if any (132 of them for DICOM, 348 for - NIfTI-1, 212 for MRC; DICOM first: a dual-personality file's preamble may hold a TIFF - header).""" + NIfTI-1, 212 for MRC, 4 for MP3; DICOM first: a dual-personality file's preamble may hold + a TIFF header).""" if head[128:132] == b"DICM": return "dicom" if head[:4] == ND2_MAGIC: @@ -57,6 +69,8 @@ def sniff(head: bytes) -> str | None: return "safe" if len(head) >= 212 and head[208:211] == b"MAP": return "mrc" + if head[:3] == b"ID3" or mpeg_header(head): + return "mp3" return None diff --git a/python/src/refkv/virtualize/profiles.py b/python/src/refkv/virtualize/profiles.py index 6bbfa9a9..b5a5a201 100644 --- a/python/src/refkv/virtualize/profiles.py +++ b/python/src/refkv/virtualize/profiles.py @@ -15,4 +15,5 @@ {'name': 'safe', 'section': 12, 'title': 'Sentinel-2 SAFE', 'uuid': 'ef81346c-19e8-42ad-93b0-a279ccaf44c1', 'version': 0, 'kind': 'both', 'suffixes': ['.zip'], 'reference': 25, 'source': 'Sentinel-2 SAFE (Level-1C, Level-2A)', 'inputs': 'Sentinel-2 Level-1C and Level-2A products: a `.SAFE` directory (a store) or a `.SAFE.zip` file', 'for': 'Sentinel-2 Level-1C and Level-2A products, as a `.SAFE` directory or a `.SAFE.zip`'}, {'name': 'czi', 'section': 13, 'title': 'CZI', 'uuid': '7a0733c7-d4be-4482-a64f-6904d9354ea5', 'version': 0, 'kind': 'file', 'suffixes': ['.czi'], 'reference': 20, 'source': 'Zeiss CZI', 'inputs': 'Zeiss CZI files (ZISRAW, file version 1), with uncompressed, JPEG, JPEG XR and Zstd subblocks, mosaics and pyramids', 'for': 'Zeiss CZI files'}, {'name': 'vsi', 'section': 15, 'title': 'VSI', 'uuid': 'c0a1d4e6-5b7f-4f3a-9c2d-8e1f6a7b3c45', 'version': 0, 'kind': 'file', 'suffixes': ['.vsi'], 'reference': None, 'source': 'Olympus VSI', 'inputs': 'Olympus cellSens VSI slides: a `.vsi` file and the tile files beside it, probed by key (uncompressed, JPEG and JPEG 2000 tiles)', 'for': 'Olympus cellSens whole-slide images (`.vsi` with its tile files)'}, + {'name': 'mp3', 'section': 16, 'title': 'MP3', 'uuid': 'b6cb0047-9448-4fdc-b03e-10dd3d6aa829', 'version': 0, 'kind': 'file', 'suffixes': ['.mp3'], 'reference': None, 'source': 'MP3 (MPEG Layer III audio)', 'inputs': 'MPEG-1, MPEG-2 and MPEG-2.5 Layer III audio files (`.mp3`), with their ID3v2, ID3v1 and APE tags; one array of samples, not an image', 'for': 'MP3 audio files, as an array of samples (`.mp3`)'}, ) diff --git a/python/src/refkv/zarr/__init__.py b/python/src/refkv/zarr/__init__.py index 0c1cd79c..ca064aec 100644 --- a/python/src/refkv/zarr/__init__.py +++ b/python/src/refkv/zarr/__init__.py @@ -10,9 +10,10 @@ ds = xr.open_zarr(refkv.zarr.open("data.vzip")) # a saved archive ds = xr.open_zarr(refkv.zarr.store(store)) # a refkv.ReferenceStore -Importing it also registers the codecs that archives of virtualized image files -and stores use (`refkv.zarr.codecs`): JPEG, JPEG 2000 and JPEG XR (whose decoders -need the `images` extra), zlib, and `n5_default`. +Importing it also registers the codecs that archives of virtualized files and +stores use (`refkv.zarr.codecs`): JPEG, JPEG 2000 and JPEG XR (whose decoders +need the `images` extra), `mp3` (whose decoder needs the `audio` extra), zlib, and +`n5_default`. """ from __future__ import annotations diff --git a/python/src/refkv/zarr/codecs.py b/python/src/refkv/zarr/codecs.py index d4dc9c1a..78f7cf21 100644 --- a/python/src/refkv/zarr/codecs.py +++ b/python/src/refkv/zarr/codecs.py @@ -16,9 +16,12 @@ ). `n5_default`: an N5 default-mode block, header included (zarr-extensions `codecs/n5_default`; spec/virtualize/n5.md). +`mp3`: a chunk of a virtualized MP3 file (spec/virtualize/mp3.md §4.1 +): the samples to +keep, then MPEG Layer III frames, decoded by miniaudio. The image codecs decode only; their encoders exist so zarr can create the -array metadata. +array metadata. The mp3 codec has no encoder. """ from __future__ import annotations @@ -39,6 +42,15 @@ from refkv._extras import missing +def _miniaudio(): + """miniaudio, which the mp3 codec needs, imported when a chunk is first decoded.""" + try: + import miniaudio + except ImportError as e: + raise missing("audio", "Reading MP3 chunks", e) from e + return miniaudio + + def _imagecodecs(): """imagecodecs, which the image codecs need, imported when a chunk is first coded.""" try: @@ -132,6 +144,55 @@ def compute_encoded_size(self, input_byte_length: int, chunk_spec: ArraySpec) -> register_codec("imagecodecs_jpegxr", JpegXrCodec) +@dataclass(frozen=True) +class Mp3Codec(ArrayBytesCodec): + """`mp3`: a chunk is a little-endian uint32, the samples per channel to keep, then MPEG + Layer III frames: the frames before the chunk's that a decoder needs (its lead-in), then + the chunk's own (spec/virtualize/mp3.md §4.1 + , §16.2 + ). The frames + decode, in one pass, to int16 of shape [samples, channels]; the chunk's samples are the + last `keep` of them, placed first and followed by zeros up to the chunk's shape. When the + decoder gives fewer (the stream's first frames, which have no lead-in, may not decode), + they end at `keep` and zeros precede them.""" + + is_fixed_size = False + + @classmethod + def from_dict(cls, data: dict) -> Self: + return cls() + + def to_dict(self) -> dict: + return {"name": "mp3"} + + async def _decode_single(self, chunk_bytes: Buffer, chunk_spec: ArraySpec) -> NDBuffer: + b = chunk_bytes.to_bytes() + if len(b) < 4: + raise ValueError("an mp3 chunk starts with the 4-byte count of its samples") + keep = int.from_bytes(b[:4], "little") + audio = b[4:] + ma = _miniaudio() + info = ma.mp3_get_info(audio) + decoded = ma.decode(audio, ma.SampleFormat.SIGNED16, nchannels=info.nchannels, sample_rate=info.sample_rate) + pcm = np.frombuffer(decoded.samples, dtype=np.int16).reshape(-1, info.nchannels) + n, c = chunk_spec.shape + if c != info.nchannels or keep > n: + raise ValueError(f"the frames hold {info.nchannels} channels and {keep} samples; the chunk is {n} x {c}") + out = np.zeros((n, c), dtype=np.int16) + tail = pcm[max(len(pcm) - keep, 0):] + out[keep - len(tail):keep] = tail + return chunk_spec.prototype.nd_buffer.from_ndarray_like(out.astype(chunk_spec.dtype.to_native_dtype(), copy=False)) + + async def _encode_single(self, chunk_array: NDBuffer, chunk_spec: ArraySpec) -> Buffer: + raise NotImplementedError("the mp3 codec decodes only") + + def compute_encoded_size(self, input_byte_length: int, chunk_spec: ArraySpec) -> int: + raise NotImplementedError + + +register_codec("mp3", Mp3Codec) + + @dataclass(frozen=True) class ZlibCodec(BytesBytesCodec): """`zlib`: each chunk is one zlib stream.""" diff --git a/python/tests/ir/test_mp3.py b/python/tests/ir/test_mp3.py new file mode 100644 index 00000000..4b7c90e1 --- /dev/null +++ b/python/tests/ir/test_mp3.py @@ -0,0 +1,250 @@ +"""The MP3 IR: the Rust parser and its schema, the projection (spec/virtualize/mp3.md) and the +`mp3` codec against two decoders on every synthetic file, the mirror's rebuild, the inputs the +profile rejects, and the lead-in of each chunk. MP3 has no frozen Python reference: miniaudio +(the codec's own decoder, run over the whole stream) and ffmpeg (an independent decoder, run by +the fixture generator and stored) are the readers it is compared with.""" + +import io +import json + +import miniaudio +import numpy as np +import pytest +import zarr + +import refkv.zarr +from ir_helpers import FIXTURES +from refkv import _core +from refkv.ir import virtualize as via_ir +from refkv.ir.cmirror import rebuild_from_archive +from refkv.virtualize import Rejected + +MP3S = sorted((FIXTURES / "mp3").glob("*.mp3")) +ACCEPTED = [p for p in MP3S if not p.name.startswith("mp3_reject")] +EXPECTED = FIXTURES / "mp3" / "expected" +# ffmpeg's decoding and miniaudio's differ by rounding (about half the samples of a joint +# stereo stream by one unit): the most a sample may differ, and the most the mean may +FFMPEG_MAX, FFMPEG_MEAN = 8, 1.0 + + +def virtualized(path, tmp_path, chunk_frames=None): + """(the output, the hierarchy's root group, read in memory from the file, the IR), with + `chunk_frames` frames a chunk (None: the profile's 256); the archive rebuilds the file.""" + data = path.read_bytes() + _core._set_chunk_frames(chunk_frames) + try: + fmt, out, ir = via_ir(str(path)) + finally: + _core._set_chunk_frames(None) + assert fmt == "mp3" + ir.check() + out.write(str(tmp_path / "a.vzip")) + buf = io.BytesIO() + rebuild_from_archive(str(tmp_path / "a.vzip"), lambda o, n: data[o:o + n], buf.write) + assert buf.getvalue() == data + root = zarr.open_group(refkv.zarr.store(out.to_store()), mode="r", zarr_format=3) + return out, root, ir + + +def chunk_parts(out, q): + """(keep, [(offset, length), ...]) of chunk q's reference: its literal and its ranges of + source 0 (spec/virtualize/mp3.md §16.2 + ).""" + lit, *ranges = out.refs[f"samples/c/{q}/0"] + assert isinstance(lit, bytes) and len(lit) == 4 + assert all(len(r) == 2 for r in ranges) + return int.from_bytes(lit, "little"), ranges + + +def frames_of(ir): + """(offset, length) of each audio frame, in file order: the IR's data elements + (spec/virtualize/mp3.md §5.3 + ).""" + cols = ir.columns() + kind = np.frombuffer(cols["kind"], np.uint8) + start, length = np.frombuffer(cols["start"], " np.ndarray: + """miniaudio's decoding of the audio frames in one pass, int16 [samples, channels].""" + info = miniaudio.mp3_get_info(audio) + assert info.nchannels == channels + d = miniaudio.decode(audio, miniaudio.SampleFormat.SIGNED16, nchannels=channels, sample_rate=info.sample_rate) + return np.frombuffer(d.samples, dtype=np.int16).reshape(-1, channels) + + +@pytest.mark.parametrize("path", ACCEPTED, ids=lambda p: p.name) +def test_chunks_decode_as_the_stream_does(path, tmp_path): + """With 4 frames a chunk (so that every file has several chunks, each with its lead-in), + the array read through the mp3 codec is miniaudio's decoding of the audio frames in one + pass, sample for sample (spec/virtualize/mp3.md §4.1 + , §16.2 + ); the root's + metadata and the summary agree with the array; the file is rebuilt from the mirror.""" + out, root, ir = virtualized(path, tmp_path, chunk_frames=4) + meta = root.attrs["refkv_virtualized"]["mp3"] + arr = root["samples"] + got = arr[...] + frames = frames_of(ir) + assert len(frames) == meta["frames"] + assert got.dtype == np.int16 and got.shape == (meta["samples"], meta["channels"]) + assert meta["samples"] == meta["frames"] * meta["samples_per_frame"] + assert arr.chunks == (4 * meta["samples_per_frame"], meta["channels"]) + chunks = -(-meta["frames"] // 4) + assert out.summary["chunks"] == chunks and out.summary["chunkFrames"] == 4 + assert set(root.attrs) == {"zarr_conventions", "refkv_virtualized"} + want = sequential(audio_frames(path, ir), meta["channels"]) + assert want.shape == got.shape + assert np.array_equal(got, want) + # each chunk keeps its own frames' samples; its ranges are the frames from its lead-in's + # first to its own last, runs of consecutive frames merged, and the first has no lead-in + for q in range(chunks): + a, b = 4 * q, min(4 * q + 4, len(frames)) + keep, ranges = chunk_parts(out, q) + assert keep == (b - a) * meta["samples_per_frame"] + l = next(j for j, (o, _) in enumerate(frames) if o == ranges[0][0]) + assert (l == 0) if q == 0 else (l < a) + assert ranges[-1][0] + ranges[-1][1] == frames[b - 1][0] + frames[b - 1][1] + assert sum(n for _, n in ranges) == sum(n for _, n in frames[l:b]) + assert all(ranges[k][0] > ranges[k - 1][0] + ranges[k - 1][1] for k in range(1, len(ranges))) + assert out.data == {} # no data sources + doc = json.loads(out.bytes_entries["samples/zarr.json"]) + assert doc["codecs"] == [{"name": "mp3"}] and doc["dimension_names"] == ["time", "channel"] + assert doc["fill_value"] == 0 and doc["data_type"] == "int16" + + +@pytest.mark.parametrize("path", [p for p in ACCEPTED if (EXPECTED / f"{p.stem}.npy").exists()], ids=lambda p: p.name) +@pytest.mark.parametrize("chunk_frames", [None, 4]) +def test_matches_ffmpeg(path, chunk_frames, tmp_path): + """The array is ffmpeg's decoding of the audio frames (fixtures/mp3/expected, written by + the generator) within a few units per sample, whole (256 frames a chunk) and in chunks of + 4 frames with their lead-ins.""" + _, root, _ = virtualized(path, tmp_path, chunk_frames) + got = root["samples"][...].astype(np.int32) + want = np.load(EXPECTED / f"{path.stem}.npy").astype(np.int32) + assert got.shape == want.shape + diff = np.abs(got - want) + assert diff.max() <= FFMPEG_MAX and diff.mean() <= FFMPEG_MEAN, (diff.max(), diff.mean()) + + +def test_a_long_stream_has_chunks_of_256_frames(tmp_path): + """mp3_mpeg25_long.mp3 (333 frames of 576 samples) has two chunks by default; the second's + lead-in starts before frame 256, and both decode as the stream does.""" + path = FIXTURES / "mp3" / "mp3_mpeg25_long.mp3" + out, root, ir = virtualized(path, tmp_path) + meta = root.attrs["refkv_virtualized"]["mp3"] + assert meta["frames"] > 256 and out.summary["chunks"] == 2 + arr = root["samples"] + assert arr.chunks == (256 * 576, 1) + keep1, ranges1 = chunk_parts(out, 1) + assert keep1 == (meta["frames"] - 256) * 576 + # frames of 72 bytes hold 59 bytes of main data (72 - 4 - 9): the lead-in is frames 254 + # and 255, and before them the 5 frames (295 bytes) that hold the 255-byte reservoir + frames = frames_of(ir) + assert ranges1 == [(frames[249][0], frames[-1][0] + frames[-1][1] - frames[249][0])] + got = arr[...] + assert np.array_equal(got, sequential(audio_frames(path, ir), 1)) + + +# (summary members, root metadata members) each file must have +CASES = { + "mp3_mpeg1_stereo_cbr": ({"version": "MPEG-1", "sampleRate": 44100, "channels": 2, "bitrate": 128, "info": None, "tags": [], + "strayBytes": 0}, + {"samples_per_frame": 1152, "channel_mode": "joint_stereo", "crc_frames": 0, "bitrate_mode": "constant"}), + "mp3_mpeg1_mono_vbr": ({"version": "MPEG-1", "channels": 1, "bitrate": "variable", "info": "Xing"}, + {"bitrate_mode": "variable", "bitrate_kbps": None}), + "mp3_mpeg2_stereo_crc": ({"version": "MPEG-2", "sampleRate": 22050, "channels": 2}, {"samples_per_frame": 576}), + "mp3_mpeg2_mono_nores": ({"version": "MPEG-2", "sampleRate": 16000, "bitrate": 32}, {}), + "mp3_mpeg25_mono_8k": ({"version": "MPEG-2.5", "sampleRate": 8000, "channels": 1, "bitrate": 16}, {"samples_per_frame": 576}), + "mp3_mpeg25_long": ({"version": "MPEG-2.5", "sampleRate": 8000, "bitrate": 8, "chunks": 2}, {}), + "mp3_mpeg2_mono_16k": ({"frames": 22, "samples": 12672, "duration": 0.792, "tags": []}, {"stray_bytes": 0}), + "mp3_tags_id3v2_id3v1": ({"tags": ["id3v2", "id3v1"]}, + {"id3v1": {"title": "A title", "artist": "An artist", "album": "An album", "year": "2021", + "comment": "Some comment", "track": 7, "genre": 0}}), + "mp3_tags_id3v1_only": ({"tags": ["id3v1"]}, {}), + "mp3_tags_ape": ({"tags": ["ape"]}, {"ape": {"version": 2000, "items": 2, "size": 32 + 32 + 2 * 8 + 6 + 9 + 7 + 10}}), + "mp3_tags_ape_id3v1": ({"tags": ["id3v1", "ape"]}, {"ape": {"version": 2000, "items": 1, "size": 32 + 8 + 6 + 9}}), + "mp3_info_lavc": ({"tags": ["id3v2"], "info": "Info"}, {}), + "mp3_abr_xing": ({"info": "Xing", "bitrate": "variable"}, {}), + "mp3_id3v2_footer": ({"tags": ["id3v2"]}, {"id3v2": [{"version": [4, 0], "flags": 16, "size": 40, "footer": True}]}), + "mp3_id3v2_twice": ({}, {"id3v2": [{"version": [3, 0], "flags": 0, "size": 16, "footer": False}, + {"version": [4, 0], "flags": 0, "size": 24, "footer": False}]}), + "mp3_id3v2_padding": ({"strayBytes": 64}, {}), + "mp3_single_frame": ({"frames": 1, "chunks": 1, "samples": 576}, {}), + "mp3_crc_mixed": ({}, {"crc_frames": 5}), + "mp3_junk_between_frames": ({"strayBytes": 35 + 100}, {}), + "mp3_junk_false_sync": ({"strayBytes": 26}, {}), + "mp3_truncated_last_frame": ({"strayBytes": 72}, {}), + "mp3_id3v1_after_truncated": ({"strayBytes": 72, "tags": ["id3v1"]}, {}), +} + + +def test_every_accepted_fixture_has_a_case(): + assert {p.stem for p in ACCEPTED} == set(CASES) + + +def test_virtualizes_the_synthetic_files(tmp_path): + for name, (summary, members) in CASES.items(): + out, root, _ = virtualized(FIXTURES / "mp3" / f"{name}.mp3", tmp_path) + assert {**out.summary, **summary} == out.summary, name + meta = root.attrs["refkv_virtualized"]["mp3"] + for k, v in members.items(): + assert meta.get(k) == v, (name, k) + keys = ["version", "layer", "sample_rate", "channels", "channel_mode", "samples_per_frame", "frames", "samples", + "duration", "bitrate_mode", "bitrate_kbps", "crc_frames"] + keys += [k for k in ("info", "id3v2", "id3v1", "ape") if k in meta] + ["stray_bytes"] + assert list(meta) == keys, name + assert set(root.attrs) == {"zarr_conventions", "refkv_virtualized"}, name + + +def test_the_info_frame_is_read_and_not_audio(tmp_path): + """A LAME Xing frame and an ffmpeg Info frame: their fields are the root's `info`, and + the first audio frame is the frame after them (the first chunk's range starts there).""" + out, root, _ = virtualized(FIXTURES / "mp3" / "mp3_abr_xing.mp3", tmp_path) + info = root.attrs["refkv_virtualized"]["mp3"]["info"] + assert info["tag"] == "Xing" and info["encoder"].startswith("LAME") and info["frames"] == out.summary["frames"] + assert isinstance(info["delay"], int) and isinstance(info["padding"], int) + _, ranges = chunk_parts(out, 0) + assert ranges[0][0] > 0 and out.summary["strayBytes"] == 0 + out, root, _ = virtualized(FIXTURES / "mp3" / "mp3_info_lavc.mp3", tmp_path) + info = root.attrs["refkv_virtualized"]["mp3"]["info"] + assert info["tag"] == "Info" and info["encoder"].startswith("Lavc") and info["frames"] == out.summary["frames"] + + +@pytest.mark.parametrize("name,message", [ + ("mp3_reject_layer2", "MPEG-2 Layer II (the frame at 0) is not supported: only Layer III is"), + ("mp3_reject_layer1", "MPEG-1 Layer I (the frame at 0) is not supported: only Layer III is"), + ("mp3_reject_free_format", "free-format bitrate (the frame header at 0) is not supported"), + ("mp3_reject_sample_rate_change", "changes the sample rate from 16000 to 22050"), + ("mp3_reject_channels_change", "changes the channel count from 1 to 2"), + ("mp3_reject_version_change", "changes the version from MPEG-2 to MPEG-1"), + ("mp3_reject_layer_change", "changes the layer from III to II"), + ("mp3_reject_no_frames", "no MPEG audio frames"), + ("mp3_reject_only_id3v1", "not a file of any supported format"), + ("mp3_reject_id3v2_outside", "the 100010-byte ID3v2 tag at 0 is outside the 60-byte file"), + ("mp3_reject_id3v2_syncsafe", "the ID3v2 tag at 0 has a size byte that is not syncsafe (128)"), + ("mp3_reject_short", "file too short for an MPEG audio frame header"), +]) +def test_rejects(name, message): + """Each rejected input, with its message (a parameter change names the frame's offset + before the message checked here; a file no row of spec/virtualize.md §1.2 matches is + rejected by the host before the parser).""" + path = FIXTURES / "mp3" / f"{name}.mp3" + with pytest.raises(Rejected) as e: + via_ir(str(path), f"https://data.test/{name}.mp3") + assert message in str(e.value), str(e.value) + if "changes the" in message: + assert str(e.value).startswith("the frame at ") + + +def test_every_reject_fixture_has_a_test(): + assert {p.stem for p in MP3S if p.name.startswith("mp3_reject")} == { + name for name, _ in test_rejects.pytestmark[0].args[1]} diff --git a/python/tests/test_virtualize_refstore.py b/python/tests/test_virtualize_refstore.py index 9f781efc..ad23df9c 100644 --- a/python/tests/test_virtualize_refstore.py +++ b/python/tests/test_virtualize_refstore.py @@ -26,7 +26,7 @@ def proxy(tmp_path_factory): return Proxy(FIXTURES, tmp_path_factory.mktemp("cache")) -# (fixture, a store, checksums, format): a TIFF through the Rust core, NIfTI, MRC, a VSI slide (a +# (fixture, a store, checksums, format): a TIFF through the Rust core, NIfTI, MRC, an MP3, a VSI slide (a # file whose tile files make it a store output), Imaris IMS, # N5 stores (one with objects it ignores, one with an empty block), an OME-Zarr 0.4 store and a # Zarr v2 store (all the core's), and a SAFE product as a store (whose ranges start past byte 0, @@ -36,6 +36,7 @@ def proxy(tmp_path_factory): ("tiff/jpeg_gray.tif", False, True, "tiff"), ("nifti/nifti_block_x_split.nii", False, False, "nifti"), ("mrc/mrc_chunk_sections.mrc", False, True, "mrc"), + ("mp3/mp3_tags_id3v2_id3v1.mp3", False, False, "mp3"), ("vsi/vsi_rgb_jpeg.vsi", False, False, "vsi"), ("vsi/vsi_raw_tzc.vsi", False, True, "vsi"), ("ims/ims_latest_uint8.ims", False, False, "ims"), diff --git a/rust/refkv-ir/profiles.json b/rust/refkv-ir/profiles.json index 1f8a46a0..a49a22c5 100644 --- a/rust/refkv-ir/profiles.json +++ b/rust/refkv-ir/profiles.json @@ -200,5 +200,20 @@ "source": "Olympus VSI", "inputs": "Olympus cellSens VSI slides: a `.vsi` file and the tile files beside it, probed by key (uncompressed, JPEG and JPEG 2000 tiles)", "for": "Olympus cellSens whole-slide images (`.vsi` with its tile files)" + }, + { + "name": "mp3", + "section": 16, + "title": "MP3", + "uuid": "b6cb0047-9448-4fdc-b03e-10dd3d6aa829", + "version": 0, + "kind": "file", + "suffixes": [ + ".mp3" + ], + "reference": null, + "source": "MP3 (MPEG Layer III audio)", + "inputs": "MPEG-1, MPEG-2 and MPEG-2.5 Layer III audio files (`.mp3`), with their ID3v2, ID3v1 and APE tags; one array of samples, not an image", + "for": "MP3 audio files, as an array of samples (`.mp3`)" } ] diff --git a/rust/refkv-ir/schema/mp3.json b/rust/refkv-ir/schema/mp3.json new file mode 100644 index 00000000..b49e521b --- /dev/null +++ b/rust/refkv-ir/schema/mp3.json @@ -0,0 +1,66 @@ +{ + "source_model": "mp3", + "version": 1, + "about": "The source model of an MP3 file (spec/virtualize/mp3.md §5.3 ): the elements a parser emits, and the roles the file, each ID3v2 tag, the stream's first frame, a frame of another stream and the audio play, each with the constraints a file must meet to have the MP3 convention's layout (spec/virtualize/mp3.md §16.1 ). The parser checks them in this order; projections read a valid IR and check nothing.", + "limits": { + "chunk_frames": 256, + "reservoir_mpeg1": 511, + "reservoir_mpeg2": 255 + }, + "tables": { + "layers": { + "about": "the layer bits of a frame header: its name", + "1": "III", + "2": "II", + "3": "I" + } + }, + "elements": { + "about": "The IR of an MP3 file. n is a tag's size, L a frame's length, S the samples per channel of a frame (1152 for MPEG-1, 576 for MPEG-2 and 2.5), C the channel count.", + "id3v2/": {"kind": "struct", "about": "the k-th ID3v2 tag at the front of the file, k from 0; its extent the whole tag"}, + "id3v2//header": {"kind": "value", "type": "{id:ascii[3],version:u1[2],flags:u1,size:u1[4]}", "extent": "(at, 10): the tag's header"}, + "id3v2//data": {"kind": "value", "type": "bytes[n]", "extent": "(at + 10, n), when n > 0: the tag's frames and padding, opaque"}, + "id3v2//footer": {"kind": "value", "type": "bytes[10]", "extent": "(at + 10 + n, 10), when the header's footer flag (0x10) is set"}, + "info": {"kind": "value", "type": "bytes[L]", "extent": "the stream's first frame, when it holds a Xing, Info or VBRI tag: not an audio frame"}, + "frames": {"kind": "struct", "about": "the audio frames; its extent from the first frame's start to the last frame's end"}, + "frames/": {"kind": "data", "form": "{geometry: {samples: S, channels: C, data_type: int16}, codec: {name: mp3, version, sample_rate}, recipe: [[src, 0, null]]}", "extent": "(offset, L): audio frame j, j from 0, header included"}, + "id3v1": {"kind": "value", "type": "{tag:ascii[3],title:cstr[30],artist:cstr[30],album:cstr[30],year:ascii[4],comment:cstr[30],genre:u1}", "extent": "(size - 128, 128), when the file ends with TAG there"}, + "ape": {"kind": "value", "type": "bytes[n]", "extent": "the APE tag before the ID3v1 tag (or at the end), footer and header included, opaque"}, + "gaps/": {"kind": "gap", "about": "bytes no frame or tag holds: junk between frames, a truncated last frame, bytes after the last frame"} + }, + "roles": { + "file": { + "given": {"size": "the file's size"}, + "constraints": [ + {"require": "size >= 4", "message": "file too short for an MPEG audio frame header"} + ] + }, + "id3v2": { + "given": {"at": "the tag's offset", "size": "the file's size", "have": "size - at", "total": "10 + the size field + 10 for a footer", "syncsafe": "whether every size byte is below 0x80", "byte": "the first size byte that is not, when one is"}, + "constraints": [ + {"require": "have >= 10", "message": "the ID3v2 tag at {at} has no 10-byte header: the file ends at {size}"}, + {"require": "syncsafe", "message": "the ID3v2 tag at {at} has a size byte that is not syncsafe ({byte})"}, + {"require": "at + total <= size", "message": "the {total}-byte ID3v2 tag at {at} is outside the {size}-byte file"} + ] + }, + "stream": { + "given": {"at": "the first confirmed frame's offset", "version": "its version's name", "layer": "its layer bits (1: Layer III)", "layer_name": "its layer's name"}, + "constraints": [ + {"require": "layer == 1", "message": "{version} Layer {layer_name} (the frame at {at}) is not supported: only Layer III is"} + ] + }, + "frame": { + "given": {"at": "a confirmed frame's offset", "what": "the first parameter it changes: version, layer, sample rate or channel count", "from": "the stream's value", "to": "the frame's", "same": "false"}, + "constraints": [ + {"require": "same", "message": "the frame at {at} changes the {what} from {from} to {to}"} + ] + }, + "audio": { + "given": {"frames": "the audio frames found", "free": "the offset of the first free-format header met, when one was"}, + "constraints": [ + {"require": "frames >= 1 || !present(free)", "message": "free-format bitrate (the frame header at {free}) is not supported"}, + {"require": "frames >= 1", "message": "no MPEG audio frames"} + ] + } + } +} diff --git a/rust/refkv-ir/src/lib.rs b/rust/refkv-ir/src/lib.rs index 9ed85e65..1b1baf1c 100644 --- a/rust/refkv-ir/src/lib.rs +++ b/rust/refkv-ir/src/lib.rs @@ -19,6 +19,7 @@ pub mod ir; pub mod json; pub mod lv; pub mod mirror; +pub mod mp3; pub mod mrc; pub mod n5; pub mod nd2; @@ -77,6 +78,7 @@ parser!(czi::Czi); parser!(dicom::Dicom); parser!(nifti::Nifti); parser!(mrc::Mrc); +parser!(mp3::Mp3); parser!(ims::Ims); parser!(safe::Safe); diff --git a/rust/refkv-ir/src/mp3.rs b/rust/refkv-ir/src/mp3.rs new file mode 100644 index 00000000..d66cc7af --- /dev/null +++ b/rust/refkv-ir/src/mp3.rs @@ -0,0 +1,503 @@ +//! A sans-IO parser of MP3 files (MPEG-1, MPEG-2 and MPEG-2.5 Layer III audio) into the IR +//! (spec/virtualize/mp3.md §16 +//! , and the +//! source model of §5.3 ). +//! +//! One round: the whole file (an MP3 has no index; each frame's header gives the next). The +//! schema (`schema/mp3.json`) holds every check, in the profile's order. The IR is the ID3v2 +//! tags at the front (a struct each), the Xing, Info or VBRI frame (one opaque value, when the +//! stream starts with one), the audio frames (a `data` element each, under `frames`), the ID3v1 +//! tag (one record value) and the APE tag (one opaque value) at the end, and gaps for the bytes +//! that are none of these. + +use crate::check; +use crate::expr::V; +use crate::fed::Fed; +use crate::ir::*; +use crate::nd2::Step; +use crate::rules::{self, Rules, Vars, flag, num, text}; +use serde_json::{json, Value as J}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +/// The versions by their header bits, and the layers by theirs (1 is Layer III). +pub const VERSIONS: [&str; 4] = ["MPEG-2.5", "reserved", "MPEG-2", "MPEG-1"]; +pub const LAYERS: [&str; 4] = ["reserved", "III", "II", "I"]; +/// The sample rates by version then index, and the channel modes by their bits. +const RATES: [[u32; 3]; 4] = [[11025, 12000, 8000], [0, 0, 0], [22050, 24000, 16000], [44100, 48000, 32000]]; +pub const MODES: [&str; 4] = ["stereo", "joint_stereo", "dual_channel", "mono"]; +/// Bitrates in kbps: MPEG-1, then MPEG-2 and 2.5; Layer I, II, III; then the index. +const BITRATES: [[[u32; 15]; 3]; 2] = [ + [ + [0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448], + [0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384], + [0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320], + ], + [ + [0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256], + [0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160], + [0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160], + ], +]; +/// The most bytes of earlier frames a frame's main data may begin in (`main_data_begin`, 9 +/// bits in MPEG-1 and 8 in MPEG-2 and 2.5), by version: the bit reservoir a decoder must hold +/// before a frame to decode it as the stream does (spec/virtualize/mp3.md §16.2 +/// ). +pub const RESERVOIR: [u64; 4] = [255, 0, 255, 511]; + +/// The frames of a chunk (spec/virtualize/mp3.md §4.1 +/// ), but in tests +/// (`set_chunk_frames`). Each run reads it once, into its facts. +pub const DEFAULT_CHUNK_FRAMES: usize = 256; +static CHUNK_FRAMES: AtomicUsize = AtomicUsize::new(DEFAULT_CHUNK_FRAMES); + +/// For tests: the frames of a chunk (None: the default, 256), so that small files have several +/// chunks and lead-ins. +pub fn set_chunk_frames(n: Option) { + CHUNK_FRAMES.store(n.unwrap_or(DEFAULT_CHUNK_FRAMES).max(1), Ordering::Relaxed); +} + +pub fn chunk_frames() -> usize { + CHUNK_FRAMES.load(Ordering::Relaxed) +} + +/// A frame header's fields (spec/virtualize/mp3.md §2 +/// ). +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub struct Head { + /// the version bits: 0 MPEG-2.5, 2 MPEG-2, 3 MPEG-1 + pub version: u8, + /// the layer bits: 1 Layer III, 2 Layer II, 3 Layer I + pub layer: u8, + /// whether a 16-bit CRC follows the header + pub crc: bool, + pub bitrate: u8, + pub rate: u8, + pub padding: bool, + /// the channel mode bits: 0 stereo, 1 joint stereo, 2 dual channel, 3 mono + pub mode: u8, +} + +impl Head { + /// The header at the start of `b`, when `b` starts with a **valid** one: the 11-bit sync, a + /// version that is not reserved, a layer that is not reserved, a bitrate index from 1 to 14 + /// and a sample rate index from 0 to 2. + pub fn parse(b: &[u8]) -> Option { + if b.len() < 4 || b[0] != 0xFF || b[1] & 0xE0 != 0xE0 { + return None; + } + let (version, layer) = ((b[1] >> 3) & 3, (b[1] >> 1) & 3); + let (bitrate, rate) = (b[2] >> 4, (b[2] >> 2) & 3); + if version == 1 || layer == 0 || bitrate == 0 || bitrate == 15 || rate == 3 { + return None; + } + Some(Head { version, layer, crc: b[1] & 1 == 0, bitrate, rate, padding: b[2] & 2 != 0, mode: b[3] >> 6 }) + } + + /// Whether `b` starts with a free-format header: valid but for a bitrate index of 0. + pub fn free_format(b: &[u8]) -> bool { + b.len() >= 4 && b[0] == 0xFF && b[1] & 0xE0 == 0xE0 && (b[1] >> 3) & 3 != 1 && (b[1] >> 1) & 3 != 0 + && b[2] >> 4 == 0 && (b[2] >> 2) & 3 != 3 + } + + pub fn rate(&self) -> u32 { + RATES[self.version as usize][self.rate as usize] + } + + pub fn channels(&self) -> u64 { + if self.mode == 3 { 1 } else { 2 } + } + + pub fn kbps(&self) -> u32 { + BITRATES[(self.version != 3) as usize][(3 - self.layer) as usize][self.bitrate as usize] + } + + /// The frame's length in bytes, header included. + pub fn length(&self) -> u64 { + let (br, sr, pad) = (self.kbps() as u64 * 1000, self.rate() as u64, self.padding as u64); + match self.layer { + 3 => (12 * br / sr + pad) * 4, + 2 => 144 * br / sr + pad, + _ if self.version == 3 => 144 * br / sr + pad, + _ => 72 * br / sr + pad, + } + } + + /// The samples per channel a Layer III frame decodes to. + pub fn samples(&self) -> u64 { + if self.version == 3 { 1152 } else { 576 } + } + + /// The side information's length (Layer III). + pub fn side(&self) -> u64 { + match (self.version == 3, self.channels() == 1) { + (true, true) => 17, + (true, false) => 32, + (false, true) => 9, + (false, false) => 17, + } + } + + /// The main data's length: the frame less its header, CRC and side information. + pub fn main(&self) -> u64 { + self.length().saturating_sub(4 + 2 * self.crc as u64 + self.side()) + } + + /// Whether `o` is a frame of the same stream: the same version, layer, sample rate and + /// channel count (the bitrate, padding, CRC and channel mode may differ frame by frame). + pub fn same_stream(&self, o: &Head) -> bool { + self.version == o.version && self.layer == o.layer && self.rate == o.rate && self.channels() == o.channels() + } +} + +/// Whether a file's first bytes are an MP3 file's (spec/virtualize.md §1.2 +/// ): `ID3` at 0, or a +/// frame header of any layer whose sync, version, layer and sample rate index are valid, whatever +/// its bitrate index (the profile then rejects a layer other than III, or a free-format +/// bitrate, by name). +pub fn detect(head: &[u8]) -> bool { + (head.len() >= 3 && &head[..3] == b"ID3") + || (head.len() >= 4 && head[0] == 0xFF && head[1] & 0xE0 == 0xE0 && (head[1] >> 3) & 3 != 1 && (head[1] >> 1) & 3 != 0 + && (head[2] >> 2) & 3 != 3) +} + +fn u32be(b: &[u8], at: usize) -> Option { + b.get(at..at + 4).map(|a| u32::from_be_bytes(a.try_into().unwrap())) +} + +fn u16be(b: &[u8], at: usize) -> Option { + b.get(at..at + 2).map(|a| u16::from_be_bytes(a.try_into().unwrap())) +} + +fn u32le(b: &[u8], at: usize) -> u32 { + u32::from_le_bytes(b[at..at + 4].try_into().unwrap()) +} + +/// The offset in a frame of its Xing or Info tag, if it holds one: after the header, the CRC +/// and the side information. +fn xing_at(f: &[u8], h: &Head) -> Option { + let at = 4 + 2 * h.crc as usize + h.side() as usize; + matches!(f.get(at..at + 4), Some(b"Xing") | Some(b"Info")).then_some(at) +} + +/// Whether the frame `f` is an info frame: a Xing or Info tag, or a VBRI tag at 36. +fn is_info(f: &[u8], h: &Head) -> bool { + xing_at(f, h).is_some() || f.get(36..40) == Some(b"VBRI") +} + +/// The fields of an info frame (spec/virtualize/mp3.md §5.1 +/// ): the tag, the +/// frame and byte counts and the quality it holds (null when it does not), and the encoder, +/// delay and padding of a LAME tag after a Xing or Info tag. +fn info_json(f: &[u8], h: &Head) -> J { + let (mut frames, mut bytes, mut quality, mut encoder, mut delay, mut padding) = (J::Null, J::Null, J::Null, J::Null, J::Null, J::Null); + let tag = if let Some(at) = xing_at(f, h) { + let flags = u32be(f, at + 4).unwrap_or(0); + let mut pos = at + 8; + let field = |pos: &mut usize| { + let v = u32be(f, *pos).map_or(J::Null, |v| json!(v)); + *pos += 4; + v + }; + if flags & 1 != 0 { + frames = field(&mut pos); + } + if flags & 2 != 0 { + bytes = field(&mut pos); + } + if flags & 4 != 0 { + pos += 100; // the seek table + } + if flags & 8 != 0 { + quality = field(&mut pos); + } + // the LAME tag: a 9-byte encoder version (`LAME3.99r`; `LAME4.0`, a space and a NUL), + // then its fields (the delays at 21) + if let Some(e) = f.get(pos..pos + 9) { + let e = &e[..e.iter().position(|&c| c == 0).unwrap_or(9)]; + if !e.is_empty() && e.iter().all(|&c| (0x20..0x7F).contains(&c)) && e[0] != b' ' { + encoder = json!(String::from_utf8_lossy(e).trim_end().to_string()); + if let Some(d) = f.get(pos + 21..pos + 24) { + delay = json!((d[0] as u32) << 4 | (d[1] as u32) >> 4); + padding = json!((d[1] as u32 & 0xF) << 8 | d[2] as u32); + } + } + } + String::from_utf8_lossy(&f[at..at + 4]).to_string() + } else { + // VBRI: version, delay, quality, bytes, frames + delay = u16be(f, 42).map_or(J::Null, |v| json!(v)); + quality = u16be(f, 44).map_or(J::Null, |v| json!(v)); + bytes = u32be(f, 46).map_or(J::Null, |v| json!(v)); + frames = u32be(f, 50).map_or(J::Null, |v| json!(v)); + "VBRI".to_string() + }; + json!({"tag": tag, "frames": frames, "bytes": bytes, "quality": quality, "encoder": encoder, "delay": delay, "padding": padding}) +} + +/// Which parameter a confirmed frame of another stream changes: the first of the version, the +/// layer, the sample rate and the channel count that differs, with the two values. +fn differs(s: &Head, h: &Head) -> (&'static str, String, String) { + if s.version != h.version { + ("version", VERSIONS[s.version as usize].into(), VERSIONS[h.version as usize].into()) + } else if s.layer != h.layer { + ("layer", LAYERS[s.layer as usize].into(), LAYERS[h.layer as usize].into()) + } else if s.rate != h.rate { + ("sample rate", s.rate().to_string(), h.rate().to_string()) + } else { + ("channel count", s.channels().to_string(), h.channels().to_string()) + } +} + +/// The ID3v1 tag as one record type (conventions §8.6 +/// ). +pub const ID3V1_TYPE: &str = "{tag:ascii[3],title:cstr[30],artist:cstr[30],album:cstr[30],year:ascii[4],comment:cstr[30],genre:u1}"; +/// An ID3v2 tag's 10-byte header as one record type. +pub const ID3V2_HEADER_TYPE: &str = "{id:ascii[3],version:u1[2],flags:u1,size:u1[4]}"; + +#[derive(Clone, Copy, PartialEq, Debug)] +enum Phase { + Start, + Scan, + Done, +} + +pub struct Mp3 { + size: u64, + phase: Phase, + fed: Fed, + ir: Ir, + rules: &'static Rules, + facts: J, +} + +impl Mp3 { + pub fn new(size: u64) -> Self { + Mp3 { size, phase: Phase::Start, fed: Fed::default(), ir: Ir::new(size), rules: rules::mp3(), facts: J::Null } + } + + pub fn feed(&mut self, offset: u64, data: Vec) { + self.fed.feed(offset, data); + } + + fn check(&self, role: &str, mut env: Vars<'static>) -> Res<()> { + self.rules.check(role, &mut env) + } + + pub fn step(&mut self) -> Result { + match self.phase { + Phase::Start => { + self.phase = Phase::Scan; + Ok(Step::Read(vec![(0, self.size)])) + } + Phase::Scan => { + self.scan()?; + self.phase = Phase::Done; + Ok(Step::Done) + } + Phase::Done => Ok(Step::Done), + } + } + + /// The whole file (spec/virtualize/mp3.md §16.1 + /// ): the ID3v2 + /// tags, the trailing tags, then the frames between them, and the elements of each. + fn scan(&mut self) -> Res<()> { + let n = self.size; + let d = self.fed.get(0, n).ok_or("internal: the file was not read")?.to_vec(); + self.fed.clear(); + self.check("file", rules::env([("size", num(n as f64))]))?; + // the ID3v2 tags at the front + let mut p: u64 = 0; + let mut id3v2 = Vec::new(); + while d.len() as u64 >= p + 3 && &d[p as usize..p as usize + 3] == b"ID3" { + let at = p as usize; + let have = n - p; + let (size, footer, bad) = if have >= 10 { + let s = &d[at + 6..at + 10]; + let size = s.iter().fold(0u64, |a, &c| a << 7 | (c & 0x7F) as u64); + (size, d[at + 5] & 0x10 != 0, s.iter().position(|&c| c >= 0x80)) + } else { + (0, false, None) + }; + let total = 10 + size + if footer { 10 } else { 0 }; + self.check("id3v2", rules::env([ + ("at", num(p as f64)), ("size", num(n as f64)), ("have", num(have as f64)), ("total", num(total as f64)), + ("syncsafe", flag(bad.is_none())), ("byte", bad.map_or(V::Absent, |k| num(d[at + 6 + k] as f64))), + ]))?; + let tag = self.ir.struct_(0, "id3v2/", id3v2.len() as u64, 0, Some((p, total)))?; + self.ir.value(tag, "header", NO_INDEX, ID3V2_HEADER_TYPE, 0, (p, 10), Some(&d[at..at + 10]))?; + if size > 0 { + self.ir.value(tag, "data", NO_INDEX, &format!("bytes[{size}]"), 0, (p + 10, size), None)?; + } + if footer { + self.ir.value(tag, "footer", NO_INDEX, "bytes[10]", 0, (p + 10 + size, 10), None)?; + } + id3v2.push(json!({"version": [d[at + 3], d[at + 4]], "flags": d[at + 5], "size": size, "footer": footer})); + p += total; + } + let a = p; + // the tags at the end: an ID3v1 tag, then an APE tag before it + let mut e = n; + let mut id3v1 = None; + if e >= a + 128 && &d[(e - 128) as usize..(e - 125) as usize] == b"TAG" { + e -= 128; + id3v1 = Some(e); + } + let mut ape = None; + if e >= a + 32 && &d[(e - 32) as usize..(e - 24) as usize] == b"APETAGEX" { + let f = (e - 32) as usize; + let (version, size, items, flags) = (u32le(&d, f + 8), u32le(&d, f + 12) as u64, u32le(&d, f + 16), u32le(&d, f + 20)); + let total = size + if flags & 0x8000_0000 != 0 { 32 } else { 0 }; + if size >= 32 && total <= e - a { + e -= total; + ape = Some((e, total, version, items)); + } + } + // the frames: a chain from each confirmed frame's end; a scan for the next after junk + let mut frames: Vec<(u64, Head)> = Vec::new(); + let mut info: Option<(u64, Head)> = None; + let mut stream: Option = None; + let mut free: Option = None; + let mut chained = false; + let mut p = a; + while p + 4 <= e { + let at = p as usize; + match Head::parse(&d[at..at + 4]) { + Some(h) => { + let len = h.length(); + let fits = p + len <= e; + let consistent = stream.is_none_or(|s| h.same_stream(&s)); + let next = || { + let q = (p + len) as usize; + q + 4 <= e as usize && Head::parse(&d[q..q + 4]).is_some_and(|g| g.same_stream(&h)) + }; + let confirmed = fits && ((chained && consistent) || (stream.is_none() && p + len == e) || next()); + if confirmed { + match stream { + None => { + self.check("stream", rules::env([ + ("at", num(p as f64)), ("version", text(VERSIONS[h.version as usize])), + ("layer", num(h.layer as f64)), ("layer_name", text(LAYERS[h.layer as usize])), + ]))?; + stream = Some(h); + } + Some(s) if !consistent => { + let (what, from, to) = differs(&s, &h); + self.check("frame", rules::env([ + ("at", num(p as f64)), ("what", text(what)), ("from", text(&from)), ("to", text(&to)), ("same", flag(false)), + ]))?; + } + _ => {} + } + if frames.is_empty() && info.is_none() && is_info(&d[at..at + len as usize], &h) { + info = Some((p, h)); + } else { + frames.push((p, h)); + } + p += len; + chained = true; + continue; + } + } + None => { + if free.is_none() && Head::free_format(&d[at..at + 4]) { + free = Some(p); + } + } + } + p += 1; + chained = false; + } + self.check("audio", rules::env([("frames", num(frames.len() as f64)), ("free", free.map_or(V::Absent, |o| num(o as f64)))]))?; + let s = stream.ok_or("internal: no stream")?; + // the elements, in the file's order + let info_json = match info { + Some((o, h)) => { + let len = h.length(); + self.ir.value(0, "info", NO_INDEX, &format!("bytes[{len}]"), 0, (o, len), Some(&d[o as usize..(o + len) as usize]))?; + info_json(&d[o as usize..(o + len) as usize], &h) + } + None => J::Null, + }; + let (first_o, last) = (frames[0].0, frames[frames.len() - 1]); + let span = last.0 + last.1.length() - first_o; + let frames_struct = self.ir.struct_(0, "frames", NO_INDEX, 0, Some((first_o, span)))?; + let form = json!({ + "geometry": {"samples": s.samples(), "channels": s.channels(), "data_type": "int16"}, + "codec": {"name": "mp3", "version": VERSIONS[s.version as usize], "sample_rate": s.rate()}, + "recipe": [["src", 0, null]], + }) + .to_string(); + let mut first = 0u32; + let mut main = Vec::with_capacity(frames.len()); + let mut used = 0u64; + let (mut crc_frames, mut kbps) = (0u64, Some(frames[0].1.kbps())); + for (j, (o, h)) in frames.iter().enumerate() { + let i = self.ir.data(frames_struct, "", j as u64, 0, (*o, h.length()), &form)?; + if j == 0 { + first = i; + } + main.push(h.main()); + used += h.length(); + crc_frames += h.crc as u64; + if kbps != Some(h.kbps()) { + kbps = None; + } + } + let id3v1_json = match id3v1 { + Some(o) => { + let i = self.ir.value(0, "id3v1", NO_INDEX, ID3V1_TYPE, 0, (o, 128), Some(&d[o as usize..o as usize + 128]))?; + json!(i) + } + None => J::Null, + }; + let ape_json = match ape { + Some((o, total, version, items)) => { + self.ir.value(0, "ape", NO_INDEX, &format!("bytes[{total}]"), 0, (o, total), None)?; + json!({"version": version, "size": total, "items": items}) + } + None => J::Null, + }; + let stray = e - a - used - info.map_or(0, |(_, h)| h.length()); + self.facts = json!({ + "frames": first, "count": frames.len(), "version": s.version, "layer": 3, "sample_rate": s.rate(), + "channels": s.channels(), "mode": frames[0].1.mode, "spf": s.samples(), "main": main, + "kbps": kbps, "crc_frames": crc_frames, "info": info_json, "id3v2": id3v2, "id3v1": id3v1_json, + "ape": ape_json, "stray": stray, "chunk_frames": chunk_frames(), + }); + Ok(()) + } + + pub fn finish(mut self) -> Result<(Ir, J), String> { + if self.phase != Phase::Done { + return Err("internal: the parse is not done".into()); + } + self.ir.sort_values(); + check::finish(&mut self.ir)?; + Ok((self.ir, self.facts)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// A 128 kbps MPEG-1 Layer III header at 44.1 kHz, joint stereo, no CRC, no padding: 417 + /// bytes, 1152 samples, 32 bytes of side information. + #[test] + fn a_header_gives_the_frames_length_and_layout() { + let h = Head::parse(&[0xFF, 0xFB, 0x90, 0x64]).unwrap(); + assert_eq!((h.version, h.layer, h.crc, h.rate(), h.channels(), h.kbps()), (3, 1, false, 44100, 2, 128)); + assert_eq!((h.length(), h.samples(), h.side(), h.main()), (417, 1152, 32, 381)); + // MPEG-2.5 at 8 kHz, 16 kbps, mono, with padding and a CRC: 72 * 16000 / 8000 + 1 = 145 + let h = Head::parse(&[0xFF, 0xE2, 0x2A, 0xC0]).unwrap(); + assert_eq!((h.version, h.crc, h.rate(), h.channels(), h.length(), h.samples(), h.side(), h.main()), (0, true, 8000, 1, 145, 576, 9, 130)); + // a reserved version, a reserved layer, a free-format bitrate, an invalid sample rate + for b in [[0xFF, 0xEB, 0x90, 0x64], [0xFF, 0xF9, 0x90, 0x64], [0xFF, 0xFB, 0x00, 0x64], [0xFF, 0xFB, 0x9C, 0x64]] { + assert!(Head::parse(&b).is_none(), "{b:?}"); + } + assert!(Head::free_format(&[0xFF, 0xFB, 0x00, 0x64])); + assert!(detect(b"ID3\x04") && detect(&[0xFF, 0xFB, 0x90, 0x64]) && detect(&[0xFF, 0xFB, 0x00, 0x64]) && !detect(b"RIFF")); + assert!(!detect(&[0xFF, 0xFB, 0x9C, 0x64]) && !detect(&[0xFF, 0xEB, 0x90, 0x64])); + } +} diff --git a/rust/refkv-ir/src/project/mod.rs b/rust/refkv-ir/src/project/mod.rs index b3d3529a..cd99895f 100644 --- a/rust/refkv-ir/src/project/mod.rs +++ b/rust/refkv-ir/src/project/mod.rs @@ -16,6 +16,7 @@ mod czi; mod dicom; mod ims; pub mod n5; +mod mp3; mod mrc; mod nd2; mod ndpi; @@ -45,6 +46,7 @@ pub fn project(format: Format, ir: &Ir, facts: &J, url: &str, copied: &Copied) - Format::Dicom => dicom::project(ir, facts, url), Format::Nifti => nifti::project(ir, facts, url, copied), Format::Mrc => mrc::project(ir, facts, url, copied), + Format::Mp3 => mp3::project(ir, facts, url, copied), Format::Ims => ims::project(ir, facts, url), Format::Safe => safe::project(ir, facts, url), Format::Ndpi => ndpi::project(ir, facts, url), diff --git a/rust/refkv-ir/src/project/mp3.rs b/rust/refkv-ir/src/project/mp3.rs new file mode 100644 index 00000000..70d93610 --- /dev/null +++ b/rust/refkv-ir/src/project/mp3.rs @@ -0,0 +1,158 @@ +//! The MP3 projection (spec/virtualize/mp3.md §4 +//! , and the root's +//! source metadata of §5 +//! ) from a valid +//! IR: one array of samples whose chunks are runs of frames, each referenced with the frames +//! before it that a decoder needs (the lead-in, §16.2 +//! ). + +use super::{arr, json_text, n, Copied}; +use crate::ir::Ir; +use crate::mp3::{MODES, RESERVOIR, VERSIONS}; +use crate::out::{array_json, declare, group_doc, Out, Part}; +use crate::refs::Refs; +use serde_json::{json, Map, Value as J}; + +/// The array's path. +pub const ARRAY: &str = "samples"; + +/// The first frame of the lead-in of the chunk that starts at frame `a` (§16.2 +/// ): none for the +/// first chunk; else the two frames before the chunk, and before them the fewest frames whose +/// main data (`main`, per frame) holds at least `reservoir` bytes, or every frame from the +/// first when they do not. +pub fn lead(a: usize, main: &[u64], reservoir: u64) -> usize { + if a == 0 { + return 0; + } + let mut l = a.saturating_sub(2); + let mut have = 0u64; + while l > 0 && have < reservoir { + l -= 1; + have += main[l]; + } + l +} + +/// The ID3v1 tag's fields as the root's source metadata writes them (§5.1 +/// ). +fn id3v1_json(b: &[u8]) -> J { + let mut m = Map::new(); + m.insert("title".into(), json_text(&b[3..33])); + m.insert("artist".into(), json_text(&b[33..63])); + m.insert("album".into(), json_text(&b[63..93])); + m.insert("year".into(), json_text(&b[93..97])); + m.insert("comment".into(), json_text(&b[97..127])); + // ID3v1.1: a NUL at byte 125 makes byte 126 the track number + m.insert("track".into(), if b[125] == 0 && b[126] != 0 { json!(b[126]) } else { J::Null }); + m.insert("genre".into(), json!(b[127])); + J::Object(m) +} + +pub fn project(ir: &Ir, facts: &J, url: &str, _copied: &Copied) -> Result { + let first = n(&facts["frames"]) as usize; + let count = n(&facts["count"]) as usize; + let (spf, channels, rate) = (n(&facts["spf"]), n(&facts["channels"]), n(&facts["sample_rate"])); + let version = n(&facts["version"]) as usize; + let main: Vec = arr(&facts["main"]).iter().map(n).collect(); + let per_chunk = n(&facts["chunk_frames"]).max(1) as usize; + if count == 0 || main.len() != count { + return Err("internal: the facts do not describe the frames".into()); + } + let samples = count as u64 * spf; + + // the root (§5.1 ) + let mut own = Map::new(); + own.insert("version".into(), json!(VERSIONS[version])); + own.insert("layer".into(), json!(3)); + own.insert("sample_rate".into(), json!(rate)); + own.insert("channels".into(), json!(channels)); + own.insert("channel_mode".into(), json!(MODES[n(&facts["mode"]) as usize])); + own.insert("samples_per_frame".into(), json!(spf)); + own.insert("frames".into(), json!(count)); + own.insert("samples".into(), json!(samples)); + own.insert("duration".into(), json!(samples as f64 / rate as f64)); + let kbps = &facts["kbps"]; + own.insert("bitrate_mode".into(), json!(if kbps.is_null() { "variable" } else { "constant" })); + own.insert("bitrate_kbps".into(), kbps.clone()); + own.insert("crc_frames".into(), facts["crc_frames"].clone()); + if !facts["info"].is_null() { + own.insert("info".into(), facts["info"].clone()); + } + if arr(&facts["id3v2"]).first().is_some() { + own.insert("id3v2".into(), facts["id3v2"].clone()); + } + if let Some(i) = facts["id3v1"].as_u64() { + let b = ir.value_bytes(i as u32).ok_or("internal: the ID3v1 tag is not held")?; + own.insert("id3v1".into(), id3v1_json(b)); + } + if !facts["ape"].is_null() { + own.insert("ape".into(), facts["ape"].clone()); + } + own.insert("stray_bytes".into(), facts["stray"].clone()); + let mut out = Out::new(url); + out.json("zarr.json", &group_doc(declare(Map::new(), "mp3", Some(url), Some(J::Object(own))))); + + // the array (§4.1 ) + let shape = [samples, channels]; + let array = array_json(&shape, "int16", json!([per_chunk as u64 * spf, channels]), json!([{"name": "mp3"}]), &["time", "channel"]); + out.json(&format!("{ARRAY}/zarr.json"), &array); + let form = ir.form_id(first as u32).ok_or("internal: a frame has no form")?; + let chunks = count.div_ceil(per_chunk); + let mut refs = Refs::new(ir, out); + for q in 0..chunks { + let a = q * per_chunk; + let b = (a + per_chunk).min(count); + let keep = ((b - a) as u64 * spf) as u32; + let l = lead(a, &main, RESERVOIR[version]); + // the frames l to b - 1, a range per run of frames that follow each other (the bytes + // between frames, which are no frame, are left out: a decoder resyncs on them) + let mut parts = vec![Part::Lit(keep.to_le_bytes().to_vec())]; + for j in l..b { + let (o, n) = (ir.start[first + j], ir.len[first + j]); + match parts.last_mut() { + Some(Part::Src(po, pn)) if *po + *pn == o => *pn += n, + _ => parts.push(Part::Src(o, n)), + } + } + refs.chunk(format!("{ARRAY}/c/{q}/0"), ir.start[first + a], ir.len[first + a], form, Some(parts), q as u64)?; + } + let mut out = refs.out; + let mut tags = Vec::new(); + if arr(&facts["id3v2"]).first().is_some() { + tags.push("id3v2"); + } + if !facts["id3v1"].is_null() { + tags.push("id3v1"); + } + if !facts["ape"].is_null() { + tags.push("ape"); + } + out.summary = json!({ + "version": VERSIONS[version], "sampleRate": rate, "channels": channels, "frames": count, "samples": samples, + "duration": samples as f64 / rate as f64, "bitrate": if kbps.is_null() { json!("variable") } else { kbps.clone() }, + "chunkFrames": per_chunk, "chunks": chunks, "info": facts["info"]["tag"].clone(), "tags": tags, + "strayBytes": facts["stray"].clone(), + }); + Ok(out) +} + +#[cfg(test)] +mod tests { + use super::lead; + + /// Frames of 100 bytes of main data, a reservoir of 511: the first chunk has no lead-in; + /// a chunk at frame 8 takes frames 6 and 7, and before them the 6 frames that hold 600 + /// bytes (frames 0 to 5): all of them; at frame 12, frames 10 and 11 and then frames 4 + /// to 9 (600 bytes), so the lead-in starts at 4; a small reservoir takes one frame. + #[test] + fn the_lead_in_holds_the_reservoir_before_the_two_frames_before_the_chunk() { + let main = vec![100u64; 20]; + assert_eq!(lead(0, &main, 511), 0); + assert_eq!(lead(1, &main, 511), 0); + assert_eq!(lead(8, &main, 511), 0); + assert_eq!(lead(12, &main, 511), 4); + assert_eq!(lead(12, &main, 50), 9); + assert_eq!(lead(12, &main, 0), 10); + } +} diff --git a/rust/refkv-ir/src/rules.rs b/rust/refkv-ir/src/rules.rs index ecbd9d40..54cb77ad 100644 --- a/rust/refkv-ir/src/rules.rs +++ b/rust/refkv-ir/src/rules.rs @@ -39,6 +39,7 @@ pub static TIFF_SCHEMA: &str = include_str!("../schema/tiff.json"); pub static CZI_SCHEMA: &str = include_str!("../schema/czi.json"); pub static NIFTI_SCHEMA: &str = include_str!("../schema/nifti.json"); pub static MRC_SCHEMA: &str = include_str!("../schema/mrc.json"); +pub static MP3_SCHEMA: &str = include_str!("../schema/mp3.json"); pub static IMS_SCHEMA: &str = include_str!("../schema/ims.json"); pub static SAFE_SCHEMA: &str = include_str!("../schema/safe.json"); pub static NDPI_SCHEMA: &str = include_str!("../schema/ndpi.json"); @@ -85,6 +86,11 @@ pub fn mrc() -> &'static Rules { S.get_or_init(|| Rules::new(MRC_SCHEMA).expect("the MRC schema is valid")) } +pub fn mp3() -> &'static Rules { + static S: OnceLock = OnceLock::new(); + S.get_or_init(|| Rules::new(MP3_SCHEMA).expect("the MP3 schema is valid")) +} + pub fn vsi() -> &'static Rules { static S: OnceLock = OnceLock::new(); S.get_or_init(|| Rules::new(VSI_SCHEMA).expect("the VSI schema is valid")) diff --git a/rust/refkv-ir/src/run.rs b/rust/refkv-ir/src/run.rs index 23cc6477..d2bf33fd 100644 --- a/rust/refkv-ir/src/run.rs +++ b/rust/refkv-ir/src/run.rs @@ -8,6 +8,7 @@ use crate::ims::Ims; use crate::ir::Ir; use crate::nd2::{Nd2, Step}; use crate::plan::{Planner, Request}; +use crate::mp3::Mp3; use crate::mrc::Mrc; use crate::nifti::Nifti; use crate::safe::Safe; @@ -31,6 +32,8 @@ pub enum Format { Ndpi, /// an MRC2014 file (a CCP4 map, an image stack, a volume or a volume stack) Mrc, + /// an MP3 file (MPEG-1, MPEG-2 or MPEG-2.5 Layer III audio), read whole + Mp3, /// An Olympus VSI slide: a `.vsi` file whose tile files lie beside it, virtualized as a /// store run of the `vsi` store format (spec/virtualize/vsi.md §15.2 /// ), never @@ -52,6 +55,7 @@ impl Format { Format::Safe => "safe", Format::Ndpi => "ndpi", Format::Mrc => "mrc", + Format::Mp3 => "mp3", Format::Vsi => "vsi", } } @@ -62,9 +66,9 @@ impl Format { matches!(self, Format::Vsi) } - /// The format of a name ("nd2", "tiff", "czi", "dicom", "nifti", "ims", "safe", "ndpi", "mrc", "vsi"). + /// The format of a name ("nd2", "tiff", "czi", "dicom", "nifti", "ims", "safe", "ndpi", "mrc", "vsi", "mp3"). pub fn from_name(s: &str) -> Option { - [Format::Nd2, Format::Tiff, Format::Czi, Format::Dicom, Format::Nifti, Format::Ims, Format::Safe, Format::Ndpi, Format::Mrc, Format::Vsi].into_iter().find(|f| f.name() == s) + [Format::Nd2, Format::Tiff, Format::Czi, Format::Dicom, Format::Nifti, Format::Ims, Format::Safe, Format::Ndpi, Format::Mrc, Format::Vsi, Format::Mp3].into_iter().find(|f| f.name() == s) } /// The format a file's first bytes give, if one of these: a hint, the format of its /// signature (any zip file is taken for a SAFE product's zip form, which then rejects one @@ -101,6 +105,9 @@ impl Format { if crate::mrc::detect(head) { return Some(Format::Mrc); } + if crate::mp3::detect(head) { + return Some(Format::Mp3); + } None } } @@ -114,6 +121,7 @@ pub enum AnyParser { Ims(Ims), Safe(Box), Mrc(Mrc), + Mp3(Mp3), /// a VSI file, which no file run reads (its parser is a store parser) Vsi, } @@ -129,6 +137,7 @@ impl AnyParser { Format::Ims => AnyParser::Ims(Ims::new(size)), Format::Safe => AnyParser::Safe(Box::new(Safe::new(size))), Format::Mrc => AnyParser::Mrc(Mrc::new(size)), + Format::Mp3 => AnyParser::Mp3(Mp3::new(size)), Format::Vsi => AnyParser::Vsi, } } @@ -142,6 +151,7 @@ impl AnyParser { AnyParser::Ims(x) => x.step(), AnyParser::Safe(x) => x.step(), AnyParser::Mrc(x) => x.step(), + AnyParser::Mp3(x) => x.step(), AnyParser::Vsi => Err("a VSI file is virtualized as a store run, with its tile files".into()), } } @@ -155,6 +165,7 @@ impl AnyParser { AnyParser::Ims(x) => x.feed(o, b), AnyParser::Safe(x) => x.feed(o, b), AnyParser::Mrc(x) => x.feed(o, b), + AnyParser::Mp3(x) => x.feed(o, b), AnyParser::Vsi => {} } } @@ -168,6 +179,7 @@ impl AnyParser { AnyParser::Ims(x) => Parser::finish(x), AnyParser::Safe(x) => Parser::finish(*x), AnyParser::Mrc(x) => Parser::finish(x), + AnyParser::Mp3(x) => Parser::finish(x), AnyParser::Vsi => Err("a VSI file is virtualized as a store run, with its tile files".into()), } } @@ -204,8 +216,8 @@ impl Run { copies: Vec::new(), copied: Default::default(), planner: Planner::new(size, remote, concurrency), - // TIFF and CZI find their ranges in whole responses; ND2 and SAFE take exact ranges - whole: !matches!(format, Format::Nd2 | Format::Safe), + // TIFF and CZI find their ranges in whole responses; ND2, SAFE and MP3 take exact ranges + whole: !matches!(format, Format::Nd2 | Format::Safe | Format::Mp3), in_batch: false, done: false, } diff --git a/rust/refkv-ir/tests/parsers.rs b/rust/refkv-ir/tests/parsers.rs index 2a6ea9ae..9ace00a4 100644 --- a/rust/refkv-ir/tests/parsers.rs +++ b/rust/refkv-ir/tests/parsers.rs @@ -9,6 +9,7 @@ use refkv_ir::czi::Czi; use refkv_ir::dicom::Dicom; use refkv_ir::nifti::Nifti; use refkv_ir::ims::Ims; +use refkv_ir::mp3::Mp3; use refkv_ir::mrc::Mrc; use refkv_ir::parse_bytes; use refkv_ir::run::{run_bytes, Format}; @@ -201,6 +202,18 @@ reject!(mrc_reject_volume_stack_mz_zero, Mrc, "mrc/mrc_reject_volume_stack_mz_ze reject!(mrc_reject_truncated, Mrc, "mrc/mrc_reject_truncated.mrc", "the 48-byte data at 1024 is outside the 1071-byte file"); reject!(mrc_reject_data_overflow, Mrc, "mrc/mrc_reject_data_overflow.mrc", "the 4951760157141521099596496896-byte data at 1024 is outside the 1072-byte file"); reject!(mrc_reject_data_outside, Mrc, "mrc/mrc_reject_data_outside.mrc", "the 48-byte data at 1040 is outside the 1087-byte file"); +reject!(mp3_reject_layer2, Mp3, "mp3/mp3_reject_layer2.mp3", "MPEG-2 Layer II (the frame at 0) is not supported: only Layer III is"); +reject!(mp3_reject_layer1, Mp3, "mp3/mp3_reject_layer1.mp3", "MPEG-1 Layer I (the frame at 0) is not supported: only Layer III is"); +reject!(mp3_reject_free_format, Mp3, "mp3/mp3_reject_free_format.mp3", "free-format bitrate (the frame header at 0) is not supported"); +reject!(mp3_reject_sample_rate_change, Mp3, "mp3/mp3_reject_sample_rate_change.mp3", "the frame at "); +reject!(mp3_reject_channels_change, Mp3, "mp3/mp3_reject_channels_change.mp3", "the frame at "); +reject!(mp3_reject_version_change, Mp3, "mp3/mp3_reject_version_change.mp3", "the frame at "); +reject!(mp3_reject_layer_change, Mp3, "mp3/mp3_reject_layer_change.mp3", "the frame at "); +reject!(mp3_reject_no_frames, Mp3, "mp3/mp3_reject_no_frames.mp3", "no MPEG audio frames"); +reject!(mp3_reject_only_id3v1, Mp3, "mp3/mp3_reject_only_id3v1.mp3", "no MPEG audio frames"); +reject!(mp3_reject_id3v2_outside, Mp3, "mp3/mp3_reject_id3v2_outside.mp3", "the 100010-byte ID3v2 tag at 0 is outside the 60-byte file"); +reject!(mp3_reject_id3v2_syncsafe, Mp3, "mp3/mp3_reject_id3v2_syncsafe.mp3", "the ID3v2 tag at 0 has a size byte that is not syncsafe (128)"); +reject!(mp3_reject_short, Mp3, "mp3/mp3_reject_short.mp3", "file too short for an MPEG audio frame header"); reject!(ndpi_edge_reject_focal_planes, Tiff, "ndpi/edge_reject_ndpi_focal_planes.ndpi", "NDPI focal planes (two levels with one magnification) are not supported"); reject!(ndpi_edge_reject_growing, Tiff, "ndpi/edge_reject_ndpi_growing.ndpi", "NDPI levels do not decrease in size"); reject!(ndpi_edge_reject_mcustarts, Tiff, "ndpi/edge_reject_ndpi_mcustarts.ndpi", "McuStarts does not match the strip's intervals"); diff --git a/rust/refkv-ir/wasm/run.mjs b/rust/refkv-ir/wasm/run.mjs index 9fbb2b31..ca9f84aa 100644 --- a/rust/refkv-ir/wasm/run.mjs +++ b/rust/refkv-ir/wasm/run.mjs @@ -24,6 +24,8 @@ function format(fd) { if (s.startsWith("\x89HDF\r\n\x1a\n")) return "ims"; if (s.startsWith("PK\x03\x04")) return "safe"; // a SAFE product's zip form if (String.fromCharCode(...head.subarray(208, 211)) === "MAP") return "mrc"; + if (s.startsWith("ID3") || (head[0] === 0xff && (head[1] & 0xe0) === 0xe0 && (head[1] & 0x18) !== 0x08 && (head[1] & 0x06) !== 0 + && (head[2] & 0x0c) !== 0x0c)) return "mp3"; return "czi"; } diff --git a/spec/TECHNIQUES.md b/spec/TECHNIQUES.md index 01fc8f32..02b2e4cb 100644 --- a/spec/TECHNIQUES.md +++ b/spec/TECHNIQUES.md @@ -185,6 +185,7 @@ From [§1](#1-three-kinds-of-information), [§4](#4-numeric-metadata-as-arrays) | DICOM | the dataset without Per-frame Functional Groups and without binary-VR values | Per-frame Functional Groups | `OF`/`OD`/`OL`/`OV` values; optionally derived per-frame position and time arrays | | NIfTI | the header; text extensions (comment, AFNI and CIFTI XML, JSON) as text; a derived orientation (which affine, whether it is applied) | none | none | | MRC | the header; the kind of file, the data type, whether the axis map is applied, the voxel size; the extended header by reference | none | none | +| MP3 | the stream's parameters (version, sample rate, channels, frames, bitrate), the Xing or Info frame's counts and LAME fields, the ID3v1 tag's fields; the ID3v2 and APE tags, and every frame, by reference | none | none | | IMS | none | the whole HDF5 tree, mirrored under `refkv_source/hdf5`: each group's attributes, links and named datatypes on its own group | every dataset but the image's (histograms, thumbnail, `DataSetTimes`, `Scene8` tables), by reference, typed when its elements are numbers; large attributes, copied | | N5 | each node's `attributes.json` without its layout members (`dimensions`, `blockSize`, `dataType`, `compression`, `n5`) | none | none | | Zarr v2, OME-Zarr | each node's `.zattrs` | none | none | diff --git a/spec/conventions.md b/spec/conventions.md index 541a1dfe..2802d506 100644 --- a/spec/conventions.md +++ b/spec/conventions.md @@ -24,6 +24,7 @@ its JSON Schema `virtualize//schema.json`: | Sentinel-2 SAFE (Level-1C, Level-2A) | [safe](virtualize/safe.md) | `ef81346c-19e8-42ad-93b0-a279ccaf44c1` | | Zeiss CZI | [czi](virtualize/czi.md) | `7a0733c7-d4be-4482-a64f-6904d9354ea5` | | Olympus VSI | [vsi](virtualize/vsi.md) | `c0a1d4e6-5b7f-4f3a-9c2d-8e1f6a7b3c45` | +| MP3 (MPEG Layer III audio) | [mp3](virtualize/mp3.md) | `b6cb0047-9448-4fdc-b03e-10dd3d6aa829` | A format's convention specifies the hierarchy's whole **Zarr layout**: which @@ -176,7 +177,8 @@ nests its own record. Unless the format's convention says otherwise (the store conventions, N5, Zarr v2 and OME-Zarr, define their arrays themselves; the CZI convention gives clipped levels the zarr-extensions `rectilinear` chunk grid and adds -the codecs `imagecodecs_jpegxr` and `numcodecs.shuffle`), every array's +the codecs `imagecodecs_jpegxr` and `numcodecs.shuffle`; the MP3 convention +defines the codec `mp3` and its own dimension names), every array's `zarr.json` is the JSON object: ```json diff --git a/spec/generate_schemas.py b/spec/generate_schemas.py index 0bd6a096..c178eb5f 100644 --- a/spec/generate_schemas.py +++ b/spec/generate_schemas.py @@ -552,6 +552,85 @@ ]} VSI_DEFS = {"vsiField": _VSI_FIELD} +SOURCE_METADATA["mp3"] = {"anyOf": [ + { + "type": "object", + "description": "The root's: the stream's parameters, derived from its frames, and the fields of its info frame and tags (spec/virtualize/mp3.md §5.1 )", + "properties": { + "version": {"enum": ["MPEG-1", "MPEG-2", "MPEG-2.5"]}, + "layer": {"const": 3}, + "sample_rate": {"enum": [8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000]}, + "channels": {"enum": [1, 2]}, + "channel_mode": {"enum": ["stereo", "joint_stereo", "dual_channel", "mono"], + "description": "The first audio frame's channel mode"}, + "samples_per_frame": {"enum": [576, 1152]}, + "frames": {"type": "integer", "minimum": 1, "description": "The audio frames (the info frame is not one)"}, + "samples": {"type": "integer", "minimum": 1, "description": "frames * samples_per_frame"}, + "duration": {"type": "number", "exclusiveMinimum": 0, "description": "samples / sample_rate, in seconds"}, + "bitrate_mode": {"enum": ["constant", "variable"]}, + "bitrate_kbps": {"type": ["integer", "null"], "description": "The bitrate of every audio frame, or null when they differ"}, + "crc_frames": {"type": "integer", "minimum": 0, "description": "The audio frames with a CRC"}, + "info": { + "type": "object", + "description": "The info frame's fields: a Xing, Info or VBRI tag, and a LAME tag after a Xing or Info one", + "properties": { + "tag": {"enum": ["Xing", "Info", "VBRI"]}, + "frames": {"type": ["integer", "null"]}, + "bytes": {"type": ["integer", "null"]}, + "quality": {"type": ["integer", "null"]}, + "encoder": {"type": ["string", "null"], "description": "The LAME tag's 9-byte encoder version, when printable"}, + "delay": {"type": ["integer", "null"], "description": "The encoder delay in samples (a LAME tag's, or a VBRI tag's)"}, + "padding": {"type": ["integer", "null"], "description": "The encoder padding in samples (a LAME tag's)"}, + }, + "required": ["tag", "frames", "bytes", "quality", "encoder", "delay", "padding"], + "additionalProperties": False, + }, + "id3v2": { + "type": "array", "minItems": 1, + "description": "The ID3v2 tags at the start, in order: each header's version, flags and size, and whether it has a footer", + "items": { + "type": "object", + "properties": { + "version": {"type": "array", "items": {"type": "integer", "minimum": 0, "maximum": 255}, "minItems": 2, "maxItems": 2}, + "flags": {"type": "integer", "minimum": 0, "maximum": 255}, + "size": {"type": "integer", "minimum": 0}, + "footer": {"type": "boolean"}, + }, + "required": ["version", "flags", "size", "footer"], + "additionalProperties": False, + }, + }, + "id3v1": { + "type": "object", + "description": "The ID3v1 tag's fields: each text up to its first NUL", + "properties": { + "title": {"$ref": "#/$defs/text"}, "artist": {"$ref": "#/$defs/text"}, "album": {"$ref": "#/$defs/text"}, + "year": {"$ref": "#/$defs/text"}, "comment": {"$ref": "#/$defs/text"}, + "track": {"type": ["integer", "null"], "description": "An ID3v1.1 tag's track number"}, + "genre": {"type": "integer", "minimum": 0, "maximum": 255}, + }, + "required": ["title", "artist", "album", "year", "comment", "track", "genre"], + "additionalProperties": False, + }, + "ape": { + "type": "object", + "description": "The APE tag's footer fields, and the tag's whole size", + "properties": {"version": {"type": "integer", "minimum": 0}, "size": {"type": "integer", "minimum": 32}, + "items": {"type": "integer", "minimum": 0}}, + "required": ["version", "size", "items"], + "additionalProperties": False, + }, + "stray_bytes": {"type": "integer", "minimum": 0, + "description": "The bytes between the tags that are in no frame"}, + }, + "required": ["version", "layer", "sample_rate", "channels", "channel_mode", "samples_per_frame", "frames", + "samples", "duration", "bitrate_mode", "bitrate_kbps", "crc_frames", "stray_bytes"], + "additionalProperties": False, + }, + {"$ref": "#/$defs/mirror"}, + {"$ref": "#/$defs/mirrorView"}, +]} + # The dataset layout of an MRC file (spec/virtualize/mrc-dataset.md §4 # ): the # MRC convention's root metadata, member for member, on the group `dataset`. diff --git a/spec/virtualize.md b/spec/virtualize.md index b20978c1..d1a53601 100644 --- a/spec/virtualize.md +++ b/spec/virtualize.md @@ -8,7 +8,9 @@ A **virtualizer** reads the structure of an image file or of a chunked array store (the formats of the table below), and writes a vzip archive ([spec/bindings/vzip.md](bindings/vzip.md)) that presents the pixels as an OME-Zarr dataset, or for a store as a Zarr v3 hierarchy (for an OME-Zarr 0.4 store, -an OME-Zarr 0.5 one; for a Sentinel-2 SAFE product, a GeoZarr one). The +an OME-Zarr 0.5 one; for a Sentinel-2 SAFE product, a GeoZarr one; for an +MP3 file, the one format that is not an image, a plain array of audio +samples). The pixels stay where they are: each Zarr chunk is a reference to byte ranges of the file, or to a whole object of the store. This document specifies, for each supported input format (a **profile**), exactly which archive a @@ -35,6 +37,7 @@ is a document of its own, numbered as a section of this one: | 13 | [CZI](virtualize/czi.md#part-2-the-profile) | file | Zeiss CZI files (ZISRAW, file version 1), with uncompressed, JPEG, JPEG XR and Zstd subblocks, mosaics and pyramids | | 14 | [MRC](virtualize/mrc.md#part-2-the-profile) | file | MRC2014 files (CCP4 maps, image stacks, volumes and volume stacks) | | 15 | [VSI](virtualize/vsi.md#part-2-the-profile) | file | Olympus cellSens VSI slides: a `.vsi` file and the tile files beside it, probed by key (uncompressed, JPEG and JPEG 2000 tiles) | +| 16 | [MP3](virtualize/mp3.md#part-2-the-profile) | file | MPEG-1, MPEG-2 and MPEG-2.5 Layer III audio files (`.mp3`), with their ID3v2, ID3v1 and APE tags; one array of samples, not an image | The table says which profiles read a single file (a **file input**), which a store of many @@ -161,6 +164,7 @@ a test that needs a byte beyond `H` does not match. | bytes 0–15 are `5A 49 53 52 41 57 46 49 4C 45` (`ZISRAWFILE`) and six `00` bytes | CZI profile ([§13](virtualize/czi.md#13-czi-profile)) | | bytes 208–210 are `4D 41 50` (`MAP`) | MRC profile ([§14](virtualize/mrc.md#14-mrc-profile)) | | bytes 0–3 are `49 49 2A 00` and bytes 8–11 are `18 00 49 53` (a cellSens container header) | VSI profile ([§15](virtualize/vsi.md#15-vsi-profile)), tested before the TIFF row | +| bytes 0–2 are `49 44 33` (`ID3`), or bytes 0–3 are an MPEG audio frame header: bits 31–21 all ones, bits 20–19 not `01`, bits 18–17 not `00`, bits 11–10 not `11` ([spec/virtualize/mp3.md §2](virtualize/mp3.md#2-frames); any layer and bitrate index) | MP3 profile ([§16](virtualize/mp3.md#16-mp3-profile)) | | anything else, including the JPEG 2000 signature box `00 00 00 0C 6A 50 20 20 0D 0A 87 0A` that starts legacy ND2 files, NIfTI header-and-image pairs (`ni1`, `ni2`) and pre-2000 MRC files without `MAP` | rejected | A DICOM file is read by the DICOM profile even when its 128-byte preamble @@ -537,7 +541,8 @@ other section: - [§12](virtualize/safe.md#12-safe-profile), the SAFE profile: [spec/virtualize/safe.md](virtualize/safe.md#part-2-the-profile); - [§13](virtualize/czi.md#13-czi-profile), the CZI profile: [spec/virtualize/czi.md](virtualize/czi.md#part-2-the-profile); - [§14](virtualize/mrc.md#14-mrc-profile), the MRC profile: [spec/virtualize/mrc.md](virtualize/mrc.md#part-2-the-profile); -- [§15](virtualize/vsi.md#15-vsi-profile), the VSI profile: [spec/virtualize/vsi.md](virtualize/vsi.md#part-2-the-profile). +- [§15](virtualize/vsi.md#15-vsi-profile), the VSI profile: [spec/virtualize/vsi.md](virtualize/vsi.md#part-2-the-profile); +- [§16](virtualize/mp3.md#16-mp3-profile), the MP3 profile: [spec/virtualize/mp3.md](virtualize/mp3.md#part-2-the-profile). ## Appendix A. Conformance diff --git a/spec/virtualize/mp3.md b/spec/virtualize/mp3.md new file mode 100644 index 00000000..c088a058 --- /dev/null +++ b/spec/virtualize/mp3.md @@ -0,0 +1,536 @@ +# MP3 + +The Zarr layout of an MP3 file (MPEG-1, MPEG-2 or MPEG-2.5 Layer III audio, +`.mp3`), and the translation of its stream parameters and tags into JSON. +What all of refkv's conventions share is in +[spec/conventions.md](../conventions.md), cited here as "conventions §n". How +refkv produces this layout as a reference store, and which files it accepts, +is the MP3 profile, [Part 2](#part-2-the-profile) below. + +Convention version: 0 (until release, [conventions §1](../conventions.md#1-conventions)) · UUID: `b6cb0047-9448-4fdc-b03e-10dd3d6aa829` · +Schema: [schema.json](mp3/schema.json) + +Added 2026-10-21, after +[revision 29](../history/virtualize/REVISIONS.md#revision-29-no-recorded-revision-the-profile-registry) +(a profile's changes are recorded here, dated, from then on). + +This document has two parts. [Part 1](#part-1-the-convention) is the MP3 +convention: the Zarr layout, cited as "the convention §n". +[Part 2](#part-2-the-profile) is the MP3 profile: how refkv reads the source, +which inputs it rejects, and how each chunk references the source. The profile +keeps its numbering as a section of [spec/virtualize.md](../virtualize.md), +and is cited as spec/virtualize.md §n. + +MP3 is the one format among refkv's conventions whose source is not an +image: the hierarchy holds the decoded audio as one array of samples, with no +OME-NGFF metadata. The samples stay in the file as MPEG frames; the array's +codec decodes them when a chunk is read. + +# Part 1. The convention + +## 1. Declaration + +The root declares the convention by [conventions §2](../conventions.md#2-attributes), +with `"profile": "mp3"`, `"version": 0` ([conventions §1](../conventions.md#1-conventions)), the file's URL as `source.url`, +and the root's source metadata of [§5.1](#51-the-root) as the member `"mp3"`. Its CMO is: + +```json +{ + "uuid": "b6cb0047-9448-4fdc-b03e-10dd3d6aa829", + "schema_url": "https://raw.githubusercontent.com/d-v-b/refkv/refs/heads/main/spec/virtualize/mp3/schema.json", + "spec_url": "https://github.com/d-v-b/refkv/blob/main/spec/virtualize/mp3.md", + "name": "refkv_virtualized", + "description": "The Zarr layout of a MP3 source virtualized by refkv, and the source's metadata" +} +``` + +The root's attributes are `zarr_conventions` and `refkv_virtualized` and +nothing else: there is no `ome` member, since the hierarchy is not an image. +`refkv_source` declares the convention too, with the IR mirror's description +([§5.2](#52-the-ir-mirror), [conventions §8](../conventions.md#8-the-ir-mirror)), and so does each group of +the mirror's view that has a member; the array and the mirror's arrays have no +attributes. + +## 2. Frames + +An MP3 file is a sequence of **frames**, each a 4-byte **header** followed by +the frame's data, with tags ([§3](#3-tags)) before the first frame and after +the last. The header's bits, most significant first (byte 0 first): + +| bits | field | values | +|---|---|---| +| 31–21 | sync | all ones (`FF Ex` to `FF Fx`) | +| 20–19 | version | `00` MPEG-2.5, `01` reserved, `10` MPEG-2, `11` MPEG-1 | +| 18–17 | layer | `00` reserved, `01` Layer III, `10` Layer II, `11` Layer I | +| 16 | protection | `0`: a 16-bit CRC follows the header; `1`: none | +| 15–12 | bitrate index | 0 free format, 15 invalid; else a table entry | +| 11–10 | sample rate index | 3 invalid; else a table entry | +| 9 | padding | the frame is one byte longer | +| 8 | private | | +| 7–6 | channel mode | `00` stereo, `01` joint stereo, `10` dual channel, `11` mono | +| 5–4 | mode extension | | +| 3 | copyright | | +| 2 | original | | +| 1–0 | emphasis | | + +A header is **valid** when its sync is all ones, its version and layer are +not reserved, its bitrate index is from 1 to 14 and its sample rate index is +from 0 to 2. (A free-format header is one that is valid but for a bitrate +index of 0.) The header gives: + +- the **sample rate**, by version and index: MPEG-1 44100, 48000, 32000; + MPEG-2 22050, 24000, 16000; MPEG-2.5 11025, 12000, 8000; +- the **bitrate** in kbps, by version, layer and index 1 to 14: for Layer + III, MPEG-1 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, + and MPEG-2 and 2.5 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, + 160 (Layer I and II frames, which the profile rejects, have their own + tables: Layer I 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, + 416, 448 for MPEG-1 and 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, + 192, 224, 256 for MPEG-2 and 2.5; Layer II 32, 48, 56, 64, 80, 96, 112, + 128, 160, 192, 224, 256, 320, 384 for MPEG-1, and Layer III's for MPEG-2 + and 2.5); +- the **channel count** `C`: 1 for mono, 2 otherwise; +- the frame's **length** `L` in bytes, header included, with `b` the bitrate + in bits per second, `r` the sample rate and `p` the padding bit, integer + division: Layer III `144 × b / r + p` for MPEG-1 and `72 × b / r + p` for + MPEG-2 and 2.5 (Layer II `144 × b / r + p`; Layer I `(12 × b / r + p) × 4`); +- the **samples per channel** `S` a Layer III frame decodes to: 1152 for + MPEG-1, 576 for MPEG-2 and 2.5. + +A Layer III frame is its header, the 2-byte CRC when the protection bit is +0, the **side information** (MPEG-1: 17 bytes for mono, 32 otherwise; +MPEG-2 and 2.5: 9 for mono, 17 otherwise), and the **main data** that fills +the rest of the frame, `M = L − 4 − 2 × crc − side` bytes. A frame's own +audio may begin before its main data, in the main data of earlier frames (the +**bit reservoir**): the side information's `main_data_begin` says how many +bytes back, at most 511 for MPEG-1 and 255 for MPEG-2 and 2.5. So a frame +cannot be decoded alone; [§4.1](#41-the-array) says what a chunk holds so +that it can be. + +Two frames are of **one stream** when they agree on the version, the layer, +the sample rate and the channel count. The bitrate, the padding, the +protection and the channel mode may differ from frame to frame (a variable +bitrate stream; joint stereo). + +**The info frame.** An encoder may start the stream with a frame that holds +no audio but a tag describing the stream: a **Xing** or **Info** tag (the +ASCII `Xing` or `Info` right after the side information, that is at offset +`4 + 2 × crc + side` of the frame), followed by a 32-bit big-endian flags +word and, for each flag bit set, the frame count (bit 0), the byte count (bit +1), a 100-byte seek table (bit 2) and a quality indicator (bit 3), each +32-bit big-endian; a **LAME tag** may follow: a 9-byte encoder version +(`LAME3.100`, `Lavc61.19`), then its fields, among them at offset 21 from +the version's start the encoder **delay** (12 bits) and **padding** (12 +bits) in samples. A **VBRI** tag is the ASCII `VBRI` at offset 36 of the +frame, followed by a 16-bit version, a 16-bit delay, a 16-bit quality, the +byte count and the frame count (32-bit, all big-endian). The convention does +not count an info frame as audio ([§4.1](#41-the-array)) and records its +fields ([§5.1](#51-the-root)). + +## 3. Tags + +An **ID3v2 tag** at the start of the file: `ID3`, a version (2 bytes: the +major version and the revision), a flags byte, and a 4-byte **syncsafe** +size (each byte below `80`; the size is their 7-bit values, most significant +first), the 10-byte header; then `size` bytes of frames and padding; then, +when bit 4 (`10`) of the flags is set, a 10-byte footer. A file may hold +several, one after the other. The convention does not decode the tag's +frames. + +An **ID3v1 tag** is the last 128 bytes of the file when they start with +`TAG`: the title, artist and album (30 bytes each), the year (4), the +comment (30; in ID3v1.1, when its byte 28 is NUL, byte 29 is the track +number) and the genre (1 byte). + +An **APE tag** ends with a 32-byte footer, right before the ID3v1 tag or at +the end of the file: `APETAGEX`, the version, the size (the items and the +footer, not the header), the item count and the flags (32-bit little-endian +each; bit 31 of the flags: the tag also has a 32-byte header before its +items), then 8 reserved bytes. The tag is `size` bytes, plus 32 when it has +a header, ending at the footer's end; a footer whose tag would start before +the first byte after the ID3v2 tags, or whose size is below 32, is not an +APE tag. The convention does not decode the items. + +## 4. The layout + +The hierarchy is a group at the root with one array at path `samples`: the +root `zarr.json` is `{"zarr_format": 3, "node_type": "group", "attributes": +A}`, where `A` has `zarr_conventions` and `refkv_virtualized` ([§1](#1-declaration)) and +nothing else. + +### 4.1 The array + +The **audio frames** are the stream's frames in file order, numbered from 0, +without the info frame ([§2](#2-frames)); `N` is their count ([spec/virtualize.md §16.1](#161-the-stream) +says which frames those are). Every audio frame has the stream's `S` +and `C`. + +- **Shape:** `[N × S, C]`: the samples per channel, then the channels. +- **Data type:** `int16`. +- **Dimension names:** `["time", "channel"]`. +- **Chunk shape:** `[F × S, C]` with **`F = 256` frames per chunk**: chunk `q` + holds the audio frames `q × F` to `min(N, (q + 1) × F) − 1`, which are + **its frames**; the last chunk may hold fewer than `F`, and is padded + to the chunk shape by the codec. The chunk grid is regular; the chunk + keys are `samples/c//0`. +- **Codecs:** `[{"name": "mp3"}]`, the array-to-bytes codec this convention + defines below. +- **Fill value:** 0. + +The array's `zarr.json` is otherwise [conventions §3](../conventions.md#3-arrays)'s. + +**The `mp3` codec.** The bytes of a chunk are: + +1. a 32-bit little-endian unsigned integer **`keep`**, the samples per + channel of the chunk's frames: `F × S`, or fewer for the last chunk; +2. then MPEG audio frames, one after the other in file order (whatever + the file holds between two frames is left out): the chunk's + **lead-in**, the frames before its first frame that a decoder needs to + have decoded so that it decodes the chunk's frames as a decoder of the + whole stream does ([spec/virtualize.md §16.2](#162-chunks) says which); + then the chunk's frames. + +Decoding a chunk is decoding the frames of 2 in one pass as a Layer III +decoder decodes a stream (the frames of the lead-in supply the bit +reservoir and the overlap state of the filter bank for the chunk's frames; +their own output is discarded), to 16-bit PCM of the stream's `C` channels, +interleaved by sample, and taking the **last `keep` samples** of the output: +they are the chunk's samples, from the chunk's first sample on, followed by +zeros up to the chunk shape. A decoder that cannot decode a frame whose +reservoir it does not hold (the stream's first frames, which have no +lead-in) gives fewer than `keep` samples for the first chunk; they are the +last of the `keep`, preceded by zeros. The channel count of the frames is +the array's; a chunk whose frames differ from it, or whose `keep` exceeds +the chunk shape, is an error. + +### 4.2 The samples + +Sample `i` of channel `c` is the output of a Layer III decoder, as ISO/IEC +11172-3 and 13818-3 define it, decoding the audio frames one after the +other from the first (the frames alone: not the bytes between them), as a +signed 16-bit integer (rounded from the decoder's output), the +`i`th sample it produces for channel `c`; the decoder starts with an empty +bit reservoir and a zero filter-bank state, and its first frame's output is +what it is (the stream's encoder delay and the decoder's own delay, about +529 samples, are in the array; neither is trimmed). The samples of a frame +are its `S` outputs; a frame the decoder cannot decode (its reservoir +reaches before the first audio frame) gives zeros. Two conforming decoders +may differ by a few units in a sample (the standards allow it); the +convention does not say which decoder a reader uses, and +[spec/virtualize.md §1.1](../virtualize.md#11-output-and-equivalence) compares +references, not samples. + +The sample rate is `sample_rate` of [§5.1](#51-the-root); sample `i` is at +`i / sample_rate` seconds from the stream's start. + +## 5. Source metadata + +The root's source metadata `S` ([conventions §2](../conventions.md#2-attributes)) +is an object with the members of [§5.1](#51-the-root), in that order, +translated by [conventions §6](../conventions.md#6-source-metadata-as-json). +Everything the file holds is on `refkv_source`, the file's **IR mirror** +([§5.2](#52-the-ir-mirror)), from which the file is rebuilt byte for byte. + +### 5.1 The root + +- `version`: `"MPEG-1"`, `"MPEG-2"` or `"MPEG-2.5"`, the stream's. +- `layer`: 3. +- `sample_rate`: the stream's, in Hz. +- `channels`: `C`. +- `channel_mode`: the first audio frame's: `"stereo"`, `"joint_stereo"`, + `"dual_channel"` or `"mono"`. +- `samples_per_frame`: `S`. +- `frames`: `N`, the audio frames. +- `samples`: `N × S`. +- `duration`: `N × S / sample_rate`, in seconds, as a number. +- `bitrate_mode`: `"constant"` when every audio frame has the same bitrate + index, else `"variable"`. +- `bitrate_kbps`: that bitrate in kbps, or `null` when variable. +- `crc_frames`: how many audio frames have the protection bit 0 (a CRC). +- `info`: when the stream starts with an info frame ([§2](#2-frames)), an + object `{"tag": T, "frames": n, "bytes": n, "quality": n, "encoder": e, + "delay": n, "padding": n}`: `T` is `"Xing"`, `"Info"` or `"VBRI"`; the + counts and the quality are those the tag holds, `null` for each it does + not (a Xing or Info flag bit clear; a value past the frame's end); + `encoder` is the LAME tag's 9-byte version as text: its bytes up to the + first NUL, when there is at least one, they are printable ASCII (`20` to + `7E`) and the first is not a space, trailing spaces removed (`LAME3.99r`, + `LAME4.0`, `Lavc63.1.`), else `null`; `delay` and `padding` are its + encoder delay and padding, `null` without an encoder or when the frame + ends before them; for a VBRI tag, `delay` is the tag's and `encoder` and + `padding` are `null`. Absent when there is no info frame. +- `id3v2`: an array with one object per ID3v2 tag at the start, in order, + `{"version": [major, revision], "flags": f, "size": n, "footer": b}` + (the header's bytes 3 and 4, its flags byte, its size field, and whether + it has a footer). Absent when there is none. +- `id3v1`: when the file ends with an ID3v1 tag, `{"title", "artist", + "album", "year", "comment"}`, each field's bytes up to its first NUL as a + text value, `"track"`, the track number of an ID3v1.1 tag (byte 28 of the + comment NUL and byte 29 not) or `null`, and `"genre"`, the genre byte. + Absent otherwise. +- `ape`: when the file has an APE tag, `{"version": v, "size": n, "items": + n}`: the footer's version and item count, and the tag's whole size + (header included). Absent otherwise. +- `stray_bytes`: the bytes between the ID3v2 tags and the trailing tags + that are in no frame (junk between frames, a truncated last frame, + bytes after the last frame). + +`version` to `crc_frames` are derived from the frames, so that a reader +need not read a header; the tags' fields are there so that a reader finds +the stream's description and the file's labels without decoding the tags. +The ID3v2 and APE tags' items are in the mirror, not decoded. + +### 5.2 The IR mirror + +`refkv_source` is the file's **IR mirror** +([conventions §8](../conventions.md#8-the-ir-mirror)): its table, from which the +file is rebuilt byte for byte, and its view, `refkv_source/tree`. The IR's +elements (the MP3 **source model**) are below; nothing is left out: the +tags, the info frame, every audio frame, and every byte between or after +them. + +### 5.3 Elements + +Paths are relative to the IR's root, whose path is `""` +([conventions §8.1](../conventions.md#81-elements)). Types are those of +[conventions §8.6](../conventions.md#86-types); `n` is a tag's size, `L` a +frame's length. + +| path | kind | type | extent: what | +|---|---|---|---| +| `""` | struct | | the root: the whole file, `(0, size)` | +| `id3v2/` | struct | | the `k`-th ID3v2 tag at the start, `k` from 0: the whole tag | +| `id3v2//header` | value | `{id:ascii[3],version:u1[2],flags:u1,size:u1[4]}` | its 10-byte header | +| `id3v2//data` | value | `bytes[n]` | its `n` bytes of frames and padding, when `n > 0`, opaque | +| `id3v2//footer` | value | `bytes[10]` | its footer, when it has one | +| `info` | value | `bytes[L]` | the info frame ([§2](#2-frames)), when the stream starts with one | +| `frames` | struct | | the audio frames: from the first's start to the last's end | +| `frames/` | data | | audio frame `j`, `j` from 0, `(offset, L)`, header included; its form's geometry is `{"samples": S, "channels": C, "data_type": "int16"}`, its codec `{"name": "mp3", "version": V, "sample_rate": r}`, and its recipe `[["src", 0, null]]` | +| `id3v1` | value | `{tag:ascii[3],title:cstr[30],artist:cstr[30],album:cstr[30],year:ascii[4],comment:cstr[30],genre:u1}` | the ID3v1 tag, `(size − 128, 128)`, when there is one | +| `ape` | value | `bytes[n]` | the APE tag, header and footer included, when there is one, opaque | +| `gaps/` | gap | | bytes no other element claims: junk between frames, a truncated last frame, bytes after the last frame | + +The view ([conventions §8.7](../conventions.md#87-the-view)) shows each ID3v2 +header and the ID3v1 tag; the tags' bodies, the info frame and the APE tag, +opaque bytes, are not shown. + +### 5.4 Equivalence + +The elements are determined by the file, and the mirror by its elements +([conventions §8.8](../conventions.md#88-canonical-form): one order, one folding, one encoding): hierarchies of one +file are compared entry for entry, `refkv_source` included +([spec/virtualize.md §1.1](../virtualize.md#11-output-and-equivalence)). + +## 6. Example + +A mono MPEG-2 stream at 16 kHz and 32 kbps of 22 frames and no tags, at +`https://example.org/clip.mp3` (the fixture +`fixtures/mp3/mp3_mpeg2_mono_16k.mp3`, 3168 bytes of frames of 144 bytes), +has this root `zarr.json`: + +```json +{ + "zarr_format": 3, + "node_type": "group", + "attributes": { + "zarr_conventions": [{ + "uuid": "b6cb0047-9448-4fdc-b03e-10dd3d6aa829", + "schema_url": "https://raw.githubusercontent.com/d-v-b/refkv/refs/heads/main/spec/virtualize/mp3/schema.json", + "spec_url": "https://github.com/d-v-b/refkv/blob/main/spec/virtualize/mp3.md", + "name": "refkv_virtualized", + "description": "The Zarr layout of a MP3 source virtualized by refkv, and the source's metadata" + }], + "refkv_virtualized": { + "profile": "mp3", + "version": 0, + "source": {"url": "https://example.org/clip.mp3"}, + "mp3": { + "version": "MPEG-2", + "layer": 3, + "sample_rate": 16000, + "channels": 1, + "channel_mode": "mono", + "samples_per_frame": 576, + "frames": 22, + "samples": 12672, + "duration": 0.792, + "bitrate_mode": "constant", + "bitrate_kbps": 32, + "crc_frames": 0, + "stray_bytes": 0 + } + } + } +} +``` + +Its array `samples/zarr.json` has the shape `[12672, 1]`, the chunk shape +`[147456, 1]` (256 frames of 576 samples), the data type `int16`, the codecs +`[{"name": "mp3"}]` and the dimension names `["time", "channel"]`. The one +chunk, `samples/c/0/0`, is the literal `80 31 00 00` (`keep = 12672`) then +the range `(0, 3168)` of source 0: every frame, no lead-in. Read with 4 +frames a chunk instead (as the tests do), chunk 3 holds frames 12 to 15, +`keep = 2304`, and its range is `(1152, 1152)`: it starts at frame 8, since +the lead-in is frames 10 and 11, the two before the chunk, and before them +frames 8 and 9, whose main data (131 bytes each: `144 − 4 − 9`) holds 262 +bytes, at least the 255-byte reservoir of MPEG-2. + +## 7. What the layout does not express + +This section is informative. + +- **Gapless playback.** The encoder delay and padding of a LAME tag say + which samples at the start and the end are the encoder's, not the + recording's; players trim them. The array holds every decoded sample and + records the two counts in `info`, so a reader that wants the recording + alone drops `delay + 529` samples at the start (529 being a decoder's own + delay) and `padding − 529` at the end, as players do. +- **The tags' items.** An ID3v2 tag's frames (title, artist, cover art, + lyrics) and an APE tag's items are kept whole in the mirror and not + decoded; `id3v1` is, as it is fixed-width. +- **Per-frame values.** The bitrate, padding and channel mode of each + frame, and the seek table of a Xing tag, are in the frames and the info + frame in the mirror, not in the root. +- **The decoder.** Which decoder, and whether it uses the gapless + information or the seek table, is the reader's choice; the convention + says what the samples are, to the accuracy the standards allow. +- **A broken reservoir.** A frame whose bit reservoir reaches into frames + the stream does not hold (two streams cut and joined, a frame lost) + decodes as the reader's decoder has it: some decoders skip it, which + shifts the samples of its chunk by a frame; others give noise or + silence for it. Only the stream's first frames, which have no earlier + frames, are such frames in a well-formed file. + +# Part 2. The profile + +The MP3 profile of [spec/virtualize.md](../virtualize.md), numbered as its +[§16](#16-mp3-profile). [§1](../virtualize.md#1-introduction) and +[§2](../virtualize.md#2-the-zarr-layout) are in spec/virtualize.md and apply +here. + +The output has the convention's layout for the input +([spec/virtualize.md §2](../virtualize.md#2-the-zarr-layout)); this profile says +which inputs are accepted and how each chunk references the file. "The +convention §n" below is a section of Part 1. + +## 16. MP3 profile + +### 16.1 The stream + +The input is an MP3 file, which [§1.2](../virtualize.md#12-input) chose by +`ID3` at offset 0, or a frame header at offset 0 whose sync, version, layer +and sample rate index are valid, of any layer and bitrate index +([the convention §2](#2-frames)). The whole file is read: an MP3 file has +no index, and each frame's header gives the next. + +**Checks.** The input is rejected unless all of these hold, checked in this +order: + +- **Size:** the file is at least 4 bytes. +- **ID3v2 tags:** for each tag at the start (`ID3` at offset 0, and again + at the end of each tag): the file has its 10-byte header; its four size + bytes are each below `80`; and the tag, footer included, ends within the + file. +- **The stream:** the file has a first confirmed frame (below), and it is + Layer III. A Layer I or Layer II first frame rejects by name + (`MPEG-2 Layer II (the frame at 0) is not supported: only Layer III is`). +- **One stream:** no confirmed frame changes the version, the layer, the + sample rate or the channel count of the stream (the first confirmed + frame's): `the frame at 2016 changes the sample rate from 16000 to 22050`. +- **Audio:** at least one audio frame. Without one, the input is rejected + as `free-format bitrate (the frame header at ) is not supported` + when the scan met a free-format header (the first one), else as `no MPEG + audio frames`. + +**Tags.** The ID3v2 tags are those at the start, one after the other, each +as [the convention §3](#3-tags) measures it; `A` is the offset after the last +(0 without one). The ID3v1 tag is the last 128 bytes when they start with +`TAG` and lie at or after `A`; `E` is its offset, else the file's size. An +APE footer ending at `E`, whose tag ([the convention §3](#3-tags)) is at +least 32 bytes and starts at or after `A`, makes the tag end at `E` and +moves `E` to the tag's start. The frames are scanned in `[A, E)`. + +**Frames.** The scan keeps a position `p`, from `A`, and the **stream** +(the first confirmed frame's version, layer, sample rate and channel +count; none at first). At `p`, when `p + 4 ≤ E` and the header at `p` is +valid ([the convention §2](#2-frames)), with its frame length `L`, the +frame **fits** when `p + L ≤ E`; it is **consistent** when there is no +stream yet or it is of the stream; the **next header** is valid and of the +same stream as this header when `p + L + 4 ≤ E` and the 4 bytes at `p + L` +are a valid header that agrees with this one on the version, layer, sample +rate and channel count. The frame is **confirmed** when it fits and one of +these holds: + +- it is **chained** (the previous confirmed frame ended at `p`) and + consistent; +- there is no stream yet and `p + L = E` (a file of one frame); +- the next header is valid and of the same stream as this header. + +A confirmed frame that is not consistent rejects the input (the one-stream +check); the first confirmed frame sets the stream (the Layer III check). A +confirmed frame is a frame: `p` moves to `p + L`, and the next frame is +chained. Otherwise, or when the header at `p` is not valid, `p` moves to +`p + 1` and the next frame is not chained. The scan ends when `p + 4 > E`. +A valid header that is not confirmed, a frame that does not fit (the last +frame, truncated), and every byte between confirmed frames are not frames. + +**The info frame.** The first confirmed frame is the **info frame** when it +holds a Xing, Info or VBRI tag ([the convention §2](#2-frames)); it is not +an audio frame. Every other confirmed frame is an audio frame, numbered +from 0 in order. + +So the scan accepts a frame reached by the chain without looking ahead, +as decoders do; a frame found after junk (or the first) needs the next +frame to agree with it, so that a sync in junk is not a frame; a parameter +change is only taken for one when two frames of the new parameters follow +each other; and trailing junk, a truncated last frame and a tag the +convention does not know are bytes between or after frames, kept as gaps +([the convention §5.3](#53-elements)). + +### 16.2 Chunks + +The array has `ceil(N / F)` chunks, `F = 256`, chunk `q` holding the audio +frames `a = q × F` to `b − 1`, `b = min(N, a + F)` +([the convention §4.1](#41-the-array)). Every chunk is present. Chunk `q`, at +`samples/c//0`, is the reference of two ranges: + +1. the literal range of 4 bytes `keep = (b − a) × S` as a 32-bit + little-endian unsigned integer; +2. the audio frames `l` to `b − 1` as ranges of source 0, in order, one + range per run of frames that follow each other in the file: a frame that + starts where the frame before it ends extends that frame's range, and + any other frame starts a new one (so the bytes between frames, which are + no frame, are in no range). `l` is the first frame of the **lead-in**: + `l = a` for the first chunk (`a = 0`); otherwise `l` is the greatest + index at most `a − 2` such that the main data of frames `l` to `a − 3` + ([the convention §2](#2-frames), `M` of each) sums to at least `R`, + where `R = 511` for MPEG-1 and `255` for MPEG-2 and 2.5, or `l = 0` when + no index does. + +So the lead-in is the two frames before the chunk, and before them the +fewest frames whose main data holds the largest bit reservoir the version +allows: a decoder that decodes the lead-in holds the reservoir the two +frames need, the two frames give it the filter bank's overlap and the +synthesis state the chunk's first frame needs (the frame before it in +MPEG-1, where a frame has two granules; the two frames before it in MPEG-2 +and 2.5, where a frame has one), and the chunk's frames then decode as +they do in the stream. Decoding the lead-in costs a few frames' work per +chunk and no extra reads. Leaving the bytes between frames out keeps a +decoder from resyncing in the middle of a chunk: a decoder that looks for a +run of frames to lock onto would drop the frames before junk, and one that +resets its state on junk would decode the frame after it from nothing. + +The ranges lie within the file (frames are found within `[A, E)`). The +output has no data sources: its source table is source 0 alone. +`refkv_source` is the IR mirror ([the convention §5.2](#52-the-ir-mirror)). The archive +has no other entries than the root's and the array's `zarr.json`, the +array's chunks, and the mirror's. + +### 16.3 Summary + +This section is informative. Both implementations print a one-line JSON +summary: `version`, `sampleRate`, `channels`, `frames` (the audio frames), +`samples`, `duration` (seconds), `bitrate` (kbps, or `"variable"`), +`chunkFrames` (`F`), `chunks`, `info` (the info frame's tag, or `null`), +`tags` (those of `"id3v2"`, `"id3v1"` and `"ape"` the file has, in that +order) and `strayBytes`. diff --git a/spec/virtualize/mp3/schema.json b/spec/virtualize/mp3/schema.json new file mode 100644 index 00000000..c7e5b48f --- /dev/null +++ b/spec/virtualize/mp3/schema.json @@ -0,0 +1,616 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://raw.githubusercontent.com/d-v-b/refkv/refs/heads/main/spec/virtualize/mp3/schema.json", + "title": "refkv MP3 convention, version 0", + "description": "The zarr.json of a node that declares the refkv MP3 convention (https://github.com/d-v-b/refkv/blob/main/spec/virtualize/mp3.md)", + "type": "object", + "properties": { + "zarr_format": { + "type": "integer", + "const": 3 + }, + "node_type": { + "type": "string", + "enum": [ + "group", + "array" + ] + }, + "attributes": { + "type": "object", + "properties": { + "ome": { + "type": "object", + "description": "OME-NGFF 0.5 metadata" + }, + "zarr_conventions": { + "type": "array", + "contains": { + "$ref": "#/$defs/conventionMetadata" + }, + "minContains": 1, + "maxContains": 1 + }, + "refkv_virtualized": { + "oneOf": [ + { + "$ref": "#/$defs/rootProperty" + }, + { + "$ref": "#/$defs/nodeProperty" + } + ] + } + }, + "required": [ + "zarr_conventions", + "refkv_virtualized" + ], + "additionalProperties": false + } + }, + "required": [ + "zarr_format", + "node_type", + "attributes" + ], + "$defs": { + "conventionMetadata": { + "type": "object", + "description": "The MP3 convention's metadata object in zarr_conventions", + "properties": { + "uuid": { + "type": "string", + "const": "b6cb0047-9448-4fdc-b03e-10dd3d6aa829" + }, + "schema_url": { + "type": "string", + "const": "https://raw.githubusercontent.com/d-v-b/refkv/refs/heads/main/spec/virtualize/mp3/schema.json" + }, + "spec_url": { + "type": "string", + "const": "https://github.com/d-v-b/refkv/blob/main/spec/virtualize/mp3.md" + }, + "name": { + "type": "string", + "const": "refkv_virtualized" + }, + "description": { + "type": "string", + "const": "The Zarr layout of a MP3 source virtualized by refkv, and the source's metadata" + } + }, + "required": [ + "uuid" + ], + "additionalProperties": false + }, + "rootProperty": { + "type": "object", + "description": "The root's property: the profile and version that produced the hierarchy, its source, and the root's source metadata", + "properties": { + "profile": { + "type": "string", + "const": "mp3" + }, + "version": { + "type": "integer", + "const": 0 + }, + "source": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "The URL of the source file" + } + }, + "required": [ + "url" + ], + "additionalProperties": false + }, + "layouts": { + "type": "object", + "minProperties": 1, + "additionalProperties": { + "type": "string", + "pattern": "^[^/]+(/[^/]+)*$" + }, + "description": "The other layouts of the source in this hierarchy, by name, each the path of its node below the root (spec/conventions.md §9 )" + }, + "mp3": { + "$ref": "#/$defs/sourceMetadata" + } + }, + "required": [ + "profile", + "version", + "source" + ], + "additionalProperties": false + }, + "sourceMetadata": { + "anyOf": [ + { + "type": "object", + "description": "The root's: the stream's parameters, derived from its frames, and the fields of its info frame and tags (spec/virtualize/mp3.md §5.1 )", + "properties": { + "version": { + "enum": [ + "MPEG-1", + "MPEG-2", + "MPEG-2.5" + ] + }, + "layer": { + "const": 3 + }, + "sample_rate": { + "enum": [ + 8000, + 11025, + 12000, + 16000, + 22050, + 24000, + 32000, + 44100, + 48000 + ] + }, + "channels": { + "enum": [ + 1, + 2 + ] + }, + "channel_mode": { + "enum": [ + "stereo", + "joint_stereo", + "dual_channel", + "mono" + ], + "description": "The first audio frame's channel mode" + }, + "samples_per_frame": { + "enum": [ + 576, + 1152 + ] + }, + "frames": { + "type": "integer", + "minimum": 1, + "description": "The audio frames (the info frame is not one)" + }, + "samples": { + "type": "integer", + "minimum": 1, + "description": "frames * samples_per_frame" + }, + "duration": { + "type": "number", + "exclusiveMinimum": 0, + "description": "samples / sample_rate, in seconds" + }, + "bitrate_mode": { + "enum": [ + "constant", + "variable" + ] + }, + "bitrate_kbps": { + "type": [ + "integer", + "null" + ], + "description": "The bitrate of every audio frame, or null when they differ" + }, + "crc_frames": { + "type": "integer", + "minimum": 0, + "description": "The audio frames with a CRC" + }, + "info": { + "type": "object", + "description": "The info frame's fields: a Xing, Info or VBRI tag, and a LAME tag after a Xing or Info one", + "properties": { + "tag": { + "enum": [ + "Xing", + "Info", + "VBRI" + ] + }, + "frames": { + "type": [ + "integer", + "null" + ] + }, + "bytes": { + "type": [ + "integer", + "null" + ] + }, + "quality": { + "type": [ + "integer", + "null" + ] + }, + "encoder": { + "type": [ + "string", + "null" + ], + "description": "The LAME tag's 9-byte encoder version, when printable" + }, + "delay": { + "type": [ + "integer", + "null" + ], + "description": "The encoder delay in samples (a LAME tag's, or a VBRI tag's)" + }, + "padding": { + "type": [ + "integer", + "null" + ], + "description": "The encoder padding in samples (a LAME tag's)" + } + }, + "required": [ + "tag", + "frames", + "bytes", + "quality", + "encoder", + "delay", + "padding" + ], + "additionalProperties": false + }, + "id3v2": { + "type": "array", + "minItems": 1, + "description": "The ID3v2 tags at the start, in order: each header's version, flags and size, and whether it has a footer", + "items": { + "type": "object", + "properties": { + "version": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "minItems": 2, + "maxItems": 2 + }, + "flags": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "size": { + "type": "integer", + "minimum": 0 + }, + "footer": { + "type": "boolean" + } + }, + "required": [ + "version", + "flags", + "size", + "footer" + ], + "additionalProperties": false + } + }, + "id3v1": { + "type": "object", + "description": "The ID3v1 tag's fields: each text up to its first NUL", + "properties": { + "title": { + "$ref": "#/$defs/text" + }, + "artist": { + "$ref": "#/$defs/text" + }, + "album": { + "$ref": "#/$defs/text" + }, + "year": { + "$ref": "#/$defs/text" + }, + "comment": { + "$ref": "#/$defs/text" + }, + "track": { + "type": [ + "integer", + "null" + ], + "description": "An ID3v1.1 tag's track number" + }, + "genre": { + "type": "integer", + "minimum": 0, + "maximum": 255 + } + }, + "required": [ + "title", + "artist", + "album", + "year", + "comment", + "track", + "genre" + ], + "additionalProperties": false + }, + "ape": { + "type": "object", + "description": "The APE tag's footer fields, and the tag's whole size", + "properties": { + "version": { + "type": "integer", + "minimum": 0 + }, + "size": { + "type": "integer", + "minimum": 32 + }, + "items": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "version", + "size", + "items" + ], + "additionalProperties": false + }, + "stray_bytes": { + "type": "integer", + "minimum": 0, + "description": "The bytes between the tags that are in no frame" + } + }, + "required": [ + "version", + "layer", + "sample_rate", + "channels", + "channel_mode", + "samples_per_frame", + "frames", + "samples", + "duration", + "bitrate_mode", + "bitrate_kbps", + "crc_frames", + "stray_bytes" + ], + "additionalProperties": false + }, + { + "$ref": "#/$defs/mirror" + }, + { + "$ref": "#/$defs/mirrorView" + } + ] + }, + "headerValue": { + "description": "A translated header value (spec/conventions.md §6 )", + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/$defs/text" + }, + { + "type": "array", + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ] + } + } + ] + }, + "text": { + "description": "A text value: a string (UTF-8), or its ISO 8859-1 reading when it is not UTF-8", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "latin1": { + "type": "string" + } + }, + "required": [ + "latin1" + ], + "additionalProperties": false + } + ] + }, + "mirror": { + "type": "object", + "description": "refkv_source's: the IR mirror's description (spec/conventions.md §8.2 )", + "properties": { + "ir": { + "type": "object", + "properties": { + "version": { + "const": 2 + }, + "size": { + "type": "integer", + "minimum": 0, + "description": "The source's size in bytes (a store IR's: its objects' sizes, summed)" + }, + "objects": { + "type": "integer", + "minimum": 0, + "description": "A store IR's objects (spec/conventions.md §8.9 ); a file IR has none" + }, + "elements": { + "type": "integer", + "minimum": 1, + "description": "The elements, column runs expanded" + }, + "rows": { + "type": "integer", + "minimum": 1, + "description": "The rows the table stores" + }, + "names": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "prefixItems": [ + { + "const": "" + } + ], + "description": "The interned names, sorted; the first, \"\", is the root's (conventions §8.1 )" + }, + "types": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "prefixItems": [ + { + "const": "" + } + ], + "description": "The interned types (§8.6 )" + }, + "forms": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The interned forms, each a JSON text (§8.5 )" + } + }, + "required": [ + "version", + "size", + "elements", + "rows", + "names", + "types", + "forms" + ], + "additionalProperties": false + } + }, + "required": [ + "ir" + ], + "additionalProperties": false + }, + "mirrorView": { + "type": "object", + "description": "A view group's (refkv_source/tree/...): a struct's view document (spec/conventions.md §8.7 )", + "properties": { + "$vz": { + "const": "derived", + "description": "A derived element's document" + }, + "$form": { + "type": [ + "string", + "null" + ], + "description": "A derived element's form (§8.5 )" + }, + "$partial": { + "const": true, + "description": "The document stops short of the struct's children" + } + }, + "minProperties": 1, + "additionalProperties": { + "$ref": "#/$defs/viewValue" + } + }, + "viewValue": { + "description": "A child's view: a JSON value, a nested document, or a $vz form", + "anyOf": [ + { + "type": [ + "string", + "number", + "boolean", + "null", + "array" + ] + }, + { + "type": "object", + "properties": { + "$vz": { + "enum": [ + "alias", + "group", + "element", + "derived", + "int", + "float", + "bytes", + "utf16" + ] + } + }, + "required": [ + "$vz" + ] + }, + { + "type": "object" + } + ] + }, + "nodeProperty": { + "type": "object", + "description": "Any other node's property: its source metadata only", + "properties": { + "mp3": { + "$ref": "#/$defs/sourceMetadata" + } + }, + "required": [ + "mp3" + ], + "additionalProperties": false + } + } +} diff --git a/spec/virtualize/profiles.json b/spec/virtualize/profiles.json index 1f8a46a0..a49a22c5 100644 --- a/spec/virtualize/profiles.json +++ b/spec/virtualize/profiles.json @@ -200,5 +200,20 @@ "source": "Olympus VSI", "inputs": "Olympus cellSens VSI slides: a `.vsi` file and the tile files beside it, probed by key (uncompressed, JPEG and JPEG 2000 tiles)", "for": "Olympus cellSens whole-slide images (`.vsi` with its tile files)" + }, + { + "name": "mp3", + "section": 16, + "title": "MP3", + "uuid": "b6cb0047-9448-4fdc-b03e-10dd3d6aa829", + "version": 0, + "kind": "file", + "suffixes": [ + ".mp3" + ], + "reference": null, + "source": "MP3 (MPEG Layer III audio)", + "inputs": "MPEG-1, MPEG-2 and MPEG-2.5 Layer III audio files (`.mp3`), with their ID3v2, ID3v1 and APE tags; one array of samples, not an image", + "for": "MP3 audio files, as an array of samples (`.mp3`)" } ] diff --git a/uv.lock b/uv.lock index ac9a4440..2536e1e5 100644 --- a/uv.lock +++ b/uv.lock @@ -230,6 +230,91 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/a7/71ac2cff56fec219ed242bb11b8efb69fcc4bec75db06fb7bfe35de520e6/certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", size = 136983, upload-time = "2026-07-22T03:35:11.276Z" }, ] +[[package]] +name = "cffi" +version = "2.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/ef/008a1939e372c06329a3fce4279c02f328488f3526744906eeec3da7ad5f/cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be", size = 530807, upload-time = "2026-08-03T21:21:18.939Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/69/43965eccfdead3b9220015fd1320e117be8c6ed01a62ffab76eeb752f5d5/cffi-2.1.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0", size = 184821, upload-time = "2026-08-03T21:19:44.887Z" }, + { url = "https://files.pythonhosted.org/packages/54/7d/16e5a096677b5e313ca80cd5e5170efa3ea44624a82bb111925522da64b1/cffi-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf", size = 184719, upload-time = "2026-08-03T21:19:46.129Z" }, + { url = "https://files.pythonhosted.org/packages/56/e6/8941622732edec876dd17d0453dce07317ae96db34f2ec1436c9d3785986/cffi-2.1.1-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a", size = 214799, upload-time = "2026-08-03T21:19:47.218Z" }, + { url = "https://files.pythonhosted.org/packages/44/de/f98430906df1545ffde0d543dd124a7a439bc2cd32b36b9c53f805df7333/cffi-2.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890", size = 222389, upload-time = "2026-08-03T21:19:48.331Z" }, + { url = "https://files.pythonhosted.org/packages/6a/5b/717f1526b9957b34456313c31645c5b82b8fb5c3fe9e4752999be7128bfc/cffi-2.1.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50", size = 210249, upload-time = "2026-08-03T21:19:49.543Z" }, + { url = "https://files.pythonhosted.org/packages/64/b3/f8aa4f3e34986c7e4ec45072d1b1b9dd295b6b18007b45518d79726dd725/cffi-2.1.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e", size = 208775, upload-time = "2026-08-03T21:19:50.918Z" }, + { url = "https://files.pythonhosted.org/packages/b1/db/dceb9dd5b231e1da801793f8acc9f3c52a7e1afe40bb1aae37e02b0faad5/cffi-2.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf", size = 221822, upload-time = "2026-08-03T21:19:52.054Z" }, + { url = "https://files.pythonhosted.org/packages/a0/d2/6cd24ae3be000a634109c247d1475d62e5616d0dc78c82770942ec384248/cffi-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517", size = 225232, upload-time = "2026-08-03T21:19:53.109Z" }, + { url = "https://files.pythonhosted.org/packages/cb/52/3fa190537004dd7f0ab860a6dc7c0175b8667f68d1e618a46f5498d30250/cffi-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735", size = 223597, upload-time = "2026-08-03T21:19:54.515Z" }, + { url = "https://files.pythonhosted.org/packages/80/fb/0bb75b7039588c074b37ae99f40d9bfddf990ecb2fbc346ebccd2e56b9be/cffi-2.1.1-cp312-cp312-win32.whl", hash = "sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e", size = 175292, upload-time = "2026-08-03T21:19:55.566Z" }, + { url = "https://files.pythonhosted.org/packages/d9/79/615cc094e2fb508cade7de88d3b4f6c4ec2bab695c97bce9153dc65aadf5/cffi-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a", size = 185919, upload-time = "2026-08-03T21:19:56.89Z" }, + { url = "https://files.pythonhosted.org/packages/70/c6/d0ea84713fe46b243a436a18fcd47d639732747e21635c8a27191b06dc30/cffi-2.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80", size = 180093, upload-time = "2026-08-03T21:19:58.155Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f4/035513d4117049066b4779dc3b7c0c0fdad175fa13731c9f4003f1cd1478/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e", size = 194248, upload-time = "2026-08-03T21:19:59.399Z" }, + { url = "https://files.pythonhosted.org/packages/76/af/2aeb4dbb5fc41a04161ae9ff1518de7cec08e164f44a8ce6a4cf7fd2cd1d/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c", size = 196908, upload-time = "2026-08-03T21:20:00.746Z" }, + { url = "https://files.pythonhosted.org/packages/a7/46/2e5fdde8555706dd98139a910ca11be02809f3f605ce956f655d0214e100/cffi-2.1.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6", size = 184805, upload-time = "2026-08-03T21:20:02.02Z" }, + { url = "https://files.pythonhosted.org/packages/55/41/4c7042f317b9217502988f0873af87e16ad606dc20f84e546e3e6ce9764c/cffi-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971", size = 184764, upload-time = "2026-08-03T21:20:03.141Z" }, + { url = "https://files.pythonhosted.org/packages/43/1f/1c3d90d91811c8f86ced9ed637956c54bfe5b79ca98fe976d7f8c8979f6b/cffi-2.1.1-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c", size = 214722, upload-time = "2026-08-03T21:20:04.377Z" }, + { url = "https://files.pythonhosted.org/packages/37/6f/3b5ce4c3b2192d250f04908f2bfd91ef34552ec8f7716a5d4abdb8d67bb2/cffi-2.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125", size = 222369, upload-time = "2026-08-03T21:20:05.544Z" }, + { url = "https://files.pythonhosted.org/packages/02/10/4b3c75dde3d9663c9e02ba05c2668b954f671d4bbe346413ca8c696b295a/cffi-2.1.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264", size = 210175, upload-time = "2026-08-03T21:20:06.75Z" }, + { url = "https://files.pythonhosted.org/packages/df/62/14f74b9543e605d17701dc797b815958b8bb70b7624ce1b832ddad48ed6c/cffi-2.1.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3", size = 208670, upload-time = "2026-08-03T21:20:08.04Z" }, + { url = "https://files.pythonhosted.org/packages/95/95/86342356ff5953b3fb06f7ef7c5bee212d45e770abc7218d451b9148313c/cffi-2.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2", size = 221824, upload-time = "2026-08-03T21:20:09.274Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ff/7b3429ff53aafe931ed8a5fc69f481bbef7ba6de87ddcbb63d08f483f613/cffi-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b", size = 225148, upload-time = "2026-08-03T21:20:10.7Z" }, + { url = "https://files.pythonhosted.org/packages/34/34/a95870b9221e09cf4f2ce3178b1a210abdfe63a1bd357da940418d7b8d15/cffi-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7", size = 223564, upload-time = "2026-08-03T21:20:12.165Z" }, + { url = "https://files.pythonhosted.org/packages/70/ea/839b50531021a647fb5e929f72cf97bc1ff702b5472166164b5b6e76b851/cffi-2.1.1-cp313-cp313-win32.whl", hash = "sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac", size = 175263, upload-time = "2026-08-03T21:20:13.559Z" }, + { url = "https://files.pythonhosted.org/packages/60/a6/8b149b2c3f2e11aaa1618ef64500b45f50f22c57a977a4dff1aff1f91042/cffi-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d", size = 185688, upload-time = "2026-08-03T21:20:14.69Z" }, + { url = "https://files.pythonhosted.org/packages/01/9a/11f687cb39d6a3504060d5242f04f48c735afb4d3d533958a20594890cb2/cffi-2.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973", size = 180078, upload-time = "2026-08-03T21:20:15.917Z" }, + { url = "https://files.pythonhosted.org/packages/d3/7b/d6bbf82b8b96e7391438898c42f5bd96dd02030fd5b64937d248220003e2/cffi-2.1.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7dbb61fe3a7699468030f71bbe5f8a0e326a151daa91beb11a6fc1f980c55e1c", size = 194064, upload-time = "2026-08-03T21:20:17.148Z" }, + { url = "https://files.pythonhosted.org/packages/94/e6/bcc91b283be94735e268487a054004f0aa19947b6348fa367db53230abc8/cffi-2.1.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:f24fb43132a4c6b4cb4eb029492919b2db645be6808d738f244fd146c03c32cb", size = 196720, upload-time = "2026-08-03T21:20:18.268Z" }, + { url = "https://files.pythonhosted.org/packages/d9/99/c4b0c17cacdc9c3b8f280026286a9826d6a208c0f047591a3c3ce99b91fd/cffi-2.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d28630f5854ab07ab1fd4aba756de52326c82e6be15d414b12793f1975048b54", size = 184964, upload-time = "2026-08-03T21:20:19.708Z" }, + { url = "https://files.pythonhosted.org/packages/b3/a9/9db617d05d7367c1ad0ab00b3aa6e6f9281edd689b4ee9ea0e5a84e89c97/cffi-2.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:661c298b4821edebead0c91edd2b00374d67ad7c5a1f7a91d4442633b79d6a72", size = 184962, upload-time = "2026-08-03T21:20:20.833Z" }, + { url = "https://files.pythonhosted.org/packages/67/b8/b42132ca113dc567d37684437b46ca1dafc885902b02a110a02d5b511857/cffi-2.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:58acb8ab8e295e6c5ea12f888cbb13cf21511ef2a3303a23f4325c29d17fe5c1", size = 222328, upload-time = "2026-08-03T21:20:22.118Z" }, + { url = "https://files.pythonhosted.org/packages/80/10/c5c0cbf0a657aecf59ef511409734230bf556f05a0d6c9eed7aa5c0a0166/cffi-2.1.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:456a61fa52d579ebf9df2e9552ead5129855dbaff6c1e5a9b1bc408809bdc062", size = 209985, upload-time = "2026-08-03T21:20:23.401Z" }, + { url = "https://files.pythonhosted.org/packages/d5/6c/bfa0b87b03b9238148beca990292843c9396ba069b54496596594173de7b/cffi-2.1.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a4f00aa42f75d6e4595e8866e748cc1705adc0cddfeb2ca86d0d03993d63ba03", size = 208530, upload-time = "2026-08-03T21:20:24.628Z" }, + { url = "https://files.pythonhosted.org/packages/e9/02/4e7d553a7ac4b4238b38b3c1b80d486e9d4436f8d2acbf87a0997fe3f402/cffi-2.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b0431303acaea1089ad4b3e9ce4e6518193def1118d4073ca848635ee4ea2e96", size = 221525, upload-time = "2026-08-03T21:20:25.758Z" }, + { url = "https://files.pythonhosted.org/packages/82/1d/a4aaf9babd75acb4d5f223bff71533bee748dd770a382619a798960ee9ba/cffi-2.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:64faea20f4e2613363a1a9b9c7dd73058f3ecd00133a511e72ad7c511658f527", size = 225053, upload-time = "2026-08-03T21:20:26.985Z" }, + { url = "https://files.pythonhosted.org/packages/81/10/5dc0e7bdd18e22107054288283380fc97a06ae3f1656a106908d666a3c88/cffi-2.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5c58fe613dc5e5336357eff555824a314d8e43282600435c8d1cb6a7a2fedd13", size = 223213, upload-time = "2026-08-03T21:20:28.277Z" }, + { url = "https://files.pythonhosted.org/packages/0b/e9/d0061c364cde06ee43168a0d076ac1da512cbc380d44767b844ba34fe2b6/cffi-2.1.1-cp314-cp314-win32.whl", hash = "sha256:1a18a57b58cfb21fc28d72e876acf10eaed67a1ed96226f92af4df681d571c4c", size = 177682, upload-time = "2026-08-03T21:20:44.288Z" }, + { url = "https://files.pythonhosted.org/packages/a7/06/1c3e01e3ba14c39f6d10bfbac52753b7e22259e38088e5cfe1d704918690/cffi-2.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:3222ba5d678f80a030e6afbcc33dc1ae5cb45facabb61cee2c7016b8432fde48", size = 187949, upload-time = "2026-08-03T21:20:45.623Z" }, + { url = "https://files.pythonhosted.org/packages/87/5b/da4e39efe18eeb89cf580ea9cfc66b6a7c3eadb808fc0cc1d3a295cb5a5d/cffi-2.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:ab36d55f9ed2d067327667c2fea18dda018eb628dd6347aa01dda6cf1f5d3836", size = 182947, upload-time = "2026-08-03T21:20:46.955Z" }, + { url = "https://files.pythonhosted.org/packages/23/59/40338bf421c5accea1d45158170c87006ef1cd371b05c077e76476949728/cffi-2.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7750c6449dff7864bb9bb27ddfb0267756189201a3afc911d82b3caacd70dfc3", size = 188504, upload-time = "2026-08-03T21:20:29.495Z" }, + { url = "https://files.pythonhosted.org/packages/7d/47/5ecf1023850036e674c77ec4de86182d309ae344e39e7cba984b7df5d647/cffi-2.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0beceaabe56af686895136a2de78db54ecd8e4046b236b8fd6d6cb61389e9bf2", size = 188259, upload-time = "2026-08-03T21:20:31.291Z" }, + { url = "https://files.pythonhosted.org/packages/2a/9c/92934c3bea9f785b23eba304538c0b4d37a2a96d2431eb3a1bc87a11aa19/cffi-2.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:49cbc70e6542d4ccccb936558d1064a8012541e78f821f955cff24e357776c94", size = 223864, upload-time = "2026-08-03T21:20:32.571Z" }, + { url = "https://files.pythonhosted.org/packages/4d/45/ba4c93527bc38616a8bd36488acb69a2212d60486794f0c1f318949bbb76/cffi-2.1.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e2d65b31f36619cda3999b78b2aa9632e76b78448e7a56fc4240824200e7c4fc", size = 211538, upload-time = "2026-08-03T21:20:33.808Z" }, + { url = "https://files.pythonhosted.org/packages/80/e9/b6ef565e452acb932fb0cb5443f44a78efbd1233e566f02b5a83855e9115/cffi-2.1.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:28907ab9bfb6aa13184cfc17c6b8e1023c5ab6fd7076d8c20a35e59fe04f8f29", size = 210688, upload-time = "2026-08-03T21:20:34.974Z" }, + { url = "https://files.pythonhosted.org/packages/9a/95/eff5f0cee78d2eabc7eebffec40d3fc1876b5f3c95582e018bb4b99601f2/cffi-2.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51b31d1c98274844cfd7838ce00bfc27c7423a4dc00fc0772fc3331c2cc90676", size = 223803, upload-time = "2026-08-03T21:20:36.564Z" }, + { url = "https://files.pythonhosted.org/packages/fa/01/579d39fb8bef00a335a23d83757b44feb24cd6345a2c451b64cb67b9c362/cffi-2.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e7cecbaadb83884793e05828cee59b210b24583b9c7425d0ba6a754fe22eb4e", size = 226763, upload-time = "2026-08-03T21:20:37.816Z" }, + { url = "https://files.pythonhosted.org/packages/8d/b0/0b44f47c60b01b57b6e2bbd92343f13a85a1d93bc46ccf6e47e244acd99c/cffi-2.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:25792eac27877609e7bb06d42ff88278a6624fff2ba9bbb523c09616b117e80f", size = 225688, upload-time = "2026-08-03T21:20:38.959Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d2/3b7176cb570a1d3e27faf67b72f591af508036e0d8b2be2ef9af9e8c84bb/cffi-2.1.1-cp314-cp314t-win32.whl", hash = "sha256:8ef53b2de9bcb9197d31854256575d59dbac0cba72ac627bb291ef5eceb74be4", size = 182868, upload-time = "2026-08-03T21:20:40.388Z" }, + { url = "https://files.pythonhosted.org/packages/56/78/31f00c1bcd97c9bbf55f1bfdf5bc809a5de8887473e90bb9960dca825e80/cffi-2.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:616f097f2fe415bc92a247f02e11f634e1f9e9a83d327e3c915c15089c87869e", size = 194104, upload-time = "2026-08-03T21:20:41.725Z" }, + { url = "https://files.pythonhosted.org/packages/7b/1b/58496f2ed0a35de575250c02a43ab3cc2c04d494a88fed31c1cabc0fd176/cffi-2.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ad2c86c495b899d862ea0f4b42891b8713a3bd45dd4105c7fd51c2a72f39f3a5", size = 186402, upload-time = "2026-08-03T21:20:43.042Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8f/9ebe220eab48a093d1a5a5e339ab0dc7316eef3bb04d63c42f0251b61f50/cffi-2.1.1-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:dddad92b554513a31f272570678ba307fb9f618f05e3d4a5eacafff9eae03e1d", size = 194043, upload-time = "2026-08-03T21:20:48.179Z" }, + { url = "https://files.pythonhosted.org/packages/ff/69/844bad3ece306c4782c2ecb93597035b6690d48704b803914c199da1e8b3/cffi-2.1.1-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:da0e573f9f97159390c89d9f1a9e41908b66d408cc5b58d08cf3847d844c531b", size = 196737, upload-time = "2026-08-03T21:20:49.457Z" }, + { url = "https://files.pythonhosted.org/packages/1b/8a/af668013284634733f02d683458a0728739c7d6ddb5e14cb0c20832266fe/cffi-2.1.1-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:fb92203a88b3d3053034db775110081c49d28be6551923805e039924093761e4", size = 184933, upload-time = "2026-08-03T21:20:50.639Z" }, + { url = "https://files.pythonhosted.org/packages/0c/75/2f5207ff6d1a613133b23a5203cc0c2a628313b5eb3974d7956ae3c57950/cffi-2.1.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2ae64be792b8966f2c69538199728b290e34726562896df1e5dc8ffd8d8188e8", size = 185002, upload-time = "2026-08-03T21:20:52.173Z" }, + { url = "https://files.pythonhosted.org/packages/e2/31/9e1313b0a6e30e91b3b3d3fff51ae99c857c07738e3afcce1f7334e1b7ab/cffi-2.1.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:507a24c282e0f42f8ed737cf048572cbf580468da5555764a8331735e9c736b6", size = 222271, upload-time = "2026-08-03T21:20:53.462Z" }, + { url = "https://files.pythonhosted.org/packages/50/e3/f6234a833e6e08c7007003074723c406559eecf9b48dfc97471e5a8eb7a0/cffi-2.1.1-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:246fa40ce8645a614ff682e0b70f37134e460eaf93a775e0cbe3cca585a67a80", size = 209919, upload-time = "2026-08-03T21:20:54.783Z" }, + { url = "https://files.pythonhosted.org/packages/0d/fc/5f74e293fced6edb51af3a46c4ccf6c23c9943774ecb375ddbd522c76add/cffi-2.1.1-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:471cee653ae88de62096552e6d24ccb4a5adb8c8c9f10b5054d0122c15bf2779", size = 208529, upload-time = "2026-08-03T21:20:56.066Z" }, + { url = "https://files.pythonhosted.org/packages/44/16/29e6d01b388bef055ecd6ca8244b3f4d336bd09e92d5d892187b9601084e/cffi-2.1.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aeae0e330c9f6acd681f647d46cefd30c29f93e3392882e792e82080c9691399", size = 221630, upload-time = "2026-08-03T21:20:57.336Z" }, + { url = "https://files.pythonhosted.org/packages/a4/18/fa7f1f6857d5eb88a4ca99ffcbfb7c387a287ccc154c64a73e86314745d7/cffi-2.1.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:42a494cee34437f05546455144f2b5d9ac09b1face62bcfce597d2e521066688", size = 225134, upload-time = "2026-08-03T21:20:58.675Z" }, + { url = "https://files.pythonhosted.org/packages/e0/9f/e8e3dfa04a1b4c241f8c91faacad872b4d4efd051d49764ad4e2fd4b9fea/cffi-2.1.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:cc572dace3f60ef98d7b12ff411d20f5362feb31a0439eab0085bbfd349982d7", size = 223197, upload-time = "2026-08-03T21:20:59.968Z" }, + { url = "https://files.pythonhosted.org/packages/f8/7e/8debeb04f1ab9fe2a6963964cd6f1aaf7192627b83926586a6a4e089c9fa/cffi-2.1.1-cp315-cp315-win32.whl", hash = "sha256:4f42141fc14250de6dde5ee7ea4432be017252d91f19c5ad043c084cea629cac", size = 177683, upload-time = "2026-08-03T21:21:14.901Z" }, + { url = "https://files.pythonhosted.org/packages/e0/31/5158704cc474ab65c1647932e88be78dc0873f47130e253be38bcaf13d01/cffi-2.1.1-cp315-cp315-win_amd64.whl", hash = "sha256:e6e8cff14d6fb0be70a09c0bdc58096f501952d04624ebf867e0e56da2df8960", size = 187897, upload-time = "2026-08-03T21:21:16.108Z" }, + { url = "https://files.pythonhosted.org/packages/cc/4b/b3a2da8570c704ffc0f9762cdc3ec0f02c8573798e0b5cf7f11c82bbb70f/cffi-2.1.1-cp315-cp315-win_arm64.whl", hash = "sha256:27350daa11d4f10c540e6e89dada4c54feb7256ad03e9a4dc075ebad7ba360d1", size = 182935, upload-time = "2026-08-03T21:21:17.271Z" }, + { url = "https://files.pythonhosted.org/packages/d0/ef/5443574510a1207e6f6bc38ba6e1f1de36cb48fef07b2728bb896a21f430/cffi-2.1.1-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:c26608d2222fb1e94487e4a387d85f13eb55d5ed725cb25a0c589ac4ee60e7bc", size = 188464, upload-time = "2026-08-03T21:21:01.163Z" }, + { url = "https://files.pythonhosted.org/packages/7e/ae/a56fa8c4686ad50e148fcbc8d3ae0d03915ff5c30d795058988c24118cef/cffi-2.1.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:4be96343e422f2dfcd12ab5c9f5aebe03f82f737c6bffeca6830b3875cb44aab", size = 188262, upload-time = "2026-08-03T21:21:02.382Z" }, + { url = "https://files.pythonhosted.org/packages/53/b2/6187f46f2912276a3ae284076109cc5c8680482f11f766ccf26db4a86427/cffi-2.1.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:937c0052c05a31ca1daf18de3158eed4dbfcb9cc107adbea227728d647be701e", size = 223779, upload-time = "2026-08-03T21:21:03.553Z" }, + { url = "https://files.pythonhosted.org/packages/8a/f6/c3ad28bd19f77047a03084424fbd4cbe997303267c14423737324be0385d/cffi-2.1.1-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:df423d40ee8654634421812bc3b196da3f9bd7d32929da813f8394c4348a5358", size = 211520, upload-time = "2026-08-03T21:21:04.863Z" }, + { url = "https://files.pythonhosted.org/packages/a0/cd/ccac9013a5bd9fd764de118674ab9c805b5ca10c19270d90ee273f8b2240/cffi-2.1.1-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a730a083190634c65cca36ba5f489531576ebd79bcd5c8e172130f6453127231", size = 210673, upload-time = "2026-08-03T21:21:06.223Z" }, + { url = "https://files.pythonhosted.org/packages/52/86/2976131c639aead931c5bee5aba67e4b09fbeb8018b6f282f70803f923a7/cffi-2.1.1-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:363e05fa78e15116c3c32c210ee36884fd6b9afa6d440e47112c3bd511d64cb6", size = 223835, upload-time = "2026-08-03T21:21:07.539Z" }, + { url = "https://files.pythonhosted.org/packages/ac/0c/33a7aeab2f9c76918c52e084beb39c570db3588133412929e8ec06fab90b/cffi-2.1.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:770de9db11e84213beec501cfcaa013b019820ca881e03344dea5844f7876d94", size = 226705, upload-time = "2026-08-03T21:21:08.774Z" }, + { url = "https://files.pythonhosted.org/packages/e3/26/2cde30fdde421130bfc18f70395731a6e6b2053c6a1978a5258ff04e72fa/cffi-2.1.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:7da0c5eff80f0197f3b3d1232ec5a682a9325f4ae9016a78f5f5ca35f9ced1f5", size = 225539, upload-time = "2026-08-03T21:21:09.911Z" }, + { url = "https://files.pythonhosted.org/packages/6d/cd/a361394c94b2129d604bb846f624a8e88255a3ee33129c434a00d715e64f/cffi-2.1.1-cp315-cp315t-win32.whl", hash = "sha256:06c72bb76605a4b0cd0aad6930b69d4baf7dd5d806cfc409b824191099700e66", size = 182707, upload-time = "2026-08-03T21:21:11.226Z" }, + { url = "https://files.pythonhosted.org/packages/9b/b5/ba2b299993c26577d529b6ae29841f9e15b9fcf004d65f423f4fcf94ade9/cffi-2.1.1-cp315-cp315t-win_amd64.whl", hash = "sha256:d9c275eaacd24aa73f94ffd6de08fc3f932424d8b6c376f4bed7cde376fe7bc3", size = 193772, upload-time = "2026-08-03T21:21:12.39Z" }, + { url = "https://files.pythonhosted.org/packages/aa/29/35e016098c814cd93de9cd320c66b5bfba14dc6ecedd3cb518fa7c408c69/cffi-2.1.1-cp315-cp315t-win_arm64.whl", hash = "sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692", size = 186360, upload-time = "2026-08-03T21:21:13.636Z" }, +] + [[package]] name = "charset-normalizer" version = "3.5.2" @@ -1266,6 +1351,35 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/92/f9/ecbde7149e95b8a0f18e16d5d747f7dc06049d5da2e4f77f6f5e4a1f46a8/markupsafe-3.0.4-cp315-cp315t-win_arm64.whl", hash = "sha256:39dbacefc411633db5b4378b066a9aca70a3d7e2922c9e578d825f844026eeba", size = 14417, upload-time = "2026-10-02T23:06:56.246Z" }, ] +[[package]] +name = "miniaudio" +version = "1.71" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d8/d5/e5439dc08561f73656bfeb3340fc64ab63163e101426593d8fb9a025ff1e/miniaudio-1.71.tar.gz", hash = "sha256:ff51e2887bb673e2e757752b586b3dc924d59aa5fbcae9bbc45f4a111bd3262b", size = 1116480, upload-time = "2026-04-29T21:20:38.182Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/d3/71124f5abbcdcae62e040f58d3dca3bd3d90fd01faa7bb276b112387b47a/miniaudio-1.71-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:62db602651bc20a2698f36a0d356d7217ed6f4f917550c7ffb3705c8e8be90cf", size = 377186, upload-time = "2026-04-29T21:20:16.713Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ac/30a324f758bed1b193e017ec25183cfb10a79e549656331f5d068a2d343a/miniaudio-1.71-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fc1a4f084cc1b4b25c567d22f54d1e46bfa505c17ed777c8b198e5c53d0f785", size = 351485, upload-time = "2026-04-29T21:20:17.761Z" }, + { url = "https://files.pythonhosted.org/packages/fa/62/ae884a9d3b2ebec9c2ed1db857593e74bff45b70c4ab17fccc11db31cbeb/miniaudio-1.71-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:19be6f0a1e601c2237433e579734cfaf6469191b224c20c9e5f73c32ef9ee2b9", size = 643556, upload-time = "2026-04-29T21:20:18.87Z" }, + { url = "https://files.pythonhosted.org/packages/a5/39/84fc665e2ea8f9f1301b6370226e3a24f08d5ad5d97143b69b4ae7ac260a/miniaudio-1.71-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e6287f15caa808a88aad0700a182bec1ff6d98769717425adf9ebf41259d1936", size = 645176, upload-time = "2026-04-29T21:20:20.194Z" }, + { url = "https://files.pythonhosted.org/packages/81/b8/37d9f67d4511da29bdb82b6c73a3ef6f4ebf2fbd30f9524f1e4a84d6f033/miniaudio-1.71-cp312-cp312-win32.whl", hash = "sha256:ab100e5240b104b5326e4ec1be07b6ae461f7d3d4d7a694857fd2f0493d210f9", size = 235095, upload-time = "2026-04-29T21:20:21.653Z" }, + { url = "https://files.pythonhosted.org/packages/fd/cf/c1a19e6800e725b6e2b4576407620a798d69e3528ebdea9aea84d69d7088/miniaudio-1.71-cp312-cp312-win_amd64.whl", hash = "sha256:f4a44b70b66628b0c307e40ae0ae857695978cae18462179b806d8edc807d416", size = 274252, upload-time = "2026-04-29T21:20:22.824Z" }, + { url = "https://files.pythonhosted.org/packages/3a/85/44545f767ec21142ffed5f9108406d11dc8a19aafed9bd57621a0892bb60/miniaudio-1.71-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:61b86f26d653040db32d9d15b05446321dd10e45beba25b44f841e26935213d5", size = 377184, upload-time = "2026-04-29T21:20:24.109Z" }, + { url = "https://files.pythonhosted.org/packages/bd/d1/071a560000c8ce903dc919968ecce40fbe7a73213ac399051b887184f8a3/miniaudio-1.71-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d9dc15eff711bcfc62a9d05e0c78e4bc34821a455595e049629f2fea7491a523", size = 351488, upload-time = "2026-04-29T21:20:25.183Z" }, + { url = "https://files.pythonhosted.org/packages/46/24/5873a569451cae5686fb656ebd78ffe0b5eebe48ca21ef61e227d237d20a/miniaudio-1.71-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:12bc33e7e61072b4b541c14e10ef76119d5643e6bbb98e2dec0c0738889438fb", size = 643552, upload-time = "2026-04-29T21:20:26.211Z" }, + { url = "https://files.pythonhosted.org/packages/90/9b/25785525e6b5ff9afd7f4c4279215dc09c3317ea4d837275b1ae17912b36/miniaudio-1.71-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:70fa2ea5353e6919aca59b8c5768144af009d18c3bca251749d66fb497424563", size = 645171, upload-time = "2026-04-29T21:20:27.494Z" }, + { url = "https://files.pythonhosted.org/packages/b1/6d/cbfd55fdc40256231f7b0c861e2bf79cc289bfbbe5e15869317944e6d673/miniaudio-1.71-cp313-cp313-win32.whl", hash = "sha256:1bf93aeede652926f27f430f0fd69ef0cf8a949c07b537d6a2f295602c747037", size = 235088, upload-time = "2026-04-29T21:20:29.031Z" }, + { url = "https://files.pythonhosted.org/packages/8d/8d/d5059c04b247b1079c0e48914a9ec20352910a3b9373060fb258dfd194ab/miniaudio-1.71-cp313-cp313-win_amd64.whl", hash = "sha256:4c849ccb1349f7b3553a77a66fe7e972315185f5c4c44a0bbda7ebcdd224db37", size = 274247, upload-time = "2026-04-29T21:20:29.96Z" }, + { url = "https://files.pythonhosted.org/packages/16/e7/b3e0df641d2d5283446d7960fc407195ba722b9a0789bb0a1429bf9ee855/miniaudio-1.71-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3ef441d139264f8a5dcb9aa6fcd0b1e1e69f58715baae416ff33f045ffba6ad5", size = 378418, upload-time = "2026-04-29T21:20:31.341Z" }, + { url = "https://files.pythonhosted.org/packages/66/ea/f5940232d0c83777562e802f376a841046d78e94753450fb9a6685a44190/miniaudio-1.71-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:84139a10ef172acd762ccf120142877b037a1aaf71def99d2c75f66329f89d8b", size = 351473, upload-time = "2026-04-29T21:20:32.464Z" }, + { url = "https://files.pythonhosted.org/packages/fd/a6/6b5ae21b74fe70da935de389e01b3cce86c790ca4083f6a63c3ee922673e/miniaudio-1.71-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a28ff4ad23e55bbde8808ce525d3bb7d249d7612f77646b30e06fc6b7a778ac", size = 643683, upload-time = "2026-04-29T21:20:33.598Z" }, + { url = "https://files.pythonhosted.org/packages/4b/43/ef851e2e1d9dfde2b97cc053f0d79c6612088b27044698ed5d8c687f05de/miniaudio-1.71-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:33986d5d725ebcbc253551e7358689bc81b19b6950b33cec8e8c1142ca4fc0a9", size = 645203, upload-time = "2026-04-29T21:20:34.713Z" }, + { url = "https://files.pythonhosted.org/packages/1b/4a/0da61fea8b8469d51b77d43846572ef9255d54c9b6b65a552446bbd55f90/miniaudio-1.71-cp314-cp314-win32.whl", hash = "sha256:3bbeb1e068fe42475e017e8150e9e345182b583d0dd4d9e77ffa20c39935d9ec", size = 241126, upload-time = "2026-04-29T21:20:35.975Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d0/ad7bfa63e1baacd2d4803ee04862bb06fcfbbb34a340bf2bf3979e0068dc/miniaudio-1.71-cp314-cp314-win_amd64.whl", hash = "sha256:154b085dd914a0e79e3d93160e1a07aacb27d66c65f9ef6a0d87c1a194f32c04", size = 281740, upload-time = "2026-04-29T21:20:37.07Z" }, +] + [[package]] name = "mrcfile" version = "1.5.4" @@ -2123,6 +2237,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/93/c0/37d4a7e8e2f7a6076283673d5298018ca26478b934c6ee369e10505ab32c/pyarrow-25.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:4288f27577352d608ca08553b0865e4a9b3aa14820c5d95b53337218d609835b", size = 28753071, upload-time = "2026-08-10T12:40:46.623Z" }, ] +[[package]] +name = "pycparser" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/a8/c5fdbeee588bb8ada9458774f43adf1bdd30bd59157055142183e769a024/pycparser-3.11.tar.gz", hash = "sha256:d875f09c3507d00e1aba0eecc6dcadc1352f30fff09dc6bff2f1c2935e97c2bc", size = 113796, upload-time = "2026-10-09T12:56:59.539Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/11/0e6f11117525ff0eec40ebac3d313376f102df93ca44ad9e893ee85e4f89/pycparser-3.11-py3-none-any.whl", hash = "sha256:51d5a8ba2be0bbe440b99d2112604c95bbbc3c2748a64260186c541e1729cd80", size = 51178, upload-time = "2026-10-09T12:56:58.131Z" }, +] + [[package]] name = "pydantic" version = "2.12.5" @@ -2512,6 +2635,10 @@ dependencies = [ ] [package.optional-dependencies] +audio = [ + { name = "miniaudio" }, + { name = "zarr" }, +] images = [ { name = "imagecodecs" }, { name = "zarr" }, @@ -2532,14 +2659,16 @@ zarr = [ requires-dist = [ { name = "google-crc32c", specifier = ">=1.9.0" }, { name = "imagecodecs", marker = "extra == 'images'", specifier = ">=2026.8.16" }, + { name = "miniaudio", marker = "extra == 'audio'", specifier = ">=1.59" }, { name = "numpy", specifier = ">=2.5.3" }, { name = "obstore", marker = "extra == 'obstore'", specifier = ">=0.11.1" }, + { name = "refkv", extras = ["zarr"], marker = "extra == 'audio'", editable = "python" }, { name = "refkv", extras = ["zarr"], marker = "extra == 'images'", editable = "python" }, { name = "refkv", extras = ["zarr", "obstore"], marker = "extra == 'virtualizarr'", editable = "python" }, { name = "virtualizarr", marker = "extra == 'virtualizarr'", specifier = ">=2.7.3" }, { name = "zarr", marker = "extra == 'zarr'", specifier = ">=3.4.0" }, ] -provides-extras = ["images", "obstore", "virtualizarr", "zarr"] +provides-extras = ["audio", "images", "obstore", "virtualizarr", "zarr"] [[package]] name = "refkv-workspace" @@ -2572,7 +2701,7 @@ dev = [ { name = "pyproj" }, { name = "pytest" }, { name = "rasterio" }, - { name = "refkv", extra = ["images", "obstore", "virtualizarr", "zarr"] }, + { name = "refkv", extra = ["audio", "images", "obstore", "virtualizarr", "zarr"] }, { name = "tifffile" }, { name = "xarray" }, { name = "zarr-n5" }, @@ -2605,7 +2734,7 @@ dev = [ { name = "pyproj", specifier = ">=3.8.0" }, { name = "pytest", specifier = ">=9.1.1" }, { name = "rasterio", specifier = ">=1.5.2" }, - { name = "refkv", extras = ["zarr", "images", "virtualizarr", "obstore"], editable = "python" }, + { name = "refkv", extras = ["zarr", "images", "audio", "virtualizarr", "obstore"], editable = "python" }, { name = "tifffile", specifier = ">=2026.9.20" }, { name = "xarray", specifier = ">=2026.9.0" }, { name = "zarr-n5", specifier = ">=0.3.1" },