Measure the level off the whole disc, and find the headroom is not worth buying
FINDINGS 69, ROADMAP P6 -- the item 66.3 reopened in session 34 and sessions 35 and 36 both deferred. The chip clamps its accumulator at 10 bits INSIDE the recursion, and the ten seconds every audio figure in this tree is quoted on peak at 435 of 511: it fits, and it fits by accident, because that window is a -13.4 dBFS passage. Nothing knew what the loudest passage of the game was. tools/analysis/35_audio_level.py reads every stream of the unique scene footage (00000-00201) through extract_audio.py's own chain -- 1,291.6 s, 201 of 202 streams -- and encodes windows of it with adpcm.CHIP. The disc peaks at 946 of 2048 = -6.71 dBFS (00200 @ 2.11 s), which is 5.35 dB over the clamp, and the census behind that peak is 687 samples of 20,182,000 (0.0034%) in 402 events, 44.0 ms, longest 0.90 ms. THE HEADLINE IS A NEGATIVE: THE LEVEL DOES NOT CHANGE. Forty 2 s windows drawn over the game's timeline at six gains -- the disc's own level (gain 1.0) has the best mean SNR (22.03 dB) and the best median, and loses the worst-window column to -3 dB by 0.04 dB. The gain that guarantees zero clamping disc-wide (0.5402) costs 0.85 dB of mean SNR across the whole game to buy back 1.90 dB on the 2.11 s that clamp, because the OKI step table's floor is a constant 16 and does not scale with the signal. AND 66.3's MECHANISM DOES NOT SURVIVE A CONTROL. Error after a clamp run is elevated ~5x -- and so is the same window at a gain that never clamps, read at the same indices, because those samples are simply loud. Worst ratio 1.28 over 64 offsets, and the clamped encode's whole-window mean |error| is the LOWER of the two (4.71 vs 5.05). adpcm.encode runs the chip's clamp inside its own sixteen-way search, so it never loses the chip's state. The worry was right about the mechanism and aimed one layer too late: an encoder clamping at 12 bits while the chip clamps at 10 is exactly that divergence, and 66 closed it. pack.py gains --audio-gain (default 1.0) so the level is a named parameter with a measurement behind it instead of a shift buried in a list comprehension, and prints the encoded window's peak against the clamp. tmp/packed_singe.dlxp rebuilds byte-identical, all 6,039,040 B. New check.sh stage, ~18 s. Three rig facts in 69.4, because a shipping encoder meets all three: 00176 has no audio track at all; 00199 is 61.31 s of video with 1.25 s of audio; and 18 stream pairs share duration, peak and RMS, 7 of them byte-identical. The 10-bit clamp is a DRIVER SETTING, not a chip constant -- x68k.cpp:1089 sets OUTPUT_10BITS -- so it is MAME's reading of the board, and hardware item 5 is what settles it. Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
@@ -377,8 +377,9 @@ from what a chip does with a byte written to its data register, with a different
|
||||
answer. The 10-bit clamp costs nothing on this window and only because the
|
||||
window peaks at **435 of 511**: it is a −13.4 dBFS passage with 1.4 dB of
|
||||
headroom, where the encoder had been clamping 12.1 dB higher. So the audio
|
||||
**level** is an open choice again, downward, and the loudest passage on the disc
|
||||
is unmeasured (FINDINGS 66).
|
||||
**level** became an open choice again, downward, with the loudest passage on the
|
||||
disc unmeasured (FINDINGS 66) — session 37 measured it, and the answer was to
|
||||
leave the level alone.
|
||||
|
||||
**Name the layer**: that is MAME's device model, measured end to end through the
|
||||
machine's real transport. It settles the rig — an emulated audio test encoded
|
||||
@@ -426,6 +427,48 @@ gap — and asserts what a cadence-blind player would read: exactly records
|
||||
off-by-one like that survives a rig that checks frame 0. The wire is **582.0 +
|
||||
7.64 = 589.6 KB/s**, which is 65.3's prediction to the tenth (FINDINGS 67).
|
||||
|
||||
**And the container has been heard — held, the bus costs the audio 463 times
|
||||
the seam.** All **78,125 B** of a DLXP2's audio reached the MSM6258 in order,
|
||||
sample-exact against the four axes in the container's own header, out of a
|
||||
player fetching records off the same disc at the same time: two DMA channels at
|
||||
once, and the interaction is not in the bytes but in the timing. The chip has
|
||||
**no starvation state** — it goes on decoding nibbles out of whatever byte its
|
||||
data register still holds — so the interval between a channel counting out and
|
||||
the CPU arming the next lump is a **held nibble pair driving the predictor**.
|
||||
Stealing, that seam is **0.51 ms over ten seconds**, because `dma.i`'s hook
|
||||
services the chip from inside the transfer wait (250,000 of 250,240 looks).
|
||||
Held, the 68000 is halted and gets 369 looks: **every** lump boundary has a
|
||||
seam, worst **72.8 ms**, **236 ms total = 2.31% of the audio** — a buzz once a
|
||||
second, with every byte still correct. 67.2's drift was predicted at 1.25 s over
|
||||
the game and played at **1.26** (FINDINGS 68).
|
||||
|
||||
**And the audio level is measured now, off the whole disc — the headroom is not
|
||||
worth buying.** The chip clamps its accumulator at **10 bits inside the
|
||||
recursion**, and the ten seconds every audio figure here is quoted on peak at
|
||||
435 of 511, which fits *by accident*: it is a −13.4 dBFS passage. Measured
|
||||
against the game's own footage instead — all 201 streams that have audio,
|
||||
21.5 minutes, through the same extract chain — the **disc peaks at 946 of 2048,
|
||||
−6.71 dBFS, 5.35 dB over the clamp**, and the census behind that peak is **687
|
||||
samples of 20.2 million: 402 events, 44.0 ms, longest 0.90 ms**. Forty windows
|
||||
drawn over the game and encoded at six gains then price the choice, and it is
|
||||
not close: the disc's own level has the **best mean SNR (22.03 dB)** and the
|
||||
gain that guarantees zero clamping costs **0.85 dB across the whole game** to
|
||||
buy back **1.90 dB on the 2.11 seconds that clamp**, because the OKI step
|
||||
table's floor is a constant and does not scale with the signal. **So the level
|
||||
does not change** — `--audio-gain` exists so it is a parameter with a
|
||||
measurement behind it rather than a shift nobody chose.
|
||||
|
||||
And 66.3's *mechanism* — that a clamp is a wrong state the next nibble is
|
||||
applied to — does not survive a control. Error after a clamp run is elevated
|
||||
about 5x; so is the same window at a gain that never clamps, read at the same
|
||||
indices, because those samples are simply loud. Worst ratio **1.28**, and the
|
||||
clamped encode's whole-window mean error is the **lower** of the two. The reason
|
||||
is that `adpcm.encode` runs the chip's clamp inside its own sixteen-way search,
|
||||
so it never loses the chip's state. The worry was right about the mechanism and
|
||||
aimed one layer too late: an encoder clamping at 12 bits while the chip clamps
|
||||
at 10 is exactly that divergence, and session 34 had already closed it
|
||||
(FINDINGS 69).
|
||||
|
||||
**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
|
||||
@@ -462,7 +505,8 @@ px68k's own GVRAM model, then **runs the packed player for 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 asks the emulated MSM6258 which of
|
||||
sixteen decoders it is, then gates the DLXP2 container and every one of its
|
||||
axes, then prints `ALL GREEN`.
|
||||
axes, then measures the audio level off every stream of the game's own footage
|
||||
and gates the disc's peak against the chip's clamp, then prints `ALL GREEN`.
|
||||
|
||||
## Reproducing this
|
||||
|
||||
@@ -611,6 +655,12 @@ tools/analysis/ measurement scripts, numbered in the order they were written.
|
||||
what both cost in accumulated seek slack, across explicit
|
||||
rates. Its cycle counts are PARSED out of the rig's log, not
|
||||
pasted in, so they cannot go stale silently.
|
||||
35 reads every stream of the game's own footage and reports
|
||||
the disc's peak against the chip's 10-bit clamp, the RUN
|
||||
LENGTHS of the samples above it (687 samples in 402 events is
|
||||
a different sound from 687 in one), and what six gains cost on
|
||||
windows drawn over the whole game. --gate asserts those
|
||||
numbers; --recover is the control that kills 66.3's mechanism.
|
||||
buscost.py is the shared bus-cycle table. The per-block
|
||||
constants live in tools/encoder/vq_hybrid.py and are imported,
|
||||
never copied.
|
||||
|
||||
Reference in New Issue
Block a user