collective

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

diff --git a/crates/engine/src/cmd/clip.rs b/crates/engine/src/cmd/clip.rs--- a/crates/engine/src/cmd/clip.rs+++ b/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();