devalang_wasm/engine/audio/effects/processors/
slice.rs

1use crate::engine::audio::effects::processors::super_trait::EffectProcessor;
2
3#[cfg(feature = "cli")]
4use rand::prelude::*;
5
6#[derive(Debug, Clone)]
7pub struct SliceProcessor {
8    pub segments: i32,
9    pub mode: String, // "sequential" | "random"
10    pub crossfade: f32,
11}
12
13impl SliceProcessor {
14    pub fn new(segments: i32, mode: &str, crossfade: f32) -> Self {
15        Self {
16            segments: segments.clamp(1, 16),
17            mode: mode.to_string(),
18            crossfade: crossfade.clamp(0.0, 1.0),
19        }
20    }
21}
22
23impl Default for SliceProcessor {
24    fn default() -> Self {
25        Self::new(4, "sequential", 0.01)
26    }
27}
28
29impl EffectProcessor for SliceProcessor {
30    fn process(&mut self, samples: &mut [f32], _sr: u32) {
31        let frames = samples.len() / 2;
32        let segs = self.segments.max(1) as usize;
33        let seg_len = (frames / segs).max(1);
34        let mut out = vec![0.0f32; frames * 2];
35        #[cfg_attr(not(feature = "cli"), allow(unused_mut))]
36        let mut order: Vec<usize> = (0..segs).collect();
37
38        #[cfg(feature = "cli")]
39        {
40            if self.mode == "random" {
41                order.shuffle(&mut thread_rng());
42            }
43        }
44
45        // Note: When compiled without "cli" feature (e.g., in plugins),
46        // the "random" mode falls back to "sequential"
47
48        let mut dst = 0usize;
49        for &s in order.iter() {
50            let start = s * seg_len;
51            let end = ((s + 1) * seg_len).min(frames);
52            for i in start..end {
53                let si = i * 2;
54                if dst < frames {
55                    let di = dst * 2;
56                    out[di] = samples[si];
57                    out[di + 1] = samples.get(si + 1).copied().unwrap_or(samples[si]);
58                    dst += 1;
59                }
60            }
61        }
62        // write back
63        for i in 0..frames {
64            let si = i * 2;
65            samples[si] = out[si];
66            if si + 1 < samples.len() {
67                samples[si + 1] = out[si + 1];
68            }
69        }
70    }
71    fn reset(&mut self) {}
72    fn name(&self) -> &str {
73        "Slice"
74    }
75}