re: recover the .slb leading segment — mono, and scoped by measurement

to_xma_riffs now emits the leading headerless segment when it sits at a whole
number of XMA1 packets and carries a non-zero byte. VOICE_D_453 goes from a
0.14 s trailing fragment to a 45116-byte leading sub-wave that dominates it.

I withdrew this exact change earlier for two reasons. Both are now answered
rather than argued away:

* "It recovers no audio" -- it used the STEREO format. At two channels every
  bank yields exactly 1792 bytes, one frame, whatever its size. Mono yields up
  to 113x more.
* "It matches 1524 of 8021 RIFF-bearing entries" -- the byte-level reach is
  still 1524, but the audible reach is not. Across the 84 movie-bound banks
  the segment adds >1 s to exactly 7, the hokyu_*_H tankers on D_453/D_454 --
  precisely the broken ones -- and <=0.25 s to 66 of the rest. The largest
  non-resupply addition is S04A at +0.66 s on a 256 s movie.

The safety oracle is recorded with its limits: 8 of the 84 banks ALREADY
exceed their movie's duration before the change, by hundredths of a second,
so it cannot resolve differences at that scale. It establishes scoping, not
correctness. Callers clamp to the movie length regardless.

VOICE_D_451's all-zero leading region is skipped by the non-zero guard, so
the rule cannot prepend silence to a bank that does not need it. Pinned, as
is the packet arithmetic (n = 8, 1, 7, 22, 29) which has no tunable.

slb_disc, movie_subtitle_disc and movie_manifest_disc all still pass.

NOT verified by ear -- that needs a human.

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-26 00:37:06 +00:00
parent ea0eedda86
commit a32c00057e
4 changed files with 152 additions and 20 deletions

View File

@@ -133,7 +133,8 @@ fn parse_voice_clip(name: &str) -> VoiceClip {
/// tracing confirmed the movie→voice binding; this fixes the *decode* of `RT*`.)
pub fn to_xma_riffs(slb: &[u8]) -> Vec<Vec<u8>> {
let mut out = Vec::new();
if find(slb, b"RIFF", 0).is_none() {
let first_riff = find(slb, b"RIFF", 0);
if first_riff.is_none() {
// Headerless single-stream bank.
if let Some(data) = slb.get(HEADERLESS_DATA_OFFSET..) {
if !data.is_empty() {
@@ -142,22 +143,33 @@ pub fn to_xma_riffs(slb: &[u8]) -> Vec<Vec<u8>> {
}
return out;
}
// ❌ A "leading headerless stream" rule was tried here and WITHDRAWN.
// HYBRID banks: a headerless packet stream followed by RIFF sub-waves, two
// SEQUENTIAL SEGMENTS of one clip. The branch above only fires when there is
// no `RIFF` at all, so the leading segment used to be dropped — which is why
// `VOICE_D_453` decoded to 0.14 s: its line is in that segment and only the
// trailing fragment survived.
//
// The structure is real: in all five resupply banks the first `RIFF` sits at
// exactly `HEADERLESS_DATA_OFFSET + n*XMA1_PACKET` (n = 8, 1, 7, 22, 29), and
// 87 % of `VOICE_D_453` lies in front of it. Emitting that region as a
// sub-wave raised byte coverage from 5.4 % to 89.9 %.
// The boundary is arithmetic, not a magic: XMA1 packets are 2048 bytes, so a
// leading stream occupies exactly `HEADERLESS_DATA_OFFSET + n*XMA1_PACKET`.
// It decodes as **mono** — at two channels every bank yields exactly 1792
// bytes, one frame, whatever its size.
//
// But byte coverage was the wrong success metric. The emitted streams decode
// to **1792 PCM bytes** — silence — through the same FFmpeg path that decodes
// the RIFF sub-waves fine, so the region is not XMA1 under the synthesised
// format. And the rule is not narrow: it matches **1524 of the 8021**
// RIFF-bearing entries in `sound.pak`, including `RT*` banks that decode
// correctly today. Landing it would have risked a large regression to fix
// five banks it does not actually fix.
//
// See docs/re/voice-bank-leading-region.md.
// An earlier version of this was withdrawn for two good reasons, both now
// answered: it recovered no audio (it used the stereo format), and it
// matched 1524 of the 8021 RIFF-bearing entries. The byte-level reach is
// still 1524, but the *audible* reach is not: across the 84 movie-bound
// banks the segment adds >1 s to exactly **7** — the `hokyu_*_H` tankers
// bound to `VOICE_D_453`/`454`, i.e. precisely the broken ones — and
// ≤0.25 s to 66 of the rest. Callers clamp to the movie length anyway.
if let Some(ri) = first_riff {
if ri > HEADERLESS_DATA_OFFSET && (ri - HEADERLESS_DATA_OFFSET) % XMA1_PACKET == 0 {
if let Some(data) = slb.get(HEADERLESS_DATA_OFFSET..ri) {
if data.iter().any(|b| *b != 0) {
out.push(build_riff(&synth_xma1_fmt(1, 0, 48000), data));
}
}
}
}
let mut pos = 0usize;
while let Some(ri) = find(slb, b"RIFF", pos) {
// Parse this sub-wave's fmt + data (declared size is honest per sub-wave).