slb: the seek chunk gives the data offset structurally, and breaks the 28 ties

The ties needed a different signal, not a longer scan. Banks carry one: a seek
chunk sitting on a packet boundary, so seek_pos % 2048 IS the data offset. On
the 6033 labelled banks with a seek before their first RIFF, 6031 agree
(99.97%) -- better than the packet scan and structural rather than statistical,
so scan_data_offset now tries it first.

On the scan's 28 ties it resolves 26 correctly and 0 wrongly (2 have no usable
seek). Combined rule scores 7354/7358 = 99.95%, up from 99.62%. 762 of the 1495
RIFF-less banks carry a seek, so the signal exists where it is needed.

Also ruled out, since a wrong offset was this page's whole subject: the header
is not audio being discarded. Adding 0 to the candidate set, it wins 6 of 7358.

7 disc tests pass.
This commit is contained in:
Sylpheed RE agent
2026-08-26 04:32:23 +00:00
parent de5ea35452
commit 6044ba49a0
4 changed files with 67 additions and 8 deletions

View File

@@ -166,14 +166,37 @@ fn packet_plausibility(slb: &[u8], start: usize) -> f32 {
}
}
/// The data offset implied by the bank's `seek` chunk, if it has one.
///
/// A bank's `seek` chunk lands on a packet boundary, so `seek_pos % XMA1_PACKET`
/// *is* the data offset. Measured on the 6 033 labelled banks that have a
/// `seek` before their first `RIFF`: **6 031 agree (99.97 %)**, 2 disagree.
/// This is structural rather than statistical, which is why it is tried first.
fn seek_chunk_offset(slb: &[u8]) -> Option<usize> {
let pos = find(slb, b"seek", 0)?;
let residue = pos % XMA1_PACKET;
DATA_OFFSET_CANDIDATES.contains(&residue).then_some(residue)
}
/// Recover a bank's data offset when there is no `RIFF` to derive it from.
///
/// Picks the candidate whose packet headers look most like a real XMA1 stream.
/// Cross-checked against the 7 358 banks where the answer *is* known from the
/// `RIFF` position: **7 330 correct (99.62 %)**, and every one of the 28 misses
/// is a tie on the top score — the scan is never wrong when it has a unique
/// winner. Ties fall back to [`HEADERLESS_DATA_OFFSET`].
/// Two independent signals, tried in order of how well each is evidenced:
///
/// 1. **the `seek` chunk's position** mod the packet size — 99.97 % on the
/// labelled set, and structural rather than statistical;
/// 2. **packet-header plausibility** — pick the candidate whose XMA1 headers
/// stay in range over the first 24 packets. Alone this is 99.62 %, and all
/// 28 of its misses are ties rather than wrong unique winners.
///
/// Together, on the 7 358 banks where the answer *is* known from the `RIFF`
/// position: **7 354 correct (99.95 %)**. The `seek` residue resolves 26 of the
/// scan's 28 ties correctly and none of them wrongly; the other 2 have no
/// usable `seek`. Falls back to [`HEADERLESS_DATA_OFFSET`] when neither signal
/// decides.
pub fn scan_data_offset(slb: &[u8]) -> usize {
if let Some(off) = seek_chunk_offset(slb) {
return off;
}
let mut best = (HEADERLESS_DATA_OFFSET, -1.0f32);
let mut tied = false;
for &c in &DATA_OFFSET_CANDIDATES {