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

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