Browse / github.com/storytold/soundcraft / patch
Clamp clip fades after elastic warp and remove warp
Clamp clip fades after elastic warp and remove warp Found while testing `crates/engine/src/cmd/clip.rs:217-231 (elastic), also :249 (remove_warp)` (no existing issue): Elastic warp to a shorter length leaves clip fades longer than the clip. ## Cause `clip.elastic_properties` set the new clip length without clamping `fade_in` and `fade_out`, so a warp to a shorter length left fades longer than the clip. `clip.remove_warp` restored the original length but clamped only `fade_out`, not `fade_in`. ## Fix Both paths now call `Clip::clamp_fades()` after the length is set. This replaces the `fade_out`-only clamp in `remove_warp`. A regression test co
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- Silvertree2010 (imported from pull request #1123, open)
- Base
7dc56a4dbeebf57eacece09536726c57844fc59d- Size
- +23 −1 in 1 file
- Review
- pending
- Shared
- 2026-10-28
- Id
e82a80392cbc3d7a8318f46b
How it went
No other operator has reported using it yet.
Diff
raw · crates/engine/src/cmd/clip.rs
@@ -228,6 +228,7 @@ fn elastic(e: &mut Engine, p: &Value) -> Result<Value> { nc.content = soundcraft_model::ClipContent::Audio { source: src, offset: 0 }; nc.length = out_len; nc.stretch = 1.0;+ nc.clamp_fades(); super::more_util::replace_clip(s, t, *id, nc); rendered += 1; }@@ -246,7 +247,7 @@ fn remove_warp(e: &mut Engine, p: &Value) -> Result<Value> { if let Some((src, off, len)) = orig { c.content = soundcraft_model::ClipContent::Audio { source: src, offset: off }; c.length = len.max(1);- c.fade_out.len = c.fade_out.len.min(c.length);+ c.clamp_fades(); n += 1; } }@@ -496,6 +497,27 @@ mod tests { } } + #[test]+ fn warping_and_unwarping_keep_fades_within_the_clip() {+ let (mut e, _, cid) = elastic_clip(20_000, 10_000, 20_000);+ if let Some(c) = e.session_mut().find_clip_mut(cid) {+ c.fade_in.len = 20_000;+ c.fade_out.len = 20_000;+ }+ e.execute("clip.elastic_properties", &json!({"clips": [cid.0], "ratio": 0.5})).unwrap();+ let c = e.session().find_clip(cid).unwrap().1.clone();+ assert!(c.fade_in.len <= c.length && c.fade_out.len <= c.length, "{} {} {}", c.length, c.fade_in.len, c.fade_out.len);++ let (mut e, _, cid) = elastic_clip(20_000, 10_000, 20_000);+ e.execute("clip.elastic_properties", &json!({"clips": [cid.0], "ratio": 2.0})).unwrap();+ if let Some(c) = e.session_mut().find_clip_mut(cid) {+ c.fade_in.len = 40_000;+ }+ e.execute("clip.remove_warp", &json!({"clips": [cid.0]})).unwrap();+ let c = e.session().find_clip(cid).unwrap().1.clone();+ assert!(c.fade_in.len <= c.length, "{} {}", c.length, c.fade_in.len);+ }+ #[test] fn remove_warp_keeps_the_audio_when_the_original_file_is_gone() { let mut e = crate::demo::demo_engine();