The structure is exact. In all five resupply banks the first RIFF sits at HEADERLESS_DATA_OFFSET + n*2048, where 1392 is a constant this crate already had and 2048 is the XMA1 packet size: n = 8, 1, 7, 22, 29. No free parameter to tune, and the raw bytes agree -- high entropy from offset 0, then a zero run immediately before the RIFF. VOICE_D_451 is the control, its single packet being all zeros. So I made the obvious fix, emitting that region as a sub-wave, and then withdrew it on two measurements: * It does not recover audio. Coverage went 5.4% -> 89.9% for VOICE_D_453, but the emitted stream decodes through FFmpeg to 1792 PCM bytes -- silence -- while the RIFF sub-waves from the same banks decode to 150-270 KB. Byte coverage was the wrong success metric and it looked like progress. * It is not narrow. The rule matches 1524 of the 8021 RIFF-bearing entries in sound.pak, including RT* movie banks that decode correctly today. Landing it would have risked a wide regression in order to not-fix five banks. to_xma_riffs is back to its previous behaviour, verified by re-measuring: coverage is 5.4% / 9.7% again. The refuted attempt is recorded in the code beside the branch it would have changed, so the next person does not re-derive the arithmetic and re-make the change. XMA1_PACKET is kept as a named constant because the blast-radius scan uses it. Artifacts: examples/voice_bank_shape.rs (structure), voice_bank_dump.rs (sub-waves for decoding), slb_hybrid_scan.rs (the 1524 count). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
32 lines
1.3 KiB
Rust
32 lines
1.3 KiB
Rust
//! How many `.slb` banks would a "leading headerless stream" rule affect?
|
|
//!
|
|
//! The rule fires when the first `RIFF` sits at exactly
|
|
//! `HEADERLESS_DATA_OFFSET + n*XMA1_PACKET` with a non-zero leading region.
|
|
//! Before trusting it, count how many banks it would change — including the
|
|
//! `RT*` movie banks that already decode correctly today.
|
|
use sylpheed_formats::{slb, PakArchive};
|
|
|
|
fn main() {
|
|
let disc = std::env::var("SYLPHEED_DISC").expect("set SYLPHEED_DISC");
|
|
let snd = PakArchive::open(format!("{disc}/dat/sound.pak")).expect("sound.pak");
|
|
let (mut total, mut has_riff, mut hybrid, mut hybrid_nonzero) = (0, 0, 0, 0);
|
|
for e in snd.entries() {
|
|
let Ok(b) = snd.read(e) else { continue };
|
|
total += 1;
|
|
let Some(ri) = b.windows(4).position(|w| w == b"RIFF") else { continue };
|
|
has_riff += 1;
|
|
if ri > slb::HEADERLESS_DATA_OFFSET
|
|
&& (ri - slb::HEADERLESS_DATA_OFFSET) % slb::XMA1_PACKET == 0
|
|
{
|
|
hybrid += 1;
|
|
if b[slb::HEADERLESS_DATA_OFFSET..ri].iter().any(|x| *x != 0) {
|
|
hybrid_nonzero += 1;
|
|
}
|
|
}
|
|
}
|
|
println!(
|
|
"sound.pak entries {total}; with a RIFF {has_riff}; \
|
|
first RIFF at 1392+n*2048 {hybrid}; of those with a NON-ZERO leading region {hybrid_nonzero}"
|
|
);
|
|
}
|