Take the player through a branch with sound, and find the predictor does not seek
FINDINGS 71, ROADMAP P6d. 70.3 named exactly what was missing -- packed.s starts PG_AK/PG_AKF at lump 0 and has no audio seek path -- and priced its absence at a mean 416.5 ms of silence over the arcade's 409 within-container seek targets. pg_aseek is that path: the lump index, the stream position, the remainder accumulator and the byte offset into the group, then the second READ(10) at the lump's own LBA and a re-arm part way into the buffer. Measured off a real volume: 132,162 B of spliced stream accounted for byte by byte in MAME's own capture, across a branch at frame 37 -- four frames into lump 3, deliberately NOT on a group boundary -- in both chip configurations. Skip computed 2,604 B, cadence says 2,604. THE PREDICTOR DOES NOT SEEK, AND THE ERROR IS DC. The MSM6258's accumulator is a pure integrator with no leakage term, so a branch that hands the chip bytes chosen for a state it is not in produces an offset that does not decay. Playing through: DC -355 of 511 with AC 0.00 -- the right shape from the wrong ground -- still -108 four seconds later. STOP and re-PLAY: all 62,500 post-seek samples are EXACTLY a decode from the container's own init, and the whole error is the single constant -65. A re-PLAY is 5.5x better and neither is zero, so PG_ARST is a mailbox with a number under it. The host computes -65 out of the container's bytes and the gate asserts the equality rather than printing both. AND THE ONLY FIX THAT REACHES ZERO IS THE ENCODER'S. A player cannot set the chip's accumulator, only reset it. Resetting the encoder's predictor every frame makes all 119 of the container's branch points exact for 0.33 dB (21.99 -> 21.66), because the step table's floor is a constant 16. That is a DLXP3 and it is deliberately not in tools/encoder. TWO SILENT BUGS, BOTH CAUGHT BY THE CAPTURE. pg_udiv32 trashes d4 and pg_aseek held hz there, so the offset came out 1 byte instead of 2,604 -- 166 ms of the wrong part of the scene at exactly the right rate, every counter agreeing. And one already in the tree that had passed this gate three times: pg_ainit waited on a READ-BACK MTC before PLAY, which is the same test as "a byte has left RAM" only if no byte leaves in between. One does, and the chip then plays the scene one byte in, forever. Found by locating the capture's opening samples in the container image: sector 1 + 1. The witness is now the count that was written. ALL GREEN, two new stages included. Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
@@ -158,6 +158,65 @@ if [ "$AUDIO_ON" = "1" ]; then
|
||||
sound (FINDINGS 67.4, and it is the bug session 36 shipped and caught)."
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 7. THE SEEK, WITH SOUND ON IT. FINDINGS 70.3 asked for this and named what
|
||||
# was missing: "src/player/packed.s starts PG_AK/PG_AKF at lump 0 and has no
|
||||
# audio seek path at all". This is that path, run.
|
||||
#
|
||||
# THE FRAME IS CHOSEN NOT TO BE A MULTIPLE OF THE CADENCE, and that is the whole
|
||||
# design of the run. A DLXP2 group is `lump k, then F records`, so a branch
|
||||
# that lands on a group boundary needs no offset and no second read -- and 36 of
|
||||
# the arcade's 409 within-container seek targets do land on one. A run that
|
||||
# picked one of those would exercise the arithmetic that was already there and
|
||||
# report success. DLX_PK_SEEK defaults below to a frame `f mod F != 0`, so the
|
||||
# byte offset inside the lump is load-bearing: get it wrong and the chip is fed
|
||||
# a stream that starts up to F frames early, which is not an error, it is a
|
||||
# rate, and only verify_packed_audio.py's spliced walk can see it.
|
||||
#
|
||||
# AND THE SECOND RESULT IS ONE NO COUNTER CAN REACH: the chip's predictor does
|
||||
# not seek. Every byte can arrive, in order, exactly -- and the samples still
|
||||
# be wrong, because the encoder chose them for a state a continuous play would
|
||||
# have been in. The verifier measures that against its own control.
|
||||
if [ "$AUDIO_ON" = "1" ] && [ "${DLX_PK_NOSEEK:-0}" != "1" ]; then
|
||||
SEEKF=${DLX_PK_SEEK:-37}
|
||||
CADF=$(sed -n 's/^ cad_f = \([0-9]*\),.*/\1/p' tmp/packed_meta.lua)
|
||||
[ $((SEEKF % CADF)) -ne 0 ] || \
|
||||
fail "the seek frame $SEEKF is a multiple of the cadence $CADF, so it lands
|
||||
ON a group boundary -- the one case that needs no byte offset and would
|
||||
pass with the offset arithmetic deleted (FINDINGS 70.3)."
|
||||
echo
|
||||
echo "--- 7. THE SEEK: two passes, the second starting at frame $SEEKF --"
|
||||
echo " lump $((SEEKF / CADF)), $((SEEKF % CADF)) frame(s) into its group"
|
||||
echo " of $CADF (FINDINGS 70.3/71) ---"
|
||||
TOTFR=$(( NFR + NFR - SEEKF ))
|
||||
SECS=$(( TOTFR / 8 + 35 ))
|
||||
# BOTH CONFIGURATIONS, and they are not two speeds of one thing. The chip's
|
||||
# accumulator is an integrator with no leak, so what a branch costs is set by
|
||||
# the state it lands in: play THROUGH and the chip keeps whatever the previous
|
||||
# scene left it in; STOP and re-PLAY and it goes to the container's own `init`
|
||||
# with the step index at 0. Neither is zero and they are 5.5x apart, so the
|
||||
# run measures both and FINDINGS 71.3 chooses.
|
||||
for M in 0 1; do
|
||||
TAG=seek; [ "$M" = 1 ] && TAG=seek_rst
|
||||
echo " -- the chip $([ "$M" = 1 ] && echo 'STOPPED and re-PLAYED' \
|
||||
|| echo 'PLAYING THROUGH') the branch"
|
||||
SOUNDARGS="-samplerate 15625 -wavwrite packed_$TAG.wav"
|
||||
run $TAG DLX_PK_HELD=0 DLX_PK_PACE=1 DLX_PK_FPS="$CFPS" DLX_PK_NFR=$NFR \
|
||||
DLX_PK_AUD=1 DLX_PK_AJSON=packed_$TAG.json \
|
||||
DLX_PK_ITER=2 DLX_PK_SEEK=$SEEKF DLX_PK_ARST=$M
|
||||
SOUNDARGS="-sound none"
|
||||
grep -aq "^\[PK\] FLAG=\$FF" "tmp/packed_$TAG.log" || \
|
||||
fail "the $TAG run did not reach the end of the second pass."
|
||||
python3 tools/bench/verify_packed_audio.py "$DLXP" "tmp/packed_$TAG.wav" \
|
||||
"tmp/packed_$TAG.json" --seek "$SEEKF" --iters 2 || \
|
||||
fail "the player did not play the container ACROSS A BRANCH ($TAG).
|
||||
Nothing here parses anything (FINDINGS 67.4): a seek that fetched the
|
||||
wrong lump plays 7,168 B of the wrong part of the scene, and one that
|
||||
dropped the byte offset plays the right lump from up to $((CADF-1))
|
||||
frames too early -- neither is an error and both are a sound."
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "${DLX_PK_GATE_ONLY:-0}" = "1" ]; then exit 0; fi
|
||||
|
||||
echo
|
||||
|
||||
Reference in New Issue
Block a user