port: fold only the channels that carry signal, and measure what the leading chunk actually is
TWO DEFECTS AND ONE MEASUREMENT, all from verifying the previous commit rather than from reading it. Channel 2 of both voice streams is DIGITALLY SILENT -- peak -inf over the whole file. The voice is a mono recording carried in a nominally stereo stream, and averaging it with silence cost 5.94 dB. The doc comment directly above the code that did it warned that "a stereo matrix applied to a mono voice track is not an error, it is a -6 dB attenuation that nothing reports", and then the code checked the DECLARED channel count instead of the content. `live_channels` now measures which channels carry signal and averages only those. Three defects this iteration were the same shape: a silent chunk in a sum, a silent channel in a fold, and a pan matrix naming channels that do not exist. Each is an input contributing nothing while still counting in a divisor, and none is visible in anything but a level. THE LEADING CHUNK IS THE TAIL OF THE FULL-LENGTH ONE. The Decoder settled by byte-span analysis that it is the movie's own dialogue, 17 of 17 -- killing its own hypothesis that it was an in-mission line -- and asked whether dropping it is a truncation, having no XMA1 decoder. Sliding envelope correlation with overhang allowed and normalised over the overlap: ADV r=0.998 at +52.8 s, S00A r=0.932 at +25.6 s, against controls of 1.000 (self) and 0.289 (a different movie). Both lags put chunk 0 flush against the END of chunk 1. Sample domain, lag refined to one sample then a scalar best-fit: residuals 16.70 dB and 23.15 dB below target. So dropping it removes a DUPLICATE and the exporter was right for a worse reason than it gave. The manifest note is NOT rewritten to claim that -- the structural conclusion belongs on the Decoder's page, not in my manifest -- but it no longer equates the chunk with BGM_103's third sub-wave, which a disc-wide census showed is a different structure, and it now says in words that the omission must not be read as junk removal. Not converted, deliberately: the Decoder's 504464 B anchor constant. Bytes per second is not constant even inside one region -- chunk 1 is 1118268 B and chunk 2 is 1171516 B for the SAME 137.324 s -- so any figure in seconds off it would be invented. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF
This commit is contained in:
@@ -2656,3 +2656,81 @@ out on its own. But a duration tie is an *observation* and `bank_header_len` is
|
||||
*decoded*, so the rule switches the day `c1f3608` reaches `main`.
|
||||
`sylpheed-formats` is a path dependency and merging another agent's topic branch
|
||||
is not the port's to do.
|
||||
|
||||
## The mono fold I warned about, in the comment directly above the code that did it
|
||||
|
||||
`export_voice`'s first version folded to mono by averaging every **declared**
|
||||
channel, and the doc comment above it said, in as many words, that *"`pan`
|
||||
silently ignores a channel the input does not have — so a stereo matrix applied
|
||||
to a mono voice track is not an error, it is a −6 dB attenuation that nothing
|
||||
reports."*
|
||||
|
||||
It then did exactly that. Per-channel `astats` on both voice streams:
|
||||
|
||||
| | channel 1 | channel 2 |
|
||||
|---|---|---|
|
||||
| `ADV` chunk 1 | peak +0.000 dBFS | **peak −inf** |
|
||||
| `S00A` chunk 1 | peak −4.207 dBFS | **peak −inf** |
|
||||
|
||||
The voice is a **mono recording carried in a nominally stereo stream**, and
|
||||
averaging it with silence cost **5.94 dB** — which is most of why `S00A`'s
|
||||
exported dialogue sat at −16.2 dBFS against a source chunk peaking at −4.2 (the
|
||||
other 6.02 dB was summing a silent *chunk*, corrected in the same iteration).
|
||||
|
||||
**Checking the declared channel count is not checking the content, and only the
|
||||
content is the fold.** `live_channels` now measures which channels carry signal
|
||||
and averages only those. `sylpheed-viewer`'s `pan=mono|c0=c0` reaches the right
|
||||
answer here for a reason it does not state; this reaches it for a stated one, and
|
||||
would still be right if a stream ever did carry two live channels.
|
||||
|
||||
Worth recording as a pattern rather than a bug: **three defects this iteration
|
||||
were all the same shape** — a silent chunk in a sum, a silent channel in a fold,
|
||||
and a `pan` matrix naming channels that do not exist. Each is an input that
|
||||
contributes nothing being counted in a divisor, and none of them is visible in
|
||||
anything but a level.
|
||||
|
||||
## The leading chunk is the TAIL of the full one — measured, and it is why the region over-covers
|
||||
|
||||
The Decoder settled by byte-span analysis that a voice region's leading chunk is
|
||||
**the movie's own dialogue, 17 of 17** — killing its own standing hypothesis that
|
||||
it was an in-mission `VOICE_D_*` line — and asked whether dropping it is
|
||||
therefore a truncation. It has no XMA1 decoder; this container does.
|
||||
|
||||
Envelope cross-correlation, sliding with overhang allowed at both ends and
|
||||
normalised over the overlap only. ⚠️ **This corrects an earlier number of mine**:
|
||||
a first pass scored 0.768 and I called it nothing, correctly — that search only
|
||||
tried lags where the shorter chunk fitted *wholly inside* the longer one, and it
|
||||
peaked on the boundary of its own range.
|
||||
|
||||
| | best *r* | at lag | overlap |
|
||||
|---|---|---|---|
|
||||
| `ADV` chunk 0 → chunk 1 | **0.998** | **+52.8 s** | 84.5 s |
|
||||
| `S00A` chunk 0 → chunk 1 | **0.932** | **+25.6 s** | 68.0 s |
|
||||
| control — `ADV` chunk 0 against itself | 1.000 | 0.0 s | — |
|
||||
| control — `ADV` chunk 0 against `S00A` chunk 1 | **0.289** | — | 28.2 s |
|
||||
|
||||
**Both lags put chunk 0 flush against the end of chunk 1**: 52.8 + 84.55 =
|
||||
137.35 s against chunk 1's 137.324, and 25.6 + 68.07 = 93.67 against 93.694.
|
||||
|
||||
Confirmed in the sample domain — lag refined to ±1 sample on the loudest second,
|
||||
then a scalar best-fit over the whole overlap: `ADV` +52.8000 s, gain 0.833,
|
||||
residual **16.70 dB** below the target; `S00A` +25.6320 s, gain 0.365, residual
|
||||
**23.15 dB**. 98–99.5 % of the energy is a scaled copy: the same material at a
|
||||
different gain, not bit-identical, which is what a lossy decode at two gains
|
||||
should look like.
|
||||
|
||||
**So dropping chunk 0 removes a duplicate, and is not a truncation** — the
|
||||
exporter's existing behaviour is right for a better reason than the one it gave.
|
||||
🟡 **The manifest note has NOT been rewritten to say so.** The structural claim —
|
||||
that the region over-covers because it re-presents its own tail, and that this
|
||||
accounts for the whole 2.6× — is the Decoder's to write down; this page reports
|
||||
the measurement and says which is which. The note stays hedged until its page
|
||||
carries the conclusion, and the hedge is true either way.
|
||||
|
||||
⚠️ **The 504 464 B constant was deliberately not converted.** The Decoder found
|
||||
the region anchor sitting that far after the true predecessor trailer on all 17
|
||||
and pointedly declined to call it missing dialogue. Converting it needs a
|
||||
byte↔time mapping, and the numbers above are the reason there isn't one: chunk 1
|
||||
is 1 118 268 B and chunk 2 is 1 171 516 B for **the same 137.324 s**, so bytes per
|
||||
second is not constant even inside a single region. Any figure in seconds off
|
||||
that constant would be invented.
|
||||
|
||||
Reference in New Issue
Block a user