Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ Notable changes to `samplerdisc`. Format-level findings live in [docs/formats/](

### Added

- **E-mu samples carry their loop points.** The 92-byte sample record's undecoded middle is an eight-pointer block — a start, an end, a loop start and a loop end, per channel, as byte offsets from the record's own start — and **8 039 of the 14 738** E-mu samples now come out with those loop points in the WAV's `smpl` chunk: 107, 1 157, 1 260, 1 689, 449, 2 551 and 826 across the seven reference discs. Every other backend has carried this since D7; the E-mu path carried none. ([docs/formats/emu3.md](docs/formats/emu3.md), [ADR-0025](docs/adr/0025-the-loop-is-decoded-the-root-key-is-not.md))

**The loop was established from the audio, not from the structure fitting.** Correlating the waveform at the loop start against the waveform at the loop end gives **+0.64 to +0.86 on six of the seven discs**, against a control — the same loop end with the start put somewhere else — of about zero on all of them. Three publishers and both E-mu generations agree. `eiv-analogia` is the exception and is reported as one: only 34 of its records carry audio loud enough at both ends to score, and those 34 show nothing, so its loops rest on the rule the other six establish.

**A loop end past the audio is refused, not clamped.** AKAI and Roland both clamp a declared end back to the audio present, because these rips run short of their directories. Doing it here destroys the loop, and `protozoa` shows it on one disc: of its one-channel records, the 689 whose end already fits correlate at **+0.86** and the 525 whose end overshoots score **−0.10** once clamped. That is why `esi32-gm` — the format doc's own reference disc — yields loops on only 5% of its samples.

**No root key ships, because the record does not carry one.** No byte of the 92 tracks the note written in the sample's own name above chance, over 1 741 named records of one disc and 917 of another. The field that looks most like a root key turns out to be the sample rate. Deriving one from the name was considered and rejected: it would be indistinguishable, in the output, from a value the disc actually stated. The WAV carries its loop with the RIFF neutral root key of 60, which the docs say plainly is a placeholder.

**Nothing else moved, and that is asserted rather than claimed.** The disc-backed suite now pins the SHA-256 of every sample payload per disc alongside the counts — a count table cannot see a payload that shifted by a byte while staying the same length. All seven digests are unchanged.

- **AIFF payloads are converted, not copied out as `.aiff`.** An AIFF's samples are big-endian and a WAV's are little-endian, so the bytes within each value are reversed and the values are left alone — a re-ordering, exactly reversible, with no resampling or change of depth. Root key, tuning and the sustain loop come across from the AIFF's `INST` and `MARK` chunks into the WAV's `smpl`. ([docs/formats/aiff.md](docs/formats/aiff.md), [ADR-0024](docs/adr/0024-the-aiff-twin-is-converted-and-deduplicated.md))

AIFF-C is refused rather than guessed at — its payload may be compressed, and compressed data written out as PCM opens, plays as noise and reports nothing wrong. 8-bit is refused too: AIFF stores it signed and WAV unsigned, so carrying it would mean adding 128 to every sample, which is a change to the values and not to their order. Nothing in the collection is either.
Expand Down Expand Up @@ -44,6 +54,8 @@ Notable changes to `samplerdisc`. Format-level findings live in [docs/formats/](

### Fixed

- **The E-mu sample record's field offsets were listed wrong, and one field was misnamed.** The eight "undecoded fields" at `+18`, `+24`, `+28` … were a four-byte stride begun in the wrong place, straddling two real fields at every step. The real block sits at `+22`, `+26`, `+30` … `+50`. `OFF_SAMPLE_HEADER_LEN` at `+22` was never a header length: it is the sample's start pointer, which reads 92 because the header is 92 bytes — and that is why it reads **0** on 547 of `eiv-studio`'s records, something [docs/formats/emu3.md](docs/formats/emu3.md) recorded as an oddity and can now explain. It also explains the `+34` "bias of two": the pointer addresses the last word rather than one past it.

- **An AKAI volume that lists nothing now says why, in the disc's own words.** Ten volumes across three discs listed empty with no explanation, which is exactly the [ADR-0012](docs/adr/0012-a-probe-must-confirm-a-file.md) signature — it reads as an empty volume rather than as a wrong answer. Each now carries a note naming the block and what the partition's allocation map says is in it: file data on `Advance Orchestra` ×4 and the OMI disc, a free block on `Kickin' Lunatic Beats 2 CD1`, and — for four more on that disc — a block the disc says *is* a volume directory and the image has none at. ([#16](https://github.com/bmxcode/samplerdisc/issues/16), [#17](https://github.com/bmxcode/samplerdisc/issues/17), [ADR-0022](docs/adr/0022-a-volume-is-explained-by-the-allocation-map.md))

**No volume or file count moves anywhere** — 872 volumes and 56 662 files across the collection, before and after, unchanged to the number. That is the point rather than a happy accident: the map explains an emptiness and never gates a listing, because the one-line fixes that *do* gate cost real audio. Rejecting volumes whose type byte is 0 discards four volumes carrying 63 files, and trusting the map as an allocation flag discards those and every volume on every S3000 and CD3000 disc besides.
Expand Down Expand Up @@ -72,6 +84,8 @@ Notable changes to `samplerdisc`. Format-level findings live in [docs/formats/](

### Known limits

- **E-mu stereo samples are written as double-length mono.** Roughly **2 700 of the 14 738** E-mu samples declare two channels in their record, stored as a block of left followed by a block of right. Reading the payload as one mono stream concatenates them. The earlier finding that "everything is mono" tested *interleaved* stereo — a sound refutation of the wrong hypothesis, since de-interleaving cannot detect a block split. Measured directly, the two halves of a two-channel record are the same performance, correlating by RMS envelope at 0.99, 0.96 and 0.95 on three discs against 0.13–0.26 for one-channel records. Not fixed here: correcting it moves audio, and this release was scoped to add metadata without touching a byte of payload. ([docs/formats/emu3.md](docs/formats/emu3.md), [ADR-0025](docs/adr/0025-the-loop-is-decoded-the-root-key-is-not.md))

- **The ISO 9660 directory hierarchy is not preserved.** A disc's audio is written flat into one directory per volume, so `PS-34 AIFF …/056_Ballad de Boo/34a-bas-56Dmin.aif` becomes `34a-bas-56Dmin.wav` and the folder that grouped it by tempo is gone. Nothing is lost on these discs — Best Service named every file uniquely, and all thirteen list zero collisions after flattening — but a disc that reused a basename would rely on `unique_path` suffixing it.

- **AIFF-C is refused, and no disc exercises a reader for it.** Nothing in the collection is AIFF-C, so there is nothing to check one against; a compressed payload written out as PCM would open, play as noise, and report nothing wrong. Same for 8-bit AIFF, where the sign convention differs from WAV's and carrying it would change the sample values.
Expand Down
5 changes: 4 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,17 @@ All of that vanishes into a working parser. Six months on, the code says *what*
| D14 | E-mu Emulator IV bank extraction ([ADR-0020](adr/0020-read-e-iv-through-its-sample-directory.md)) | done |
| D15 | Every partition of an AKAI disc, from the table it declares ([ADR-0023](adr/0023-partitions-come-from-the-table-the-disc-declares.md)) | done |
| D16 | AIFF payloads converted, deduplicated against their WAV twin, and EXS24/HALion instruments kept ([ADR-0024](adr/0024-the-aiff-twin-is-converted-and-deduplicated.md)) | done |
| D17 | E-mu loop points in the WAV `smpl` chunk ([ADR-0025](adr/0025-the-loop-is-decoded-the-root-key-is-not.md)) | done |

Across the local collection, by listing: 71 of 79 images claimed, 2 578 volumes, 110 989 files, 77 620 of them samples. The AKAI discs are 44 of those images and 68 997 of those files, read across 275 partitions — before D15 they were 14 670 files, because only the partition at the origin was read.

## What is not done

- **Roland S-550.** `Roland LCD1.iso`/`.nrg` opens `* ROLAND S-550 *` and is a different format from the S-7xx entirely ([ADR-0014](adr/0014-one-backend-per-on-disc-format.md)). Neither archive holds a second specimen, so it stays deferred rather than being reverse-engineered from one disc.
- **Ensoniq and Kurzweil backends.** The archives are full of these discs and the containers already open them; each needs a module in `fs/` and nothing else ([ADR-0003](adr/0003-brand-neutral-pluggable-backends.md)).
- **Loop points and root key for E-mu.** The 92-byte sample header has eight undecoded fields (`+18`, `+24`, `+28`, `+32`, `+36`, `+40`, `+44`, `+48`); some are very likely loop points and root key. [ADR-0011](adr/0011-the-deliverable-is-daw-ready-wav.md) wants them in the WAV `smpl` chunk and the E-mu path writes none. Deferred rather than done because it changes the *shared* record parser and would alter every E-mu sample already extracted.
- **E-mu stereo samples come out as double-length mono.** The sample record's pointer block declares a channel count, and roughly **2 700 of the 14 738** E-mu samples declare two — stored as a block of left followed by a block of right, not interleaved. Reading the payload as one mono stream concatenates the channels. D17 established this and deliberately did not fix it: correcting it moves audio, and that deliverable was scoped to add metadata without touching a byte of payload. It is the largest known defect in the E-mu path ([formats/emu3.md](formats/emu3.md), [ADR-0025](adr/0025-the-loop-is-decoded-the-root-key-is-not.md)).
- **`esi32-gm` and `protozoa` declare a longer extent than their record length gives.** On about 2 200 records of one and 3 800 of the other, `end_L` runs some 45 frames past the payload `+34` produces. Either the reader is 90 bytes short on those samples or the extent field means something else; the splice test does not settle it — a scan for the true loop end peaks within ±2 frames of the declared one on 10% and 20% of records, against about 3% for chance. Those records are refused a loop rather than given a clamped one, and nothing is changed on the strength of an unsettled measurement.
- **No root key for E-mu.** It is not in the sample record: no byte of the 92 tracks the note in the sample's own name above chance, over 1 741 named records of `esi32-gm` and 917 of `eiiix-1`. The E3 keeps it in the preset, and presets are not read — see the `E4P1` entry below. E-mu WAVs carry their loop with the RIFF neutral root key of 60 ([ADR-0025](adr/0025-the-loop-is-decoded-the-root-key-is-not.md)).
- **`E4P1` presets are not read.** The three E-IV discs carry 916, 901 and 284 of them. On `eiv-studio` 100 of 230 banks have no sample directory and are listed with a note; preset-only banks are the likely explanation, and it is not established.
- **The `.mds` track table is unread.** One real pair now reads end to end, but geometry is sniffed from the `.mdf` rather than taken from the descriptor, so a multi-track or offset image would be read from byte 0. What the one specimen's descriptor holds is written down in [formats/mdx.md](formats/mdx.md) without being relied on.
- **CUES chunks in NRG.** Only `CUEX` is parsed; `CUES` encodes position as MSF and no disc using it was available to check the layout against.
Expand Down
2 changes: 2 additions & 0 deletions docs/adr/0020-read-e-iv-through-its-sample-directory.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ Three things follow from that, and each is the same rule applied at a different

**Treat the paired length fields as a channel count.** `+34 == 2 × (+30) − 90` on both EIII and E-IV looks exactly like a mono/stereo flag, and building a stereo path on it was planned. Rejected on measurement: de-interleaving a payload as stereo roughly doubles its sample-to-sample delta, which is what decimating a smooth mono signal does, and the known-good `esi32-gm` `Piano E0` scores the same as every E-IV record. Everything is mono. E-IV pairs samples into stereo the way the rest of the collection does, by name ([ADR-0017](0017-the-stereo-side-marker-is-a-character-class.md)).

> **This rejection is overturned by [ADR-0025](0025-the-loop-is-decoded-the-root-key-is-not.md); the rest of this record stands.** The measurement above is sound about *interleaved* stereo and tested the wrong hypothesis: the format splits into blocks — all of the left channel, then all of the right — which de-interleaving cannot detect. The two halves of a record whose pointers declare two channels are the same performance, correlating at 0.99, 0.96 and 0.95 by RMS envelope on three discs against 0.13–0.26 for one-channel records. The paired fields *are* a channel count. Nothing else here depends on it: bank binding, the chain and the directory's length are untouched.

## Consequences

**Good.** Three discs that could only be listed now extract: 449, 2 822 and 828 samples. The four EIII/ESI counts are unchanged, which is the check that the shared record parser was not disturbed.
Expand Down
Loading
Loading