Files
Sylpheed/crates/sylpheed-formats/examples/sound_cue_fields.rs
MechaCat02 62376dd4a1 style: rustfmt sweep — 107 files the lint gate never saw
This branch predates CI on `main`. `cargo fmt --all` only; no behaviour.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 16:34:40 +02:00

94 lines
3.3 KiB
Rust
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! F2 — is a per-cue or per-bus GAIN on the disc?
//!
//! The port has no gain value anywhere in its export: `confirm` peaks at
//! 0.0 dBFS and sits 3 dB above the music. A cue record commonly carries a
//! volume beside its wave index. This asks the disc directly rather than
//! choosing a number.
//!
//! Method: dump every token of every `tables.pak` object whose tokens mention
//! SOUND/BANK/SE/BGM, so a gain field would appear as a token if one exists.
//! ⚠️ A NEGATIVE here is only as good as its coverage, so this prints the token
//! count per object and does not filter — a field missed by a filter would read
//! exactly like a field that is not there.
//!
//! cargo run --release -p sylpheed-formats --example sound_cue_fields -- $SYLPHEED_DISC
use sylpheed_formats::{idxd::IdxdObject, pak::PakArchive};
fn main() {
let a: Vec<String> = std::env::args().collect();
let root = a
.get(1)
.cloned()
.unwrap_or_else(|| std::env::var("SYLPHEED_DISC").unwrap());
let arc = PakArchive::open(format!("{root}/dat/tables.pak")).unwrap();
// Anything a gain would plausibly be called, plus the audio nouns.
const GAINY: &[&str] = &["VOL", "GAIN", "LEVEL", "DB", "ATTEN", "AMP", "MIX", "LOUD"];
let mut audio_objs = 0usize;
let mut gain_hits: Vec<(usize, String)> = Vec::new();
for (i, e) in arc.entries().iter().enumerate() {
let Ok(b) = arc.read(e) else { continue };
let Ok(o) = IdxdObject::parse(&b) else {
continue;
};
let t = o.tokens();
let up: Vec<String> = t.iter().map(|s| s.to_uppercase()).collect();
let is_audio = up.iter().any(|s| {
s.contains("SOUND")
|| s.contains("BANK_")
|| s.starts_with("SE_")
|| s.starts_with("BGM_")
});
if !is_audio {
continue;
}
audio_objs += 1;
println!(
"audio object #{i}: schema {:08x}, {} tokens",
o.schema_hash,
t.len()
);
for (j, tok) in up.iter().enumerate() {
if GAINY.iter().any(|g| tok.contains(g)) {
gain_hits.push((i, t[j].clone()));
}
}
}
println!("\naudio-bearing objects examined: {audio_objs}");
println!("tokens matching {GAINY:?}: {}", gain_hits.len());
for (i, tok) in &gain_hits {
println!(" object #{i}: {tok}");
}
if gain_hits.is_empty() {
println!("\n==> NO gain-like token in any audio object of tables.pak.");
}
// CONTROL: the search must be able to FIND a token when one is present.
// Without this, "no hits" is indistinguishable from a broken matcher.
let mut ctrl = 0usize;
for e in arc.entries() {
let Ok(b) = arc.read(e) else { continue };
let Ok(o) = IdxdObject::parse(&b) else {
continue;
};
ctrl += o
.tokens()
.iter()
.filter(|s| s.to_uppercase().contains("SE_UI"))
.count();
}
println!(
"\nCONTROL — the same matcher looking for a token known to exist (\"SE_UI\"): {ctrl} hits"
);
println!(
" {}",
if ctrl > 0 {
"PASS: the matcher finds tokens that are there"
} else {
"FAIL: matcher is broken, the negative above means nothing"
}
);
}