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
7.4 KiB
🔴 A 6-channel PulseAudio capture SCRAMBLES AND DUPLICATES channels unless the maps match
Classification: measured, on the capture chain itself rather than on the game. Recorded because a capture taken with this defect was handed to the port as evidence, cost them a full controlled analysis, and the negative they correctly reported was my instrument, not the guest.
What happened
adv-game-output-6ch.wav was captured from Canary through a PulseAudio null
sink and shared as "what the game emits during ADV". The port could not match
it against anything — the ADV bed, any of the three XMA voice streams,
BGM_103, S00A — with best-vs-runner-up margins of 0.001–0.016 everywhere,
i.e. plateaux rather than peaks. They controlled that three ways (their
instrument finds bed vs bed at r=1.000 margin +0.115; their .ogv reference
matches the disc's .wmv at r=1.000 margin +0.114; and drift was excluded by
windowed lags scattering across the movie). They also observed that capture
channels 3 and 6 were byte-identical, same MD5.
That duplicate pair is the tell, and it is reproducible without the emulator.
The control I should have run first
Six channels, each a different tone, so any reorder, drop or duplication
shows up as a wrong frequency. Played to the sink with paplay, recorded from
its monitor with the same parec invocation the ADV capture used.
Sink map FL,FR,RL,RR,FC,LFE, i.e. NOT the stream's map — the original setup:
| channel | expected | captured | |
|---|---|---|---|
| 0 | 400 Hz | 400 Hz | ok |
| 1 | 800 Hz | 3200 Hz | wrong |
| 2 | 200 Hz | 200 Hz | ok |
| 3 | 1600 Hz | 800 Hz | wrong |
| 4 | 3200 Hz | 800 Hz | wrong |
| 5 | 6400 Hz | 200 Hz | wrong |
ch2 == ch5, byte-identical — the same artefact the port found. The 6400 Hz
and 1600 Hz channels are gone entirely, replaced by duplicates.
Sink map made identical to Canary's own stream map
(front-left,front-right,front-center,lfe,rear-left,rear-right), and the same
map given to parec explicitly:
| channel | expected | captured |
|---|---|---|
| 0–5 | 400 / 800 / 200 / 1600 / 3200 / 6400 | 400 / 800 / 200 / 1600 / 3200 / 6400 |
No duplicates. CONTROL PASSED.
🔴 And a LEVEL CHECK cannot see this failure — by construction
The port made this point while building a checker for it, and it refutes something written above.
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 no matter how the channels are permuted or duplicated — and on real content the peaks simply differ from each other, which looks equally healthy. Either way the table is uninformative.
⚠️ So "the WAV has plausible per-channel levels" was not weak evidence that the
capture was sound; it was no evidence, and this page said otherwise. The
per-channel peak table is the natural thing to eyeball after a capture and it is
blind to remap corruption. What detects it is hashing each channel and
comparing — the port's tools/port/check-capture, controlled in both directions
(six distinct tones → PASS; this page's known-bad pattern → FAIL naming all four
pairs; the withdrawn capture → FAIL on ch2 == ch5).
The rule
⚠️ A null sink whose channel_map differs from the client's makes PulseAudio
remap, and a 6-channel remap silently loses channels and duplicates others.
There is no error, no warning, and the WAV has the right length, the right
channel count and plausible per-channel levels. Set the sink's map to the
client's, and pass the same map to parec:
MAP=front-left,front-right,front-center,lfe,rear-left,rear-right
pactl load-module module-null-sink sink_name=cap channels=6 channel_map=$MAP
parec -d cap.monitor --channels=6 --rate=48000 --format=s16le --channel-map=$MAP …
🔴 What this withdraws
adv-game-output-6ch.wavis withdrawn as evidence. Its channels are scrambled and one pair is a duplicate. Nothing should be concluded from it, in either direction — it is not evidence that the game emits something unexpected, and the port's inability to match it is fully explained.- "All six channels carry signal" — withdrawn. One of the six was a copy of another.
- "The surround and LFE channels are not zero, which a stereo guest padded
into a 6-channel frame would give" — withdrawn. It was offered as weak
support for the 5.1 reading of a voice cue's three streams
(
voice-three-streams-are-concurrent.md), and it is worth nothing. 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. That is read from the emulator's own log, not from the audio path, and it reproduced on two independent boots.
The lesson, in the form it should have been applied
The corpus's own rule is run your instrument through a control first. Here the control needed no emulator, no disc and 30 seconds: play a known signal through the capture chain and check that it comes back. It was not run, an artefact was published, and the person who found the defect was the one who could not see the instrument. ⚠️ A capture is an instrument, not just an output — the same scrutiny a parser or an estimator gets.
✅ The capture that passes — recipe, and how it proves itself
Take 2, 2026-08-29. Verified with the port's independent
tools/port/check-capture (six distinct channel MD5s → PASS) before being
shared, deliberately using their tool rather than the hand that made the file.
MAP=front-left,front-right,front-center,lfe,rear-left,rear-right # Canary's own
pactl load-module module-null-sink sink_name=cap channels=6 channel_map=$MAP
parec -d cap.monitor --channels=6 --rate=48000 --format=s16le \
--channel-map=$MAP --file-format=wav out.wav & # recorder FIRST
PULSE_SINK=cap SDL_AUDIODRIVER=pulseaudio \
run-canary --mute=false … # both mutes off
Two properties make it self-checking, and both were the port's asks:
- The recorder starts before the emulator, so WAV
t=0precedes process launch and the movie cannot fall outside the window by accident. - A screenshot every ~11 s, keyed to the recording's own clock. Classified
against the committed references afterwards, this run reads
movie/otherfor t = 10 … 251 and thentitle_noplateat t = 262 (r = +0.998),title_plateat 277/289. So the 253 s of audio sits wholly inside the movie, with the title arriving just after it ends. A miss would now be diagnosable instead of ambiguous — which is the whole difference from take 1.
⚠️ It is still the full mix — the movie's own WMA bed plus the voice streams. Nothing at this boundary separates them.
❔ New, unexplained: this run decoded FIVE XMA streams, not three
--xma_param_probe on the take-2 boot logs five distinct byte_size values:
ADV's three (1 294 336 / 1 118 208 / 1 171 456) plus 1 150 976 and
1 269 760. The extra pair belongs to some other cue and is unidentified —
they are not BGM_103's two waves (3 876 864 / 3 930 112). A pair is the shape
bgm-two-stems documents for music banks, so a
second bank is the first guess and it is untested.