Skip to content

D19: the S3000 header is 192 bytes, and an AKAI payload must be the file its entry placed - #36

Merged
bmxcode merged 1 commit into
mainfrom
d19-akai-payload-check
Aug 22, 2026
Merged

D19: the S3000 header is 192 bytes, and an AKAI payload must be the file its entry placed#36
bmxcode merged 1 commit into
mainfrom
d19-akai-payload-check

Conversation

@bmxcode

@bmxcode bmxcode commented Aug 22, 2026

Copy link
Copy Markdown
Owner

Closes #23. Opens #35.

What #23 asked for, and why it is not what this delivers

#23 says an AKAI sample payload whose header disagrees with its directory entry is extracted silently, as a WAV that opens, plays, and is somebody else's audio. It names nine files on AMG - Kickin' Lunatic Beats 2 AKAI CD1, proposes four tests, and asks for a sweep across the collection before deciding what a failure should do.

The sweep says it does not reproduce. Across all 44 AKAI discs and 56 490 sample entries, 96 payloads disagree with their entry and all 96 were already being refused, the nine named files included. Nothing was extracted silently and nothing ever had been: _looks_like_header has tested the id, the valid byte and the name's decodability since D3, and parse has tested the rate. Three and a half of the four proposed tests were already there.

The 96 are also, exactly, the 96 skips the README already reported — 92 "do not begin with an AKAI sample header" plus four "implausible sample rates". Not a near-miss: the same files. The counts were suspiciously close because they were the same count.

What the issue did have was the false-positive case it told us to rule out first — the S3000 192-byte header variant exists, and a check keyed to 150 that fires on every S3000 disc is what to rule out first. Ruling it out is what found the defect underneath, and that is the headline.

The headline: 13 451 samples were read 42 bytes early

The S3000 family writes a 192-byte header where the S1000 family writes 150, and every sample was read at 150.

That does not fail. The frame count comes out right, the WAV opens, the length is within 0.1 %, and the payload-versus-output check the README ran compared the output against the same wrong offset it was written from. What shipped was a WAV beginning with 42 bytes of header read as PCM — a burst of roughly ±20 000 lasting 0.24 ms, an audible click in place of the attack — missing the last 21 frames of the sound, with every loop point 21 frames out of alignment.

13 451 of the 56 490 AKAI samples, on nine discs: AKAI.S3000.Sound.Library.17 (4 455, 3 086, 1 990, 1 010, 601, 168, 218), East Connexion Piano (730) and AMG - Now CD-Rom for (AKAI) (1 193). Anyone who has extracted those discs should do it again.

Three structures agree on it and none knows about the others:

  • The directory. Every one of the 13 451 is a file whose type byte has the high bit set — the S3000-family flag that already named a kept original .s3s rather than .s1s. The split is perfect: 13 451 high-bit files at 192, 42 989 low-bit files at 150, no disc mixing the two rules, no exception.
  • The payload. The directory's declared size is words × 2 + header_len on 56 430 of 56 430 payloads readable at all. The 60 that fail that identity are the damaged ones, and every one of them fails an identity test too.
  • The bytes. On Library.2's NPF E0, offsets 150–170 are zero and 171–191 are 0a ff ff 22 a8 00 aa ff ff …, the same shape on every sample of the disc, which audio is not. Waveform starts at 192.

HEADER_LEN_S3000 = 192 was declared in sample/akai.py and read by nothing. The format doc said S3000 discs may use a 192-byte variant and to branch on the id and valid bytes — wrong twice: the variant is not conditional, and 0x80 appears on 42 989 samples at 150 and 13 410 at 192.

31 healthy samples were being thrown away for a bit

Of the 96 refusals, 31 fail on the valid byte alone: 0x81 on 29 samples of Library.2, 0x9c on two of Library.1. Correct id, name matching the directory exactly, a normal 44 100 or 22 050, and a word count the declared size agrees with at 192. 0x80 is a flag inside a byte and was being tested as the whole byte — 29 consecutive 1015 E.PF, 1051 VL+PIZ and 1054CHO HARP entries that are plainly a library's own multisamples.

What moved

Before After
Samples, collection 89 125 89 156
Samples, AKAI 56 394 56 425
AKAI stereo joins 14 449 14 461
WAVs written 105 082 105 125
AKAI entries not written 97 66 — 61 mismatch, 5 damage

The stereo joins move because 31 more samples means twelve more -L/-R pairs with both halves present. E-mu (14 738), ISO 9660 (11 601) and Roland (6 392) do not move by one, and neither does anything in the directory walk: _AKAI and _AKAI_FIRST_PARTITION in tests/test_discs.py — volumes, files, noted volumes, declared and present partitions — are untouched on all nine pinned discs, which is the control on this being a payload change and not a filesystem one.

Every S3000 disc's audio changes. That is the point and it is the risk.

The four tests, and which of them earn their place

Over the 65 refusals that remain once the flag is read as a flag:

Test Fires Fires alone
id != 3 61 1
valid, no 0x80 bit 60 0
name != the entry's 60 0
rate outside 4000–50000 58 4

The name comparison — the one thing #23 was actually about — detects nothing the other three miss. Every payload whose name disagrees also has a wrong id and a cleared valid flag, because on these images the displacement lands mid-audio and mid-audio does not look like a header.

It ships anyway, and the argument is not a count. The other three ask whether the payload is a sample; only this one asks whether it is this sample, which is the failure class #23 named and the one #25 will raise. It costs one string comparison. What this PR does not claim is that it has been shown to work on a disc: it is exercised synthetically alone, against a fixture where ALPHA's entry points at a complete valid header for BETA, and the test docstring, the format doc and docs/README.md's "What is not done" all say so.

The failures cluster, which is what says the check is right

60 of 65 are a run to the end of one volume. The other 34 AKAI discs have none at all, Advance Orchestra's 2 236 samples included.

Disc Mismatches Where Partitions declared / present
Best Service - Alpha Dance II 21 AC.DRUMLOOPS, last 21 of 22 6 / 6
Best Service - Alpha Dance I 15 ATTACK BANK2, last 15 of 18 5 / 4
Kickin' Lunatic Beats 2 CD1 9 13-TRACK 06, last 9 of 20 11 / 1
AKAI.S3000.Sound.Library.5 7 SURDO, last 7 of 13 9 / 3
AKAI.S3000.Sound.Library.1 4 3084 B.BEAT6 last 3 of 8; one rate 13 / 13
AMG - Global Trance Mission 2 3 AMBIENT PAD2, last 3 of 6 9 / 4
AKAI.S3000.Sound.Library.2 3 three isolated rate bytes — 0, 519, 519 13 / 13
AKAI.S3000.Sound.Library.3 1 VOLUME 001, its only file 13 / 13
Audio Factory - Classical Wild Takes 1 VOLUME 002, last of 2 11 / 6
AMG - Loop Soup 1 SOUP 101-103 entry 27 — the format doc's known one 9 / 9

The falsifying case the sweep was meant to find became a finding instead. Alpha Dance II declares six partitions and holds all six and still loses 21 of one volume's 22 samples; Library.1 and Library.3 are the same shape. That is a run of blocks lost inside a partition, so no header goes missing and the table's declared-against-present arithmetic sees nothing. 25 files on three .mdx images — #35, and the reason declared == present must not start being read as a clean bill of health.

The five that do not cluster are single files: four with a corrupt rate byte and an otherwise perfect header (EG 2MUTE at 0 Hz, M.VOICE A1 and SYN 1 at 519, HOUSE BASS at 1280) and Loop Soup's one directory record landing mid-sample. Those four are the files their entries placed, with one field unusable, so they are counted as damage rather than as mismatches.

What a refusal does now

Skip-and-log, the house style, as a Skipped carrying a mismatch flag counted apart in the summary and the manifest — ADR-0024's precedent one step on. A third result shape was rejected: a mismatch is a subset of not-written, and every consumer would grow a branch to say what one boolean says.

The reason names every field that disagrees rather than the first, because what they disagree about together is the diagnosis:

payload header carries id 224 not 3, a name that does not decode in the AKAI
charset, placed by an entry named 'PADY CHORD06'

against the old payload does not start with an AKAI sample header, which was true of a payload that is mid-audio and of one that is a perfectly good sample under the wrong name alike. That is the honest lesson of #23: the refusal existed the whole time and told nobody which of four things was wrong, or that a directory entry was involved at all — so nobody checked whether it existed.

Testing

The suite had no AKAI payload check, which is how a 42-byte slip survived four deliverables in a green run. The E-mu and Roland paths have asserted their audio against the disc for two deliverables each.

  • Over every AKAI disc in the collection: every accepted payload's PCM is the disc's own bytes from the chosen offset, and entry.size == words × 2 + header_len — 56 425 of 56 425. Plus the general invariant A sample payload whose header disagrees with its directory entry is extracted silently #23 asked for: no AKAI sample is written whose payload header names a different file.
  • Eight discs pinned by payload — four whole S3000 discs, three carrying mismatches, and Advance Orchestra as the control with 2 236 samples and nothing wrong anywhere.
  • Synthetic: the 192-byte read asserted on bytes rather than frame counts; the 42-byte slip asserted at both the head and the tail; 0x81 and 0x9c accepted; a program (id 1) never handed to the sample parser; the name check exercised where no disc can exercise it.

Whole-collection payload check re-established, not inherited — it was true before against the wrong offset, which is exactly what made it worthless: 70 of 70 discs, 89 156 WAVs, zero whose audio is not on the disc it came from. 275 silent files, 1 047 distinct rates from 6 000 to 49 999, none unreadable, none zero-length — all unchanged.

Roland, E-mu and ISO 9660 are untouched. The declared name and the generation bit reach the parser through AkaiBackend.parse_sample, the route Emu3Backend and RolandS7xxBackend already use, so extract.py learns no AKAI constant (ADR-0003); the only shared-path additions are Skipped.mismatch and a PayloadMismatch in sample/__init__.py that any backend may raise.

Is #25 unblocked?

Yes, with a limit that should be read before starting it.

#25 was deferred because displaced audio extracted as wrong files with nothing reporting it, and ADR-0023 names #23 as the standing evidence for that. That argument no longer holds: a displaced payload is now refused and named, per file and per disc, so recovering a short image's partitions no longer risks silently writing one sample's sound under another's name. The safety case for the deferral is answered.

The limit is the honest half. On all nine of those images the displacement lands mid-PCM and is caught by the id and valid tests, never by the name test. The guard against a displacement landing exactly on another sample's header — which is the case #25 will produce most of, since it will be reading whole partitions of shifted audio rather than one volume's tail — has zero positives on real data and is exercised only against a fixture. It is a comparison that cannot really be wrong, but it has not been shown right on a disc, and #25 should be attempted knowing that rather than treating this PR as having proved it.

#35 is the other thing #25's author should know: a rip can lose a run of blocks inside a partition without losing a header, so the nine images in #25's table are a floor and not the list.

Docs

Verify

uv run ruff check .          # passed
uv run ruff format --check . # 94 files
uv run pytest -q             # passed
SAMPLERDISC_TEST_DISCS=… uv run pytest -q   # passed, 44 AKAI discs
uv tool install --editable . && samplerdisc --version   # 0.3.0

🤖 Generated with Claude Code

… file

Closes #23, whose bug did not reproduce: all 96 payloads disagreeing with
their directory entry were already refused. Ruling out the S3000
false-positive case found the defect underneath -- 13 451 of 56 490 AKAI
samples carry a 192-byte header and were read at 150, putting 42 bytes of
header into the audio and dropping the last 21 frames.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@bmxcode
bmxcode force-pushed the d19-akai-payload-check branch from 0bede50 to b12cec5 Compare August 22, 2026 01:25
@bmxcode
bmxcode merged commit 0ddfec6 into main Aug 22, 2026
1 check passed
@bmxcode
bmxcode deleted the d19-akai-payload-check branch August 22, 2026 03:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A sample payload whose header disagrees with its directory entry is extracted silently

1 participant