Put sound on the wire, and find three LSBs are worth 25 dB
ROADMAP P6, everything in the item except the bus half session 20 closed. tools/encoder/adpcm.py is an MSM6258 codec, tools/encoder/extract_audio.py takes the same seconds of the same stream the frames come from, tools/bench/verify_adpcm.py is the gate, tools/analysis/32_audio_wire.py the container arithmetic. There is no reference encoder -- ffmpeg has a decoder for this format and none the other way -- so what is gated is the decoder the encoder runs INSIDE its own nibble search, sample-exact against ffmpeg's over 4,268 nibbles. An encoder that agrees with its own wrong decoder is what that catches. The Singe window: 156,250 samples -> 78,125 B at 21.97 dB, which is 7,812.5 B/s to the byte. Normalising the disc's -13.4 dBFS level moves the SNR 21.97 -> 21.97, so the level is not a lever. And the two published delta formulas are not the same codec. They differ by at most 3 in 12-bit units; encode for one and decode on the other and the SNR goes 21.97 -> -2.88 dB, the noise louder than the signal, because ADPCM is recursive the way the video codec is temporally recursive. Which one the chip runs is now P6a and it is a precondition on shipping any audio. And audio is the first thing the packed branch's simplification has cost anything for. A record has no index BY DESIGN, so audio cannot be per-record without making records variable; it rides a fixed cadence (F, A), the obvious F=1 wastes 57.3% of every audio sector, and the pick is F=11 A=14 -- 0.09% padding, 14,336 B held, wire 582.0 -> 589.6 KB/s. The codec container, which kept its index, pays zero. The MAME experiment did not work and 65.5 says so: :okim6258 is there at $E92001/$E92003, read out of the machine's own program map, and feeding it from Lua recorded silence across control 0..3 x port C 0..15. The register semantics were not guessed at further. FINDINGS 65. check.sh ALL GREEN before and after, with a new stage. Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
@@ -339,6 +339,34 @@ from taking. It believed it was at 12 fps; the screen was at **6.37**. Only the
|
||||
host's raster count contradicts it, and the gate asserts on the difference
|
||||
(FINDINGS 64.3).
|
||||
|
||||
**And the sound has an encoder, whose most useful output so far is a warning.**
|
||||
The X68000's audio is an OKI MSM6258 — 4 bits a sample, 15,625 of them a second,
|
||||
7,812.5 bytes a second exactly. `tools/encoder/adpcm.py` encodes the same ten
|
||||
seconds the frames come from: **78,125 B at 21.97 dB**. There is no reference
|
||||
encoder to check it against — ffmpeg has a decoder for this format and no encoder
|
||||
— so what is gated is the decoder the encoder runs *inside its own nibble
|
||||
search*, sample-exact against ffmpeg's over 4,268 nibbles. An encoder that agrees
|
||||
with its own wrong decoder is what that catches.
|
||||
|
||||
**And the two published versions of this codec are not the same codec.** ffmpeg
|
||||
computes a nibble's contribution as `((2*(n&7)+1) * step) >> 3`; the OKI
|
||||
datasheet truncates per term. They differ by **at most 3 in 12-bit units**.
|
||||
Encode for one and decode on the other and the signal-to-noise ratio goes from
|
||||
**21.97 dB to −2.88 dB — the noise comes out louder than the signal**, because
|
||||
ADPCM is recursive and a rounding difference does not stay where it happens. So
|
||||
which one the chip runs is not a footnote; it is a precondition on shipping any
|
||||
audio at all, and MAME's x68000 has the chip to ask (FINDINGS 65).
|
||||
|
||||
**And audio is what the packed container's best property finally costs
|
||||
something for.** A packed record is 97 sectors and its address is arithmetic —
|
||||
no index, and none can be needed. Audio is 651.0417 bytes a frame slot, a rate
|
||||
with no arithmetic relationship to 12 fps, so it cannot ride the record without
|
||||
making records variable length and bringing an index back. It rides a fixed
|
||||
cadence instead — every 11 frames, 14 sectors — which wastes **0.09%**, where
|
||||
the obvious one-lump-per-record cadence wastes **57.3%** of every audio sector.
|
||||
The wire goes **582.0 → 589.6 KB/s**. The codec container, which already has the
|
||||
index the packed one deleted, pays **zero**.
|
||||
|
||||
**The scene graph is in, and the worst gap between two decision points is
|
||||
zero.** `tools/import/scenegraph.py` imports the arcade scene graph — 40 scenes,
|
||||
516 sequences, 906 input windows — and 5.4% of the game's 612 branch transitions
|
||||
@@ -371,7 +399,8 @@ cores, the ring and paced-ring passes, the DMAC configuration gate and the
|
||||
load-time transforms on both cores, then imports and gates the scene graph
|
||||
when a DirkSimple checkout is present, then builds the packed container and
|
||||
renders it through px68k's own GVRAM model, then **runs the packed player for
|
||||
120 frames off a real volume and compares every one of them**, then prints
|
||||
120 frames off a real volume and compares every one of them**, then encodes the
|
||||
same window's audio and gates it against ffmpeg's decoder, then prints
|
||||
`ALL GREEN`.
|
||||
|
||||
## Reproducing this
|
||||
|
||||
Reference in New Issue
Block a user