Commit Graph

6 Commits

Author SHA1 Message Date
sylph-decoder
02a99bc3e9 re: withdraw the pulse-period argument, and the shared WAV declares itself empty
Two corrections to my own recent work, both prompted by the port checking it.

First, the settle-time page argued the plate delay discrepancy was an instrument
artefact on two legs, and one of them is withdrawn. It said the plate pulse
period acts as an internal clock for presentation rate and measured 2.369 s
against the corpus s 2.3. That estimate rests on ONE interval between two
distinct troughs at a 125 ms sample interval -- uncertainty 0.177 s or 6.7
percent -- and trough-picking on a noisy plateau is fragile enough that
re-running it gives 2.628 s, because an adjacent local minimum had been counted
as a separate trough. Against the corpus s 2.24 that is +17.3 percent, about two
sigma. So the pulse period does not show the run at normal speed; it is too weak
to show anything, and cannot resolve a real-time factor below about 7 percent.

The conclusion survives on the other leg, which is the sound one: the
content-measured 2.247 s agrees with three independent prior readings
(2.13 / 2.132 / 2.138), and both its landmarks are sharp content transitions
rather than a trough on a plateau. A 17 percent slowdown would have put it at
2.49 s.

What that leaves open matters because the port authors from these numbers: the
run carries an unmeasured real-time factor under about 7 percent. The plate delay
is anchored by agreement with prior runs; the menu build-in and B-to-title are
anchored by nothing, so that is a second reason to treat them as provisional.

Second, the shared capture is worse than truncated: parec writes the WAV header
with zero sizes and patches them on clean exit, so the mid-write copy has RIFF
size 8 and data size 0 against 183 MB of actual bytes. Python s wave module
refuses to open it; ffmpeg and ffprobe recover by scanning and report a plausible
duration, which is exactly why it went unnoticed -- the lenient reader hid it.

Also corrects the attribution of the starvation numbers: 39.3 percent and
16680453 frames were measured on the finished local recording, not on the shared
artefact. The port measured the shared copy and got 35.6 percent and 15289876
frames, with burst and gap medians agreeing to 0.1 ms. The diagnosis is
unaffected but a number must say which artefact it came from.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
2026-08-29 16:28:09 +00:00
sylph-decoder
5938d3b1fc notes: build-canary points at a source root that does not exist here
Recorded as a blocker rather than worked around, because it changes what the
next session can plan.

The faithful-capture route is an internal tap at SDLAudioDriver::SubmitFrame,
which receives exactly frame_size_ bytes of the guest s own frame in guest order
with no wall clock in the loop. A cvar-gated WAV writer there would record what
the guest PRODUCED rather than what a device CONSUMED, so it would be gap-free
however slowly the emulator runs -- which is precisely the defect that made both
ADV captures unusable.

The change is small. The build is not. build-canary builds
${PROJECT_DIR:-/work}/xenia-canary, which does not exist in this container; the
source is at /canary. The warm 235 MB tree at /sylph-home/re/canary-build is
configured with CMAKE_HOME_DIRECTORY=/work/xenia-canary, also missing, and its
build-Release.ninja carries no per-file rules -- it re-runs CMake first, and that
reconfigure fails on the absent root. So any Canary change is a full reconfigure
against /canary plus a full compile, at SYLPH_JOBS=4 on a box sitting at about
700 MB free with a documented history of full-parallel builds OOM-killing the
host.

Not attempted: that is a whole session s risk for one probe, and the next session
should decide with the cost in front of it rather than discover it halfway
through.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
2026-08-29 16:22:13 +00:00
sylph-decoder
c05c8e1719 re: take 2 is also unusable -- the sink is starved, 39.3 percent digital silence
The port could not find the movie bed or the cutscene voice in take 2 either,
this time with a correlator they had rebuilt and calibrated in both directions
after retracting the first one. Their negative stands. They named two readings:
the capture path is still losing the guest s mix, or the guest is not emitting
these sources -- and flagged the second as landing on them hard, because if the
game never plays the .wmv s WMA track the port s intro audio has been wrong
since P4.

It is the first, and take 2 says so on its face:

  digital silence on all six channels   6557892 / 16680453 = 39.3 percent
  non-silent runs   10595, median 13.60 ms, longest 1.19 s
  silent runs       10596, median 3.94 ms
  burst+gap period  about 17.5 ms, 57 Hz, duty cycle 60.7 percent

The recording is chopped into 13 ms fragments separated by 4 ms holes, ten
thousand times over -- a starved sink, PulseAudio filling underruns with silence.
That destroys envelope correlation by construction, since the envelope is
dominated by a 57 Hz chop unrelated to the content. The file s strongest
periodicity is 5.2 s rather than BGM_102 s 37.487 s loop; the estimator was
controlled first, recovering a synthetic 37.487 s loop as 37.480 and scoring
non-repeating noise at 0.019.

So the port s alarming hypothesis is NOT supported. Nothing here says the game
fails to play the movie s audio; it says this capture cannot answer either way.

A monitor sink cannot fix it: parec reads a monitor that advances at wall clock
and substitutes silence, so every moment the emulator runs below real time is a
hole and the timebase is warped non-uniformly. The route that would work is an
internal tap at SDLAudioDriver::SubmitFrame, which sees every frame the guest
produces in guest order with no wall clock -- same shape as xma_param_probe,
additive and default-off. Not attempted this iteration.

Also corrects a provenance number I got wrong: I told the port take 2 was 253.3 s
when the shared file is 318.5 and the full recording 349. I read ffprobe while
the recorder was still writing and copied the file before it finished, so the
shared artefact is itself a truncation. Corrected provenance: movie 10-251, title
262-318, back to movie at 329 -- meaning the file includes the title screen,
contrary to what I told them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
2026-08-29 16:19:46 +00:00
sylph-decoder
b047788d37 re: the capture recipe that passes, and a five-stream observation it turned up
Take 2 of the ADV audio capture verified with the port s independent
tools/port/check-capture -- six distinct channel MD5s, PASS -- run before
sharing and deliberately using their tool rather than the hand that made the
file.

Records the recipe: sink channel_map set equal to Canary s own stream map and
the same map passed to parec, so PulseAudio does no remapping; both of
run-canary s mutes off; recorder started before the emulator so WAV t=0 precedes
process launch; and a screenshot every ~11 s keyed to the recording s own clock.

That last pair is what makes it self-checking, and both were the port s asks.
Classified against the committed references, this run reads movie/other for
t=10..251 and then title_noplate at t=262 (r=+0.998) and title_plate at 277/289
-- so the 253 s of audio sits wholly inside the movie with the title arriving
just after. A miss is now diagnosable instead of ambiguous, which is the whole
difference from take 1.

Still the full mix: movie WMA bed plus voice, nothing at this boundary separates
them.

Also records something unexplained that the run turned up: the probe logged FIVE
distinct XMA byte_size values, not three -- ADV s 1294336 / 1118208 / 1171456
plus 1150976 and 1269760. The extra pair belongs to some other cue, is not
BGM_103 s two waves, and a pair is the shape bgm-two-stems documents for music
banks. Untested.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
2026-08-29 16:10:28 +00:00
sylph-decoder
930ab1016d re: a per-channel level check is blind to remap corruption, by construction
The port made this point while building a checker for the channel-map trap, and
it refutes a sentence in my own write-up.

In the known-bad control all six channels report a peak of -18.063656 dB,
identical to six decimals, while the file contains three duplicate pairs. Equal
tone amplitudes make the peak table uniform however the channels are permuted or
duplicated; on real content the peaks simply differ from one another, which looks
equally healthy. The table is uninformative either way.

So "the WAV has plausible per-channel levels" was not weak evidence that a
capture was sound, it was none, and this page implied otherwise. The per-channel
peak table is the natural thing to eyeball after a capture and it cannot see this
failure at all. What detects it is hashing each channel.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
2026-08-29 16:08:10 +00:00
sylph-decoder
e2c599fa72 re: a 6-channel capture scrambles and duplicates channels unless the maps match
The ADV audio capture I shared with the port is withdrawn as evidence. They
could not match it against anything -- the movie bed, any of the three voice
streams, BGM_103, S00A -- with best-vs-runner-up margins of 0.001 to 0.016
everywhere, and they controlled that three ways before saying so. They also
noticed capture channels 3 and 6 were byte-identical.

That duplicate pair reproduces without the emulator, and it is my capture chain.
Six channels each carrying a different tone, played to the null sink and
recorded from its monitor with the same parec invocation:

  sink map NOT matching the client (the original setup)
    expected  400  800  200 1600 3200 6400
    captured  400 3200  200  800  800  200     ch2 == ch5 byte-identical

  sink map made identical to Canary s stream map, and passed to parec too
    captured  400  800  200 1600 3200 6400     no duplicates -- CONTROL PASSED

PulseAudio remaps when the maps differ, and a 6-channel remap silently drops
channels and duplicates others. No error, no warning; the WAV has the right
length, channel count and plausible per-channel levels.

Withdrawn with it: "all six channels carry signal", and the observation that
non-zero surround and LFE weakly supported the 5.1 reading of a voice cue s
three streams. The port said a duplicated channel is not an independent one and
they were right before this control existed.

Unaffected: the three-XMA-context concurrency result, which is read from the
emulator s own log rather than the audio path, on two independent boots.

The control needed no emulator, no disc and thirty seconds. It was not run, an
artefact was published, and the person who found the defect was the one who
could not see the instrument.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
2026-08-29 16:04:52 +00:00