devalang_wasm/engine/audio/effects/processors/
reverb.rs1use crate::engine::audio::effects::processors::super_trait::EffectProcessor;
2use std::fmt::Debug;
3
4#[derive(Debug, Clone)]
5pub struct ReverbProcessor {
6 room_size: f32,
7 damping: f32,
8 mix: f32,
9 decay: f32,
10 comb_buffers: Vec<Vec<f32>>,
12 comb_positions: Vec<usize>,
13 comb_feedback: Vec<f32>,
14 allpass_buffers: Vec<Vec<f32>>,
16 allpass_positions: Vec<usize>,
17}
18
19impl ReverbProcessor {
20 pub fn new(room_size: f32, damping: f32, decay: f32, mix: f32) -> Self {
21 let room_size = room_size.clamp(0.0, 1.0);
22 let damping = damping.clamp(0.0, 1.0);
23 let decay = decay.clamp(0.0, 2.0);
24
25 let comb_delays = [1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617];
27 let mut comb_buffers = Vec::new();
28 let mut comb_feedback = Vec::new();
29
30 for &delay in &comb_delays {
31 comb_buffers.push(vec![0.0; delay]);
32 let base = 0.78 + room_size * 0.14; let mult = 0.6 + decay * 0.2; let mut fb = base * mult;
36 if fb >= 0.995 {
37 fb = 0.995;
38 }
39 comb_feedback.push(fb);
40 }
41
42 let allpass_delays = [556, 441, 341, 225];
44 let mut allpass_buffers = Vec::new();
45
46 for &delay in &allpass_delays {
47 allpass_buffers.push(vec![0.0; delay]);
48 }
49
50 Self {
51 room_size,
52 damping,
53 mix: mix.clamp(0.0, 1.0),
54 decay,
55 comb_buffers,
56 comb_positions: vec![0; 8],
57 comb_feedback,
58 allpass_buffers,
59 allpass_positions: vec![0; 4],
60 }
61 }
62}
63
64impl Default for ReverbProcessor {
65 fn default() -> Self {
66 Self::new(0.5, 0.5, 0.5, 0.3)
67 }
68}
69
70impl EffectProcessor for ReverbProcessor {
71 fn process(&mut self, samples: &mut [f32], _sample_rate: u32) {
72 for i in 0..samples.len() {
73 let input = samples[i];
74 let mut output = 0.0;
75
76 for (j, buffer) in self.comb_buffers.iter_mut().enumerate() {
78 let pos = self.comb_positions[j];
79 let delayed = buffer[pos];
80
81 let filtered = delayed * (1.0 - self.damping);
83 buffer[pos] = input + filtered * self.comb_feedback[j];
84
85 output += delayed;
87
88 self.comb_positions[j] = (pos + 1) % buffer.len();
89 }
90
91 output /= self.comb_buffers.len() as f32;
92
93 for (j, buffer) in self.allpass_buffers.iter_mut().enumerate() {
95 let pos = self.allpass_positions[j];
96 let delayed = buffer[pos];
97
98 buffer[pos] = output + delayed * 0.5;
99 output = delayed - output * 0.5;
100
101 self.allpass_positions[j] = (pos + 1) % buffer.len();
102 }
103
104 samples[i] = input * (1.0 - self.mix) + output * self.mix;
106 }
107 }
108
109 fn reset(&mut self) {
110 for buffer in &mut self.comb_buffers {
111 buffer.fill(0.0);
112 }
113 for buffer in &mut self.allpass_buffers {
114 buffer.fill(0.0);
115 }
116 self.comb_positions.fill(0);
117 self.allpass_positions.fill(0);
118 }
119
120 fn name(&self) -> &str {
121 "Reverb"
122 }
123}