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
46 lines
2.0 KiB
Python
46 lines
2.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Extract the audio of a Blu-ray window as mono PCM at an MSM6258 sample rate.
|
|
|
|
The video side of this window is tools/encoder/extract.py; the arguments mean
|
|
the same things and are meant to be given the same values, because an audio
|
|
stream that is not the same seconds as the frames is not this project's audio.
|
|
|
|
The disc is AC-3 5.1 at 48 kHz. The arcade original is MONO, so this downmixes
|
|
-- ffmpeg's default matrix, dialogue from the centre channel included -- and
|
|
resamples to the chip's rate. Nothing here shapes, gates or normalises the
|
|
level: what the ADPCM encoder is handed is what the disc has, so that the SNR
|
|
it reports is the codec's and not a gain stage's.
|
|
"""
|
|
import getpass, os, subprocess, sys
|
|
|
|
BDROM = os.environ.get("DLX_BDROM") or f"/media/{getpass.getuser()}/BDROM"
|
|
STREAM_DIR = f"{BDROM}/BDMV/STREAM"
|
|
|
|
# 8 MHz / {512, 768, 1024}. The chip has no other rates and 15,625 is the one
|
|
# every budget in this project is written against (FINDINGS 52).
|
|
RATES = {15625: 512, 10417: 768, 7813: 1024}
|
|
|
|
|
|
def extract(stream, out, rate=15625, start=None, dur=None):
|
|
if rate not in RATES:
|
|
raise SystemExit(f"{rate} is not an MSM6258 rate: {sorted(RATES)}")
|
|
src = f"{STREAM_DIR}/{stream}.m2ts"
|
|
cmd = ["ffmpeg", "-v", "error"]
|
|
if start is not None: cmd += ["-ss", str(start)]
|
|
if dur is not None: cmd += ["-t", str(dur)]
|
|
cmd += ["-i", src, "-vn", "-ac", "1", "-ar", str(rate),
|
|
"-f", "s16le", "-acodec", "pcm_s16le", out, "-y"]
|
|
subprocess.check_call(cmd)
|
|
n = os.path.getsize(out) // 2
|
|
print(f"{stream}: {n} samples @ {rate} Hz mono = {n/rate:.3f} s -> {out}")
|
|
return n
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# extract_audio.py <stream> <out.raw> [rate] [start_s] [dur_s]
|
|
stream, out = sys.argv[1], sys.argv[2]
|
|
rate = int(sys.argv[3]) if len(sys.argv) > 3 else 15625
|
|
start = float(sys.argv[4]) if len(sys.argv) > 4 else None
|
|
dur = float(sys.argv[5]) if len(sys.argv) > 5 else None
|
|
extract(stream, out, rate, start, dur)
|