#2104: document audio comparison and regression contracts

This commit is contained in:
FredApps committed 2026-11-10 13:36:17 +01:00
1 parent 31da676415
commit d047d89b9a
2 files changed
+8

No files matched your search

+1
View File
@@ -344,6 +344,7 @@ fn audio_changed(old: &Project, new: &Project, comp: ItemId) -> bool {
/// Each shared precomp is compared once per depth. A depth limit alone still visits an
/// exponentially large number of paths in a small graph of reused precomps, blocking the UI.
fn audio_changed_inner(old: &Project, new: &Project, comp: ItemId, seen: &mut HashSet<(ItemId, usize)>) -> bool {
/// Compare one comp and its reachable audio sources, without revisiting a shared path depth.
fn comps_differ(old: &Project, new: &Project, comp: ItemId, depth: usize, seen: &mut HashSet<(ItemId, usize)>) -> bool {
if depth >= 16 || !seen.insert((comp, depth)) {
return false;
+7
View File
@@ -34,6 +34,7 @@ impl FootageSource for Ramp {
}
}
/// Construct a paused feeder whose short nonzero span makes every source sample observable.
fn playback(footage: Arc<dyn FootageSource>) -> AudioPlayback {
let mut project = Project::default();
let f = Footage { path: "ramp.wav".into(), kind: FootageKind::Audio, has_audio: true, ..Default::default() };
@@ -64,16 +65,19 @@ fn playback(footage: Arc<dyn FootageSource>) -> AudioPlayback {
}
}
/// Run exactly one production feeder block, without a background refill racing assertions.
fn mix(p: &AudioPlayback) {
feed_block(&p.state, p.comp, &p.feed, &p.span, p.rate, p.mix);
}
/// Copy the active project and apply a layer edit through the same snapshot boundary as the UI.
fn edit(p: &AudioPlayback, update: impl FnOnce(&mut Layer)) -> Arc<Project> {
let mut project = p.project().unwrap();
update(&mut Arc::make_mut(&mut project).comp_mut(p.comp).unwrap().layers[0]);
project
}
/// Levels edits retain sample position across the loop boundary and the exclusive non-looping end.
#[test]
fn project_replacement_resumes_at_the_first_unconsumed_sample() {
for looping in [false, true] {
@@ -122,6 +126,7 @@ impl FootageSource for Gated {
}
}
/// A slow mix must not block edits or publish samples from the superseded project generation.
#[test]
fn a_block_in_flight_cannot_publish_after_a_mute() {
let (entered, waiting) = mpsc::channel();
@@ -151,6 +156,7 @@ impl ExprHost for OpacityLevels {
}
}
/// Video properties are irrelevant to a plain mix, but may be dependencies of audio expressions.
#[test]
fn video_edits_keep_the_queue_unless_audio_expressions_can_read_them() {
for expression in [false, true] {
@@ -180,6 +186,7 @@ fn video_edits_keep_the_queue_unless_audio_expressions_can_read_them() {
}
}
/// Reused nested comps cost linear visits while edits to their descendants remain detectable.
#[test]
fn shared_nested_comps_are_compared_once_per_depth() {
let mut project = Project::default();