Files
Sylpheed/crates/sylpheed-formats/examples/voice_region_start_audit.rs
sylph-decoder 3e8235ddbd re: resolve_movie_voice_region starts INSIDE the first stream, 8 of 10 multichannel regions
Found because the port refused to apply my stream assignment and did the
arithmetic instead: the running decoder's three ADV contexts sum to 3 584 000 B
against a resolved region of 3 114 352 -- 15 % too small to hold them. Two spans,
one wrong, and it was the disc side.

The gap is 238 packets exactly (487 424 B), which is what a start offset looks
like; ctx0 declares 632 packets and the resolver's leading chunk has 394.

Verified against the decoder's own byte_sizes, which cannot be fitted to: at
-238 packets to_xma_riffs yields [1294336, 1118208, 1171456], all three exactly.
It is a real boundary and not the end of a sweep -- at -300 the previous asset's
chunks appear while the three ADV sizes stay stable.

Disc-wide: 24 of 24 single-chunk regions start at a boundary; 8 of 10 three-chunk
regions start mid-stream. The defect is specific to the multichannel case.

The audit's per-movie number is an UPPER BOUND, not the clip -- its stopping rule
is the chunk count changing, and to_xma_riffs absorbs a few packets of the
previous asset first (243 reported for ADV against a true 238). Only ADV has
external ground truth.

Consequence: in those 8 movies the leading chunk is a truncated first stream, not
a spurious artefact, and anything measured on it was measured on a fragment --
including this corpus's own chunk-0 level, though the assignment survives because
its ratio test was chosen to be immune to the clipping.

The resolver is NOT patched. Why the predecessor cue's trailer lands 238 packets
into the next asset is unanswered, and a fix guessed from one movie would be
worse than a documented defect.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 08:41:22 +00:00

64 lines
2.9 KiB
Rust

//! Does `resolve_movie_voice_region` start inside the first stream, disc-wide?
//!
//! Verified on `ADV`: the resolver starts **238 packets (487 424 B) late**, and
//! extending the span by exactly that reproduces the running decoder's three
//! byte_sizes to the byte. The decoder is the ground truth there, but it exists
//! for one movie only — so this asks a structural question instead.
//!
//! **If the region began at a stream boundary, stepping the start backwards would
//! immediately expose the PREVIOUS asset's chunks.** If it began mid-stream, the
//! first chunk instead *grows*, packet for packet, until the real boundary. The
//! number of packets it grows for is the clip.
//!
//! cargo run -p sylpheed-formats --example voice_region_start_audit
use sylpheed_formats::media::{self, DirectorySource, DiscSource};
use sylpheed_formats::movie_manifest;
use sylpheed_formats::slb::{self, VoiceLang};
fn main() {
let disc = std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC");
let src = DirectorySource::new(std::path::PathBuf::from(&disc));
let tpak = src.open_pak("dat/tables.pak").expect("tables.pak");
let manifest = tpak
.entries()
.iter()
.find_map(|e| tpak.read(e).ok().filter(|b| movie_manifest::is_manifest(b)))
.expect("manifest");
let movies: Vec<String> = movie_manifest::parse(&manifest)
.into_iter()
.map(|m| m.movie)
.collect();
println!("{:10} {:>8} {:>12} {:>10} {}", "movie", "chunks", "first chunk", "clip pkts", "verdict");
let (mut clipped, mut clean, mut skipped) = (0, 0, 0);
for movie in movies {
let Some((start, end)) = media::resolve_movie_voice_region(&src, &movie, VoiceLang::English)
else { skipped += 1; continue };
// ONE read of the region plus a lead-in, then slide inside it. Re-reading
// several MB per step made this too slow to finish at all.
const LEAD: u64 = 600 * 2048;
let lead = LEAD.min(start);
let buf = match src.read_segment_range("dat/sound", start - lead, (end - (start - lead)) as usize) {
Ok(b) => b, Err(_) => { skipped += 1; continue }
};
let at = |back: usize| -> Vec<Vec<u8>> {
let off = lead as usize - back * 2048;
slb::to_xma_riffs(&buf[off..])
};
let base_riffs = at(0);
if base_riffs.is_empty() { skipped += 1; continue }
let n0 = base_riffs.len();
let first0 = base_riffs[0].len() - 60;
let mut clip = 0usize;
for k in 1..=(lead as usize / 2048) {
if at(k).len() != n0 { break }
clip = k;
}
let verdict = if clip == 0 { clean += 1; "starts at a boundary" }
else { clipped += 1; "STARTS MID-STREAM" };
println!("{movie:10} {n0:>8} {first0:>12} {clip:>10} {verdict}");
}
println!("\nclipped {clipped} clean {clean} skipped {skipped}");
}