re: the .slb leading region is XMA1 MONO — 113x more audio than stereo

Retried the format probe with the fmt chunk built to synth_xma1_fmt's exact
byte layout, and with the bank's own RIFF sub-wave decoded through the same
pipe as a CONTROL so a broken harness cannot masquerade as a result.

The channel count is the whole story:

  bank         lead B   channels=2   channels=1
  VOICE_D_450   16384         1792        46756
  VOICE_D_451    2048         1792          896   (all-zero region: control)
  VOICE_D_452   14336         1792        30154
  VOICE_D_453   45056         1792       203648
  VOICE_D_454   59392         1792       294440

channels=2 yields EXACTLY 1792 bytes for every bank regardless of size -- one
frame, then it stops. That constant is the tell. At channels=1 the same data
yields up to 113x more, and the control sub-wave decodes to 13568, so the
pipe works.

Why the previous probe got 0 bytes everywhere is now named: I read
synth_xma1_fmt(2, 2, 48000)'s second argument as a STREAM COUNT when it is a
CHANNEL MASK, and built the WAVEFORMATEX around that misreading.

Also recorded as a refutation, because it was tempting: solving for the
sample rate as decoded-samples / last-subtitle-cue does NOT converge. D_453
implies 21665 Hz -- close enough to 22050 that I nearly wrote it down -- but
D_450 implies 5844 Hz. No single rate explains both, and the decodes are
visibly partial (samples per input byte ranges 2.10-4.96 where a clean decode
would be near-constant).

So the container is identified and the duration is not. Next step recorded:
find why FFmpeg stops early, likely the hardcoded packet/subframe fields.

Artifact: examples/slb_fmt_probe.rs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
This commit is contained in:
Sylpheed RE agent
2026-08-25 23:53:10 +00:00
parent 391f4bd5e6
commit 58ee6ac52c
3 changed files with 181 additions and 11 deletions

View File

@@ -1063,12 +1063,21 @@ premise was wrong.**
five banks fail that: `D_450` cue 4.00 s vs 1.41 s decoded, `D_451` 3.70 vs
1.81, `D_453` **4.70 vs 0.07**. The other two have their only cue at 0.0 s and
give no signal. Artifact `examples/voice_len_vs_subs.rs`, FFmpeg-measured.
**The fmt-variation probe was INCONCLUSIVE** — 36 combinations over
`VOICE_D_453`'s leading region all produced 0 PCM bytes, *including* ones
equivalent to the crate's working `synth_xma1_fmt`, so the probe tested my
hand-built `fmt` chunk rather than the hypothesis. Not evidence the region is
non-XMA. ▶️ Retry building the chunk with the crate's own helper and varying
its parameters. See
**(same day) The leading region IS XMA1 — MONO, not stereo.** At
`channels = 2` every bank decodes to *exactly* 1792 bytes regardless of size
(one frame, then it stops); at `channels = 1` the same data yields up to
**113× more**`VOICE_D_453` goes 1 792 → **203 648**. The bank's own RIFF
sub-wave is decoded through the same pipe as a control (13 568 bytes), so the
harness is sound, and the all-zero `VOICE_D_451` region is the control the
other way. The earlier 0-byte probe was my own error: I read
`synth_xma1_fmt`'s second argument as a stream count when it is a **channel
mask**. ❌ Solving for the sample rate from the subtitle cue **does not
converge** — 21 665 Hz for `D_453` (temptingly near 22 050, and I nearly wrote
it down) but **5 844 Hz** for `D_450`. The decodes are partial: samples per
input byte ranges 2.104.96 where a clean decode would be near-constant.
▶️ Next: find why FFmpeg stops early — likely the packet/subframe fields in the
synthesised `fmt`, which are hardcoded (`SubframeData = 4`, `NumStreams = 1`).
See
[`voice-bank-leading-region.md`](voice-bank-leading-region.md).
***(2026-08-25) My own boot-nav diagnosis, MEASURED AND WITHDRAWN.** I said
the run died because `skip_intro.sh` gates the title test at `rmse <= 1500`

View File

@@ -144,7 +144,54 @@ Three of the five are decisive; the other two have their only cue at 0.0 s, whic
tells us nothing in either direction. So **something is genuinely missing from
these banks** — independent of anything above, and now measured rather than felt.
## ❔ Varying the XMA format — inconclusive, and for a boring reason
## ✅ The leading region IS XMA1 — but **mono**, not stereo
Retried with the `fmt ` chunk built to `slb::synth_xma1_fmt`'s exact byte layout
(and with the bank's own RIFF sub-wave decoded through the same pipe as a
**control**, so a broken harness cannot masquerade as a result). Artifact
`examples/slb_fmt_probe.rs`.
The parameter that matters is the channel count, and the difference is not
subtle:
| bank | leading bytes | decoded at **channels = 2** | decoded at **channels = 1** |
|---|---|---|---|
| `VOICE_D_450` | 16 384 | 1 792 | **46 756** |
| `VOICE_D_451` | 2 048 | 1 792 | 896 |
| `VOICE_D_452` | 14 336 | 1 792 | **30 154** |
| `VOICE_D_453` | 45 056 | 1 792 | **203 648** |
| `VOICE_D_454` | 59 392 | 1 792 | **294 440** |
`channels = 2` yields **exactly 1792 bytes for every bank regardless of size**
one frame, then it stops. That constant is the tell: stereo is simply the wrong
shape. At `channels = 1` the same data yields up to **113× more** audio, and the
control sub-wave decodes to 13 568 bytes, so the harness is sound.
`VOICE_D_451` decoding to almost nothing is the expected control the other way:
its leading region is the all-zero one.
The sample rate and channel mask make **no difference to the decoded byte
count** — as expected, since they set playback speed rather than sample count.
## ❌ Solving for the sample rate from the subtitle cue — does NOT converge
`decoded samples / last subtitle cue` should give the real rate if the decode
were complete. It does not agree with itself:
| bank | samples | cue | implied |
|---|---|---|---|
| `VOICE_D_453` | 101 824 | 4.70 s | 21 665 Hz |
| `VOICE_D_450` | 23 378 | 4.00 s | **5 844 Hz** |
21 665 Hz is temptingly close to 22 050, and I nearly wrote that down. The second
bank refutes it: no single rate explains both. The decodes are also visibly
**partial** — decoded samples per input byte ranges 2.10 to 4.96 across the
banks, where a clean decode would be near-constant — so FFmpeg is not consuming
these streams to the end.
So: the container is identified, the duration is not.
## ❔ The first attempt at this — inconclusive, and for a boring reason
The recorded next step was to vary the synthesised `fmt` (channels, streams,
sample rate) rather than assume the container. I tried 36 combinations over
@@ -152,10 +199,11 @@ sample rate) rather than assume the container. I tried 36 combinations over
including combinations that should be equivalent to the crate's own
`synth_xma1_fmt(2, 2, 48000)`, which does at least parse (it yields 1792 bytes).
That means the probe tested **my hand-built `fmt` chunk**, not the hypothesis. It
is not evidence that the region is non-XMA. The next attempt should build the
chunk with the crate's own helper and vary its parameters, rather than
hand-rolling the WAVEFORMATEX.
That means the probe tested **my hand-built `fmt` chunk**, not the hypothesis.
The specific error is worth recording: I read `synth_xma1_fmt(2, 2, 48000)`'s
second argument as a *stream count* when it is a **channel mask**, and built the
`WAVEFORMATEX` around that misreading. Replicating the real layout is what turned
0 bytes into 203 648.
## What this does not settle