devalang_wasm/engine/audio/effects/processors/
speed.rs1use crate::engine::audio::effects::processors::super_trait::EffectProcessor;
2
3#[derive(Debug, Clone)]
4pub struct SpeedProcessor {
5 speed: f32,
6 buffer: Vec<f32>,
7}
8
9impl SpeedProcessor {
10 pub fn new(speed: f32) -> Self {
11 let clamped = if speed.abs() < 0.0001 {
14 if speed.is_sign_negative() {
15 -0.0001
16 } else {
17 0.0001
18 }
19 } else {
20 speed
21 };
22
23 Self {
24 speed: clamped,
25 buffer: Vec::new(),
26 }
27 }
28}
29
30impl Default for SpeedProcessor {
31 fn default() -> Self {
32 Self::new(1.0)
33 }
34}
35
36impl EffectProcessor for SpeedProcessor {
37 fn process(&mut self, samples: &mut [f32], _sample_rate: u32) {
38 if (self.speed - 1.0).abs() < f32::EPSILON {
39 return; }
41
42 let original_len = samples.len();
43 let speed_abs = self.speed.abs();
44 let new_len = (original_len as f32 / speed_abs) as usize;
45
46 self.buffer.resize(new_len, 0.0);
48
49 if self.speed > 0.0 {
52 for i in 0..new_len {
53 let src_pos = i as f32 * self.speed;
54 let src_idx = src_pos.floor() as isize;
55 let frac = src_pos.fract();
56
57 if src_idx >= 0 && (src_idx as usize) + 1 < original_len {
58 let idx = src_idx as usize;
59 self.buffer[i] = samples[idx] * (1.0 - frac) + samples[idx + 1] * frac;
60 } else if src_idx >= 0 && (src_idx as usize) < original_len {
61 self.buffer[i] = samples[src_idx as usize];
62 } else {
63 self.buffer[i] = 0.0;
64 }
65 }
66 } else {
67 for i in 0..new_len {
69 let src_pos_from_end = i as f32 * speed_abs;
71 let src_pos = (original_len as f32 - 1.0) - src_pos_from_end;
73 if src_pos < 0.0 {
74 self.buffer[i] = 0.0;
75 continue;
76 }
77 let src_idx = src_pos.floor() as usize;
78 let frac = src_pos.fract();
79
80 if src_idx + 1 < original_len {
81 self.buffer[i] = samples[src_idx] * (1.0 - frac) + samples[src_idx + 1] * frac;
82 } else if src_idx < original_len {
83 self.buffer[i] = samples[src_idx];
84 } else {
85 self.buffer[i] = 0.0;
86 }
87 }
88 }
89
90 let copy_len = std::cmp::min(original_len, new_len);
93 samples[..copy_len].copy_from_slice(&self.buffer[..copy_len]);
94 if new_len < original_len {
95 for s in &mut samples[new_len..original_len] {
96 *s = 0.0;
97 }
98 }
99 }
100
101 fn reset(&mut self) {
102 self.buffer.clear();
103 }
104
105 fn name(&self) -> &str {
106 "Speed"
107 }
108}