EMU3: decode the record's channel count and write stereo as stereo (#32) - #34
Merged
Conversation
The sample record's pointer block declares two channels on 2 721 records across the seven reference discs, storing the payload as a block split -- all of the left channel, then all of the right. Read as one mono stream that is a file twice as long as the sound. 2 656 of them now come out as one interleaved stereo WAV each. The other 65 declare the split and then close end_L somewhere else. They are not stereo -- their halves score at the negative control on fine structure and best lag, and on protozoa the second half is another bank's record -- so the gate requires end_L + 2 == start_R and they stay mono. Sample counts, payload digests and all seven loop counts are unchanged, and the disc-backed suite now pins the stereo count per disc and checks that de-interleaving reproduces the disc's two blocks byte for byte. Closes #32 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ecord, not the second The measurement is sharper than the claim it replaces. On six of the 19, the *first* half is byte for byte a complete one-channel record of the same name in another bank and nothing matches the second half -- so the payload is twice the sound and start_R lands on the halfway point by arithmetic rather than by declaration, which is exactly what end_L contradicts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
The
EMU3sample record's pointer block declares a channel count, and where it declares two the payload is a block split — all of the left channel, then all of the right. Read as one mono stream that is a file twice as long as the sound, with the right channel playing after the left rather than alongside it. 2 656 of the 14 738 E-mu samples on the reference shelf were coming out that way, and they now come out as one interleaved stereo WAV each.ADR-0025 found the channel count in D17 and deliberately did not act on it, because acting on it moves audio and that deliverable was scoped to add metadata without touching a byte of payload. This is that deliverable. Closes #32.
esi32-gmeiiix-1eiiix-2protozoaeiv-analogiaeiv-studioeiv-vitousMiroslav Vitous String Ensemblesis the one to look at: 828 of 828, an orchestral string library that was entirely double-length mono.A channel count is not enough on its own
2 721 records declare
start_R == start_L + P/2, and 65 of them are not stereo. They declare the split and then closeend_Lsomewhere else — 19 onprotozoa, 40 oneiiix-1, 6 oneiiix-2. So the gate has a third condition, that the left block close exactly where the right one opens:The 65 rejects are not a judgement call, and six of
protozoa's can be identified exactly.Trom B2,Trom E3andTrom A3are each written in two banks, and in all six the first half is byte for byte the whole of a one-channel record of the same name inVintage PresetsX— 16 756 bytes ofTrom B2against a 33 512-byte payload — while nothing on the disc matches the second half. Those payloads are twice their sound, which is the only reasonstart_Rlands onstart_L + P/2at all: arithmetic, not declaration.end_Lsays so, closing 8 bytes past the halfway point rather than on it. Without the third condition they ship with an unaccounted-for second sound in the right channel, and nothing reports a problem.The third condition also keeps D17 whole. The only two records anywhere whose declared loop end lies past its own channel —
Mbira A3andMbira F3oneiiix-1— are both rejects. They stay mono and keep their loops, so all seven loop counts survive by construction rather than by luck.The obvious measurement is confounded, and that is the interesting part
The evidence in #32 was the RMS-envelope correlation between the two halves. Re-verifying it on the set this gate selects turned up the confound: a single decaying note's two halves both decay, and correlate at 0.94 without being two channels of anything. Every disc has a tail of those —
Piano Db3,Glockenspiel D5,Snare 2. An envelope threshold set anywhere useful takes in hundreds of them.So two sharper instruments, with a control on each side. Fine structure is the 64-frame RMS envelope divided by its own 1024-frame trend, so what is correlated is transients rather than the shape of the decay. Best lag is the peak normalised waveform cross-correlation over ±64 samples. The positive control is the twelve name-paired
-L/-Rrecords oneiv-analogia(ADR-0017) — known-true stereo established by a mechanism the pointer block knows nothing about. The negative control is halves taken from two different records.esi32-gmeiiix-1eiiix-2protozoaeiv-analogiaeiv-studioeiv-vitousend_Lpaststart_Rend_Lshort of the splitThe selected set scores with the positive control on all seven discs; the rejects score with two unrelated records.
protozoa's weak 0.55 in the #32 table was those false positives, 19 of its 27.Channel order is structural, and asserted rather than assumed
The first block is the left channel: the pointer block is ordered
(start_L, start_R)andstart_Laddresses the first block. That is the whole of the argument, and it is the kind of thing a swap would leave inaudible in isolation and wrong forever, sotests/test_emu3.pystates it as a named claim rather than leaving it implicit in a slice index.The only content evidence available is weak and agrees. Of
eiv-analogia's twelve name-paired records, all six ending-Ldeclare their single channel in the left-hand pointer set and three of the six ending-Rdeclare theirs in the right-hand set — nine of twelve consistent, none contradicting, p ≈ 0.09. Recorded for exactly what it is worth.The inverse error was looked for and is not there
A record that is stereo and declares one channel would leave a structural signature: an extent covering half its payload. Not one of the 12 017 records that do not declare the two-channel shape has it. The 439 whose halves correlate above 0.9 by envelope show a midpoint z-jump of −0.27 to −0.41 — there is no discontinuity where a block join would be — and they are the decaying single notes above.
eiiix-2needed checking, because the format doc gave it the weakest separation in the table at 0.59. Under these instruments its high-envelope one-channel records score fine structure −0.021, the negative control, and its one-channel envelope median re-measures at 0.114 over 603 scored records. The 0.59 is not reproduced here; both figures are recorded and neither is relied on.What did not move, and how that is known
read_fileis untouched and the offset arithmetic is untouched.(pointer − start) / 2is a per-channel frame index either way, so a loop that moved would be arithmetic that drifted. A stereo sample's loop is now bounded by its channel, which is a tighter check than before.The per-disc stereo counts are pinned in
tests/test_discs.pyas tightly as the sample counts, because the gate's third condition is exactly the kind of thing a later simplification removes.What this deliberately does not do
It does not write the mono halves alongside, the way ADR-0007 does for
-L/-Rjoins. That rule exists because name pairing is a heuristic and the halves are how a user notices a bad guess. Neither half transfers: the disc states the channel count and two further fields of the same record confirm it, so there is nothing to hedge — and the "original" would be one leg of a concatenation, not a sound anyone recorded.It does not file the result under
<volume>/stereo/. That directory means rebuilt from two files whose names looked like a pair. A natively-stereo record was never two files, and putting it there would tell a user the pairing had been guessed at when it was read.It does not decide stereo from the audio. Content beats declared text in this project — a filename, a name field — and here the declaration is structure: three fields of one record agreeing with the payload's own length. Measurement's job was to check the gate, not to be it.
Both mechanisms remain, and
eiv-analogiaexercises both at once:samplerdisc extracton it reports 449 files, 279 of them stereo samples, and 6 joined stereo pairs. They are counted apart in the CLI and in the batch manifest, the way duplicates are counted apart from damage — one is a channel count the disc declared, the other a pairing this tool inferred from two filenames.Known limits after this
65 records declare two channels and are not stereo, and only
protozoaaccounts for what they hold. There the second half is another bank's record at the constant shift ADR-0021 describes. Oneiiix-1's 40 andeiiix-2's 6 the halves are measurably not one performance and nothing says where the second one came from. Mono is the safe answer, not an explained one.protozoafalls from 27 stereo samples to 8, and 8 is too few to establish anything alone. Its stereo rests on the rule the other six discs establish, aseiv-analogia's loops rest on the other six in ADR-0025.Four records have byte-identical halves (two on
eiv-analogia, two oneiv-studio) and are written as stereo. Dual mono is a real thing a sampler can hold, and second-guessing it would mean deciding channel counts by comparing audio.A generation writing a third record shape — one where
end_Lmeans something else again — would be refused silently and come out double-length mono, as quiet a failure as the one this fixes. The pinned stereo counts are the tripwire.Also in here
The format doc's claim that E-IV discs pair samples into stereo by name is corrected. That is true of 12 samples across all seven discs — six pairs, all on
eiv-analogia— against 2 656 whose record declares two channels, with zero overlap. Both mechanisms are real; the doc gave the rare one as the answer.The record-shape table is also corrected. Its "neither" column folded in the 550 records that declare a single channel in the right-hand set — 542 on
eiv-studio, 8 oneiv-analogia— which are ordinary one-channel records the loop decoder already reads correctly. That is why the old table said 620 and 24 where the finer breakdown says 78 and 16.Two stale
CHANGELOG"Known limits" bullets go with it: "Loop points and root key are still absent from E-mu WAVs", which D17 contradicted in the same section, and "The E-mu sample record has no channel count", which ADR-0025 overturned and this settles.Verification
Spot-checked on the discs themselves: a
eiv-vitousbank writes 21 of 21 samples as two-channel WAVs at the true duration with nostereo/directory created, andeiiix-1'sMbira A3— one of the 65 — still writes mono at 237 136 frames with its loop at (2, 121 476) intact.🤖 Generated with Claude Code