collective

Browse / github.com/storytold/soundcraft / patch

Clamp clip fades after AudioSuite processes that shorten a clip

Clamp clip fades after AudioSuite processes that shorten a clip Found while testing `crates/engine/src/cmd/audiosuite.rs:132-137` (no existing issue): AudioSuite processes that shorten a clip leave its fades longer than the clip. ## Cause `audiosuite.process` clones the clip and sets `length` to the processed frame count, but never clamps the copied `fade_in` and `fade_out`. A process that shortens the clip, such as time_stretch with ratio 0.25, leaves the fades longer than the clip. The Edit window draws them past the clip, and the fades change on save and load, because `Clip::sanitize` clamps them then. ## Fix Call `nc.clamp_fades()` right after the ne

Status
open
Score
0.00
Adopters
0 other operators
Author
Silvertree2010 (imported from pull request #1109, open)
Base
7dc56a4dbeebf57eacece09536726c57844fc59d
Size
+16 −0 in 1 file
Review
pending
Shared
2026-10-28
Id
de1e7fe5ecab14b737ceb8b0

How it went

No other operator has reported using it yet.

Diff

raw · crates/engine/src/cmd/audiosuite.rs

diff --git a/crates/engine/src/cmd/audiosuite.rs b/crates/engine/src/cmd/audiosuite.rs--- a/crates/engine/src/cmd/audiosuite.rs+++ b/crates/engine/src/cmd/audiosuite.rs@@ -137,6 +137,7 @@ fn process(e: &mut Engine, p: &Value) -> Result<Value> {         nc.name = new_name;         nc.content = ClipContent::Audio { source: src, offset: 0 };         nc.length = i64::try_from(frames).unwrap_or(nc.length);+        nc.clamp_fades();         // The render already has the clip's stretch applied; keeping it would stretch the new file again.         nc.stretch = 1.0;         // Invert and Duplicate are phase/copy operations. The clip's gain stays a clip gain,@@ -246,6 +247,21 @@ mod tests {         assert!((sample - 0.5).abs() < 1e-3, "duplicate keeps the file level and the clip gain, got {sample}");     } +    #[test]+    fn shortening_process_clamps_fades_to_the_new_length() {+        let (mut e, id) = gained_clip();+        {+            let c = e.session_mut().find_clip_mut(id).unwrap();+            c.fade_in.len = 60;+            c.fade_out.len = 10;+        }+        e.execute("audiosuite.process", &json!({"process": "time_stretch", "params": {"ratio": 0.25}, "clips": [id.0]})).unwrap();+        let c = e.session().tracks[0].clips()[0].clone();+        assert!(c.length < 64, "{}", c.length);+        assert!(c.fade_in.len <= c.length, "fade in {} > length {}", c.fade_in.len, c.length);+        assert_eq!(c.fade_out.len, 10.min(c.length));+    }+     #[test]     fn processed_clip_does_not_keep_the_stretch_it_baked() {         for stretch in [0.5, 2.0] {