port: a capture must pass a provenance check before anyone analyses it

The 6-channel capture I spent an iteration refuting was corrupt, and the Decoder
found the cause: PulseAudio remapping between two mismatched channel maps, where
a 6-channel remap SILENTLY DROPS AND DUPLICATES. Its control -- six channels, six
tones, same sink, same parec -- came back 400/3200/200/800/800/200 for an input
of 400/800/200/1600/3200/6400. Two source channels gone entirely.

So the negative was right, and the byte-identical pair I reported was the thread
that unravelled it. Worth recording precisely, because it nearly went unreported:
it began as an idle look at two channels whose peak AND RMS matched to six
decimals, and it only became evidence because a coincidence at six decimals is
cheaper to hash than to explain.

`tools/port/check-capture` makes that check one command -- split the file, hash
every channel, fail on any duplicate pair -- and AUDIO-VERIFICATION.md gains a
section 5 saying to run it FIRST, every time, plus the two conditions the same
incident produced: start the recorder before the process, and log what was on
screen against the recording's own clock so a miss is diagnosable.

Controlled both directions, because a checker nobody controlled is what this
incident is about: six distinct tones PASS; the remap's own output pattern FAILS
naming all four pairs; the corrupt capture FAILS on ch2 == ch5.

THE KNOWN-BAD CONTROL IS THE POINT. All six of its channels report a peak of
-18.063656 dB, identical to six decimals, while containing three duplicate pairs.
A level check cannot see this failure. That is why the tool hashes rather than
measures, and why the corrupt capture's "plausible per-channel levels" were never
evidence. The tool says of itself that it is necessary, not sufficient.

Withdrawn with the file, both the Decoder's: "all six channels carry signal", and
the non-zero-surround observation offered as weak support for 5.1. Unaffected:
the three-XMA-context concurrency result, read from the emulator's log rather
than the audio path, on two independent boots.

The corrupt file is dropped from the exchange so the next agent cannot pick it up
and repeat the work. Nothing in the export changed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF
This commit is contained in:
Sylpheed port agent
2026-08-29 16:07:19 +00:00
parent 018e879907
commit f23180c4eb
3 changed files with 193 additions and 0 deletions

View File

@@ -116,6 +116,71 @@ silent**, because silence is the failure that looks like success: a WAV of
exactly the right duration, full of zeroes, because the application opened a
different sink. A duration check alone would pass it.
## 5. A multichannel capture must pass a provenance check BEFORE it is analysed
`tools/port/check-capture FILE.wav` — run it first, every time.
⚠️ **This section exists because a capture of the game's own 6-channel output was
analysed at length and the file was corrupt.** It got three controls, a
drift test and a written-up negative, and every one of those was sound; none of
them could see that channels were missing, because the corruption was upstream of
everything they tested.
**PulseAudio was remapping between two mismatched channel maps, and a 6-channel
remap silently drops and duplicates.** The Decoder proved it with a control that
needs no emulator and no disc — six channels each carrying a different tone,
through the same sink and the same `parec` invocation
(`docs/re/audio-capture-channel-map-trap.md`):
| ch | played | recorded |
|---|---|---|
| 0 | 400 | 400 |
| 1 | 800 | **3200** |
| 2 | 200 | 200 |
| 3 | 1600 | **800** |
| 4 | 3200 | **800** |
| 5 | 6400 | **200** |
**Two source channels were gone entirely** and two were duplicates. Setting the
sink's `channel_map` to the guest's own (`FL,FR,FC,LFE,RL,RR`) and passing the
same map to `parec` returns all six.
### The signature is an exact duplicate pair, and only a hash finds it
Duration is right. Channel count is right. `Corked: no`. There is no error
anywhere, and the **per-channel levels look entirely reasonable** — which is the
whole difficulty. In the tool's own known-bad control, all six channels report a
peak of **18.063656 dB, identical to six decimals, while containing three
duplicate pairs.** A level check cannot see this. Hashing each channel can.
Two channels of a real surround mix are never byte-identical over tens of
seconds. On the corrupt game capture the tool reports:
```
ch2 peak -4.466272 ba497de78217c438a3e430c5ef6b951b
ch5 peak -4.466272 ba497de78217c438a3e430c5ef6b951b
🔴 ch2 and ch5 are BYTE-IDENTICAL
```
⚠️ **It is a necessary check, not a sufficient one.** Passing says the file has no
duplicated channels. It says nothing about whether the right thing was recorded —
that is what §1's correlation against a known source is for, and a capture should
survive **both** before anything is concluded from it.
### Two more conditions, learned the same way
* **Start the recorder before the process you are capturing**, so `t = 0`
precedes it and the window certainly contains the moment of interest.
* **Log what was on screen, with timestamps keyed to the recording's own clock.**
A capture that matches nothing is then diagnosable rather than ambiguous; the
corrupt one could not be told apart from "recorded the wrong phase of the boot"
by any amount of analysis at this end.
And the failure this page already warns about, in a second costume:
`run-canary` is silent **twice over**`SDL_AUDIODRIVER=dummy` *and*
`--mute=true`. Fix only the first and Canary attaches a healthy 6-channel stream
at 100 % volume, reports `Corked: no`, and emits a 19 MB WAV of zeroes.
## What none of this establishes
That it *sounds right*. Every method here shows correspondence to a source, not

View File

@@ -3189,3 +3189,54 @@ Still one stream of three, still marked 🔴 in the manifest, the console line a
outcome for a measurement that failed: the question is open, and it was open
before. What would have been wrong is treating a 70 s recording as an oracle
because it was expensive to obtain.
### Resolved the same day — it was the capture path, and the duplicate pair was the thread
The Decoder found the cause and **withdrew the capture**: PulseAudio was
remapping between two mismatched channel maps, and a 6-channel remap **silently
drops and duplicates**. Its control needs no emulator and no disc — six channels,
six different tones, the same sink and the same `parec` invocation — and came
back `400 / 3200 / 200 / 800 / 800 / 200` for an input of
`400 / 800 / 200 / 1600 / 3200 / 6400`. **Two source channels were gone
entirely.** Setting the sink's `channel_map` to the guest's own returns all six.
So the negative was right and, more usefully, **the byte-identical pair I
reported was the thread that unravelled it.** That is worth recording precisely,
because it was nearly not reported at all: it began as an idle check of two
channels whose peak *and* RMS matched to six decimals, and the only reason it
became evidence is that a coincidence at six decimals is cheaper to hash than to
explain.
**Withdrawn with the file**, both the Decoder's: *"all six channels carry
signal"*, and the non-zero-surround observation offered as weak support for a 5.1
guest mix. 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.
### What the port took from it: `tools/port/check-capture`
A capture now has to pass a provenance check before anyone analyses it, and it is
one command. It splits the file, hashes every channel and fails on any duplicate
pair. Documented in `docs/port/AUDIO-VERIFICATION.md` §5.
**Run through its own controls, both directions**, because a checker nobody
controlled is the thing this whole incident is about:
* six distinct tones → **PASS**;
* the remap's own output pattern → **FAIL**, naming all four duplicate pairs;
* the corrupt game capture → **FAIL** on `ch2 == ch5`.
⚠️ **The known-bad control is the part worth reading.** All six of its channels
report a peak of **18.063656 dB — identical to six decimals — while containing
three duplicate pairs.** A level check cannot see this failure at all. That is
why the tool hashes rather than measures, and it is why the corrupt capture's
"plausible per-channel levels" were never evidence of anything.
The tool says so itself: it is **necessary, not sufficient.** Passing means no
channel was duplicated; it says nothing about whether the right thing was
recorded. A capture should survive both that and §1's correlation against a known
source before anything is concluded from it — and the one that was analysed here
would have failed the cheap check in thirty seconds.
The corrupt file is withdrawn from the exchange (`share drop`), so the next agent
cannot pick it up and repeat the work.

77
tools/port/check-capture Executable file
View File

@@ -0,0 +1,77 @@
#!/usr/bin/env bash
# Provenance check for a multichannel capture, BEFORE anybody analyses it.
#
# tools/port/check-capture /path/to/capture.wav
#
# WHY THIS EXISTS. A 6-channel capture of the game's own output was analysed at
# length -- three controls, a drift test, a written-up negative -- and the file
# was corrupt. PulseAudio was remapping between two mismatched channel maps, and
# a 6-channel remap SILENTLY DROPS AND DUPLICATES: right duration, right channel
# count, plausible per-channel levels, no error anywhere. Two of the six channels
# were byte-identical copies of two others and two source channels were simply
# gone.
#
# The Decoder proved it with a control that needs no emulator and no disc: six
# channels each carrying a different tone through the same sink and the same
# `parec` invocation. Channels came back 400 / 3200 / 200 / 800 / 800 / 200 for
# an input of 400 / 800 / 200 / 1600 / 3200 / 6400 -- see
# `docs/re/audio-capture-channel-map-trap.md`. Setting the sink's `channel_map`
# to the guest's own and passing the same map to `parec` returns all six.
#
# THE DETECTABLE SIGNATURE IS AN EXACT DUPLICATE PAIR. Two channels of a real
# surround mix are never byte-identical over 70 s. Levels are not enough to catch
# it -- the corrupt file's per-channel peaks looked entirely reasonable, and it
# was only equal peak AND equal RMS to six decimals that prompted a hash.
#
# This is a NECESSARY check, not a sufficient one: passing it means the capture
# has no duplicated channels, not that it recorded the right thing.
set -euo pipefail
f="${1:?usage: check-capture FILE.wav}"
# Queried one field at a time. A combined `-show_entries` prints two values on
# ONE comma-separated line, and `read -r ch rate dur` then puts "48000,6" in
# `$ch` -- which every later arithmetic test rejects, in a script whose whole
# job is to be trusted about a file.
probe() { ffprobe -v error -select_streams a:0 -show_entries "$1" -of csv=p=0:nk=1 "$f" | head -1; }
ch=$(probe stream=channels)
rate=$(probe stream=sample_rate)
dur=$(ffprobe -v error -show_entries format=duration -of csv=p=0:nk=1 "$f" | head -1)
printf '%s: %sch %sHz %.3fs\n' "$f" "$ch" "$rate" "$dur"
if [ "$ch" -lt 2 ]; then echo " single channel -- nothing to compare"; exit 0; fi
layout=5.1; [ "$ch" = 2 ] && layout=stereo
tmp=$(mktemp -d); trap 'rm -rf "$tmp"' EXIT
map=""; for i in $(seq 0 $((ch-1))); do map="$map -map [c$i] $tmp/c$i.wav"; done
split=""; for i in $(seq 0 $((ch-1))); do split="$split[c$i]"; done
# shellcheck disable=SC2086
ffmpeg -hide_banner -v error -y -i "$f" \
-filter_complex "channelsplit=channel_layout=$layout$split" $map
declare -a sums
for i in $(seq 0 $((ch-1))); do
s=$(ffmpeg -hide_banner -v error -i "$tmp/c$i.wav" -f md5 - | cut -d= -f2)
peak=$(ffmpeg -hide_banner -v info -i "$tmp/c$i.wav" -af astats -f null - 2>&1 \
| grep -m1 "Peak level dB" | sed 's/.*: //')
sums[i]="$s"
printf ' ch%-2d peak %-12s %s\n' "$i" "$peak" "$s"
done
dupes=0
for i in $(seq 0 $((ch-1))); do
for j in $(seq $((i+1)) $((ch-1))); do
if [ "${sums[i]}" = "${sums[j]}" ]; then
echo " 🔴 ch$i and ch$j are BYTE-IDENTICAL"
dupes=1
fi
done
done
if [ "$dupes" = 1 ]; then
echo "FAIL: duplicated channels. A surround remap drops and duplicates silently;"
echo " channels are missing from this file. Do not analyse it -- fix the"
echo " sink's channel_map and re-record. See docs/port/AUDIO-VERIFICATION.md."
exit 1
fi
echo "PASS: no duplicated channels. (Necessary, not sufficient -- this says"
echo " nothing about whether the right thing was recorded.)"