diff --git a/contributors/people.toml b/contributors/people.toml index bc8bd31c..3144370c 100644 --- a/contributors/people.toml +++ b/contributors/people.toml @@ -40,3 +40,6 @@ sync_github_name = true real_name = "Vikram Bhaskaran" display_name = "Vikram Bhaskaran" sync_github_name = false + +[people.webdevtodayjason] +display_name = "Jason Brashear" diff --git a/crates/model/src/clip.rs b/crates/model/src/clip.rs index 4d30bea1..322d375e 100644 --- a/crates/model/src/clip.rs +++ b/crates/model/src/clip.rs @@ -215,7 +215,12 @@ impl Clip { self.length -= delta; self.start = new_start; self.clamp_fades(); - self.gain_env = self.gain_env.iter().filter_map(|&(t, v)| (t - delta >= 0).then_some((t - delta, v))).collect(); + // Keep the gain at the cut when earlier breakpoints are dropped. + if self.gain_env.iter().any(|&(t, _)| t < delta) && self.gain_env.iter().all(|&(t, _)| t != delta) { + self.gain_env.insert(0, (delta, env_value(&self.gain_env, delta))); + } + self.gain_env.retain(|&(t, _)| t >= delta); + self.gain_env.iter_mut().for_each(|(t, _)| *t = t.saturating_sub(delta)); } /// Move the end edge to `new_end`. @@ -282,6 +287,27 @@ mod tests { assert!((c.gain_at(500) - db_to_gain(-10.0)).abs() < 1e-4); } + #[test] + fn trim_start_keeps_gain_envelope_at_cut() { + for (env, cut, expected) in [ + (vec![(0, 0.0), (1000, -20.0)], 500, vec![(0, -10.0), (500, -20.0)]), + (vec![(0, 0.0), (100, -20.0)], 500, vec![(0, -20.0)]), + (vec![(0, 0.0), (500, -10.0), (1000, -20.0)], 500, vec![(0, -10.0), (500, -20.0)]), + (vec![], 500, vec![]), + (vec![(100, -3.0)], 0, vec![(100, -3.0)]), + (vec![(100, -3.0)], -100, vec![(200, -3.0)]), + ] { + let mut clip = Clip::audio(ClipId(1), "a", SourceId(1), 100, 0, 1000); + clip.gain_env = env; + let gain_at_cut = clip.gain_at(cut); + clip.trim_start_to(cut); + assert_eq!(clip.gain_env, expected); + if cut > 0 { + assert!((clip.gain_at(0) - gain_at_cut).abs() < 1e-6); + } + } + } + #[test] fn trims_keep_material_anchored() { let mut c = Clip::audio(ClipId(1), "a", SourceId(1), 1000, 100, 1000);