EMU3: decode the loop from the record's pointer block - #31
Merged
Conversation
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. 8 039 of the 14 738 E-mu samples now carry their loop points in the WAV smpl chunk. Established from the audio: the waveform at the loop start correlates with the waveform at the loop end at +0.64 to +0.86 on six of seven discs, against a control of about zero. A loop end past the audio is refused rather than clamped, which is where this format parts company with AKAI and Roland -- clamping turns +0.86 into -0.10 on protozoa's own records. No root key ships: the record does not carry one, measured against the notes in the sample names over 2 658 records. Additive by construction, and asserted -- the disc-backed suite now pins the SHA-256 of every sample payload per disc, and all seven are unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Every other backend carries what its disc knows about a sample into the WAV's own
smplchunk — AKAI since D7, Roland since D13, AIFF since D16. The E-mu path carried none, so 14 738 samples across seven discs shipped as plain WAV and their loop points were lost the moment the disc was. ADR-0011 calls dropping that data loss, not neutrality.8 039 of the 14 738 now carry their loop points.
esi32-gmeiiix-1eiiix-2protozoaeiv-analogiaeiv-studioeiv-vitousThe eight fields were never eight fields
docs/README.mdlisted the record's undecoded middle as+18,+24,+28,+32,+36,+40,+44,+48. That is a four-byte stride begun in the wrong place: au32read at+28straddles two real fields, which is why those columns dump as nine-digit noise and why nothing was ever made of them.The record carries an eight-pointer block at
+22,+26,+30,+34,+38,+42,+46,+50— a start, an end, a loop start and a loop end, per channel, each a byte offset from the record's own start naming the first byte of a 16-bit word.The strongest argument that this reading is right is how much of the existing doc it explains for free:
OFF_SAMPLE_HEADER_LENwas never a header length. It isstart_L, reading 92 because the header is 92 bytes and the audio begins immediately after it — which is also why it works as the record signature.docs/formats/emu3.mdrecorded that this field "reads 92 on most E-IV records and 0 on 547 ofeiv-studio's — those carry 92 at+26instead" and left it as an oddity. Those records declare no left channel. Not a broken field: a different value of a working one.RECORD_LEN_BIAS = 2stops being a bias.+34isend_R, which addresses the last word rather than one past it.+34 == 2 × (+30) − 90, reported in the "Everything is mono" section without an explanation, isend_R = end_L + P/2.How the loop was established
The oracle is the one formats/roland-s7xx.md used for the S-7xx sustain loop, guards included — a minimum loop length and a minimum amplitude at both ends, because that record says in as many words that a metric that rewards silence will find plenty of it. Two tests on different evidence. The join is
|x[E−1] − x[L]|over the mean step measured in a window at each end; the shape test correlates the waveform atLagainst the waveform atE, and is the stronger instrument here.The control is the same loop end with the start put somewhere else, which is the only thing that isolates the field in question.
eiiix-1eiiix-2protozoaesi32-gmeiv-studioeiv-vitouseiv-analogiaSix of seven discs, both E-mu generations, three publishers. ADR-0020's independence requirement is met and then some.
What the end field is not.
+46and+30sit six frames apart on most records, so no test separates them. The start is what is established, along with the fact that the pair splices.A loop end past the audio is refused, not clamped
This is the finding that made the measurement work, and the one place this format parts company with the rest of the project. AKAI and Roland both clamp a declared end back to the audio actually present, because these rips run a little short of their directories. Doing that here destroys the loop, and
protozoashows it on a single disc within a single record shape:protozoa, one-channel recordsSame disc, same shape, separated only by whether the end fits. A clamped end is a loop point the disc did not state.
That is most of why
esi32-gm— the format doc's own reference disc, whose8M GeneralMidi Xis its worked example — yields loops on 5% of its samples. It declares an extent about 45 frames past the payload on nearly every record.What this deliberately does not claim
There is no root key, and none is invented. No byte of the 92 tracks the note written in the sample's own name: over 1 741 named records on
esi32-gmthe best byte matches at any constant offset on 8%, and 917 oneiiix-1on 6% — chance, on constant-zero bytes.+58is the field that looks most like it and turns out to be the sample rate (64 096 ↔ 12 000, 64 184 ↔ 13 000, 64 388 ↔ 15 625). The E3 keeps root key in its preset and presets are not read.Deriving one from the sample name —
Piano E0→ 28 — would have covered 1 741 records of one disc and is rejected, as the most important rejection in ADR-0025. A name is a label someone typed; the output would be indistinguishable from a value the disc actually stated, which is the failure ADR-0012 exists to prevent. The WAV carries its loop withMIDIUnityNote60, the RIFF neutral value, and every document says plainly that 60 is a placeholder.eiv-analogiadoes not confirm on its own evidence, and is reported that way. 441 of its 449 records pass every structural gate but only 34 carry audio loud enough at both ends to score, and those 34 show nothing. That is a lack of power rather than a refutation; its loops rest on the rule the other six discs establish. It is stated rather than smoothed over.Which of
esi32-gm's two lengths is right is open. Either the reader is 90 bytes short on ~2 200 records or the extent field means something else. Scanning candidate ends across ±96 frames and taking the shape peak does not settle it: within ±2 frames of the declared end on 10% ofesi32-gm's records and 20% ofprotozoa's, against ~3% for chance. Better than chance, nowhere near an answer, so nothing is changed on it.This overturns a rejected alternative in ADR-0020
ADR-0020 rejected "treat the paired length fields as a channel count" on a measurement, and that measurement tested the wrong hypothesis. It de-interleaved payloads as
LRLRand found the roughness roughly doubled — a sound refutation of interleaved stereo. The pointer block says the layout is a block split, all left then all right, which de-interleaving cannot detect: read as mono it is one continuous waveform with a single join in the middle.Measured directly, on records whose own pointers declare two channels, the halves are the same performance — median RMS-envelope correlation:
esi32-gmeiiix-1eiiix-2protozoaanalogiastudiovitousSo roughly 2 700 of the 14 738 E-mu samples are stereo and are currently written as double-length mono. That is the largest known defect in the E-mu path and it is not fixed here: correcting it moves audio, and this deliverable was scoped to add metadata without touching a byte of payload. ADR-0020 is annotated rather than edited,
docs/README.mdlists it under what is not done, and it has an issue.The loop points survive that fix unchanged:
(pointer − start) / 2is a per-channel frame index either way.Additive, and asserted rather than claimed
Nothing here touches
read_fileor the offset arithmetic. Saying so is not enough — a table of sample counts cannot see a payload that shifted by a byte while staying the same length — sotests/test_discs.pynow pins the SHA-256 of every sample payload per disc beside the counts. All seven digests are identical to the release before this branch, verified by running the same walk onmain.The per-disc loop counts are pinned as tightly as the sample counts, for the reason the AKAI table pins its noted-volume counts: a loop appearing where none was measured is a gate come loose, and one disappearing is the decode silently failing on a disc nobody looked at.
Verification
uv run ruff check .·uv run ruff format --check .·uv run pytest -q— clean.SAMPLERDISC_TEST_DISCS=~/repo/projects/sample-images uv run pytest -q— clean across the whole shelf, not only the E-mu discs.uv tool install --editable . && samplerdisc --version— 0.3.0.eiiix-1'sFull Arco Stringgives 14 WAVs whosedatachunks are byte-identical to the disc and all 14 carry ansmplchunk — e.g.Arco Violin F#2, loop (23 455, 63 893) in 127 798 frames.🤖 Generated with Claude Code