Preserve fractional-millisecond decoder evidence in timing evaluator
This commit is contained in:
1 parent
2c3c91179b
commit
f15ee07ed0
2 files changed
+35
-5
No files matched your search
@@ -138,3 +138,17 @@ missing source windows prohibit numeric accepted timing scores. Historical
|
|||||||
full-source gated DTW **6/8** is context, never an inherited result or an isolated
|
full-source gated DTW **6/8** is context, never an inherited result or an isolated
|
||||||
causal comparison with this end-to-end hybrid run. No new timing score exists
|
causal comparison with this end-to-end hybrid run. No new timing score exists
|
||||||
until this exact mode executes and all checks finish.
|
until this exact mode executes and all checks finish.
|
||||||
|
|
||||||
|
The first attempt at `.searchi/qa/speech-live-timing-v1` failed during source
|
||||||
|
preflight, before any model load or inference. Its immutable `failure.json`
|
||||||
|
SHA-256 is `9ba49fd5cdb69e57c267f579818f226949b02eafbc0e592161fad7593f00c6aa`.
|
||||||
|
The bark recording lasts 2.038594 seconds: its rounded 2039 ms window implies
|
||||||
|
32624 samples, while aligned decoding correctly retains 32618 real samples.
|
||||||
|
The six-sample difference is 0.375 ms. The evaluator now accepts the existing
|
||||||
|
one-millisecond coverage bound (16 samples), without padding, trimming or
|
||||||
|
changing source bytes, labels, ranking, or DTW points. Its regression test
|
||||||
|
accepts that real tail and rejects a 17-sample discrepancy and invalid bounds.
|
||||||
|
Seven Rust tests, strict all-target Clippy and five timing-adapter tests passed.
|
||||||
|
A retry must use a fresh output directory after the corrected evaluator is
|
||||||
|
frozen and the CPU inference slot is granted again; the failed attempt remains
|
||||||
|
preserved and has no quality score.
|
||||||
@@ -60,6 +60,18 @@ fn file_hash(path: &Path) -> Result<String> {
|
|||||||
}
|
}
|
||||||
Ok(format!("{:x}", state.finalize()))
|
Ok(format!("{:x}", state.finalize()))
|
||||||
}
|
}
|
||||||
|
fn validate_sample_coverage(samples: usize, duration_ms: u32) -> Result<()> {
|
||||||
|
let expected = duration_ms as usize * 16;
|
||||||
|
ensure!(
|
||||||
|
samples > 0
|
||||||
|
&& samples <= 480000
|
||||||
|
&& expected > 0
|
||||||
|
&& expected <= 480000
|
||||||
|
&& samples.abs_diff(expected) <= 16,
|
||||||
|
"Fixture source clock coverage differs beyond existing one-millisecond bound"
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
fn write_new(path: &Path, value: &Value) -> Result<()> {
|
fn write_new(path: &Path, value: &Value) -> Result<()> {
|
||||||
let mut file = fs::OpenOptions::new()
|
let mut file = fs::OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
@@ -174,16 +186,13 @@ fn run_case(
|
|||||||
let mut source_windows = Vec::new();
|
let mut source_windows = Vec::new();
|
||||||
for window in windows(metadata.audio_start_ms, metadata.audio_end_ms, max_windows)? {
|
for window in windows(metadata.audio_start_ms, metadata.audio_end_ms, max_windows)? {
|
||||||
let pcm = decode_audio_aligned(&assets.tools, &path, window, &limits)?;
|
let pcm = decode_audio_aligned(&assets.tools, &path, window, &limits)?;
|
||||||
ensure!(
|
validate_sample_coverage(pcm.len(), window.duration_ms)?;
|
||||||
pcm.len() == window.duration_ms as usize * 16,
|
|
||||||
"Fixture source clock coverage differs"
|
|
||||||
);
|
|
||||||
let sha = hash(
|
let sha = hash(
|
||||||
&pcm.iter()
|
&pcm.iter()
|
||||||
.flat_map(|value| value.to_le_bytes())
|
.flat_map(|value| value.to_le_bytes())
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
);
|
);
|
||||||
let record = json!({"asset":id,"start_ms":window.start_ms,"duration_ms":window.duration_ms,"samples":pcm.len(),"pcm_sha256":sha});
|
let record = json!({"asset":id,"start_ms":window.start_ms,"duration_ms":window.duration_ms,"samples":pcm.len(),"nominal_samples":window.duration_ms as usize*16,"coverage_difference_samples":pcm.len() as i64-i64::from(window.duration_ms)*16,"pcm_sha256":sha});
|
||||||
expected.entry(sha).or_default().push(record.clone());
|
expected.entry(sha).or_default().push(record.clone());
|
||||||
source_windows.push(record);
|
source_windows.push(record);
|
||||||
}
|
}
|
||||||
@@ -487,6 +496,13 @@ mod tests {
|
|||||||
assert!(values.iter().all(|window| window.duration_ms <= 30000));
|
assert!(values.iter().all(|window| window.duration_ms <= 30000));
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
|
fn fractional_millisecond_tail_preserves_real_samples() {
|
||||||
|
assert!(validate_sample_coverage(32618, 2039).is_ok());
|
||||||
|
assert!(validate_sample_coverage(32607, 2039).is_err());
|
||||||
|
assert!(validate_sample_coverage(0, 1).is_err());
|
||||||
|
assert!(validate_sample_coverage(480001, 30000).is_err());
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
#[ignore = "Requires the five hash-verified real media fixture files; no inference"]
|
#[ignore = "Requires the five hash-verified real media fixture files; no inference"]
|
||||||
fn timing_mode_preflight_checks_all_real_frozen_sources_without_models() -> Result<()> {
|
fn timing_mode_preflight_checks_all_real_frozen_sources_without_models() -> Result<()> {
|
||||||
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../../fixtures/media");
|
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../../fixtures/media");
|
||||||
|
|||||||
Reference in new issue
Block a user