devalang_wasm/engine/audio/effects/processors/
gate.rs1use crate::engine::audio::effects::processors::super_trait::EffectProcessor;
2
3#[derive(Debug, Clone)]
5pub struct GateProcessor {
6 threshold: f32,
7 attack: f32,
8 release: f32,
9 envelope: f32,
10}
11
12impl GateProcessor {
13 pub fn new(threshold: f32, attack: f32, release: f32) -> Self {
14 Self {
15 threshold,
16 attack: attack.max(0.001),
17 release: release.max(0.001),
18 envelope: 0.0,
19 }
20 }
21}
22
23impl Default for GateProcessor {
24 fn default() -> Self {
25 Self::new(-30.0, 0.001, 0.05)
26 }
27}
28
29impl EffectProcessor for GateProcessor {
30 fn process(&mut self, samples: &mut [f32], sample_rate: u32) {
31 let attack_coeff = (-1.0 / (self.attack * sample_rate as f32)).exp();
32 let release_coeff = (-1.0 / (self.release * sample_rate as f32)).exp();
33
34 for i in (0..samples.len()).step_by(2) {
35 let left = samples[i];
37 let right = if i + 1 < samples.len() {
38 samples[i + 1]
39 } else {
40 left
41 };
42 let rms = ((left * left + right * right) / 2.0).sqrt();
43
44 let db = if rms > 0.0001 {
46 20.0 * rms.log10()
47 } else {
48 -100.0
49 };
50
51 let target = if db > self.threshold {
53 0.0 } else {
55 -100.0 };
57
58 let coeff = if target > self.envelope {
59 attack_coeff
60 } else {
61 release_coeff
62 };
63
64 self.envelope = target + coeff * (self.envelope - target);
65
66 let gain = 10.0_f32.powf(self.envelope / 20.0);
68
69 samples[i] *= gain;
71 if i + 1 < samples.len() {
72 samples[i + 1] *= gain;
73 }
74 }
75 }
76
77 fn reset(&mut self) {
78 self.envelope = 0.0;
79 }
80
81 fn name(&self) -> &str {
82 "Gate"
83 }
84}