devalang_wasm/engine/audio/effects/processors/
phaser.rs1use crate::engine::audio::effects::processors::super_trait::EffectProcessor;
2use std::f32::consts::PI;
3
4#[derive(Debug, Clone)]
5pub struct PhaserProcessor {
6 stages: usize,
7 rate: f32,
8 depth: f32,
9 feedback: f32,
10 mix: f32,
11 phase: f32,
12 allpass_states: Vec<[f32; 2]>, }
14
15impl PhaserProcessor {
16 pub fn new(stages: usize, rate: f32, depth: f32, feedback: f32, mix: f32) -> Self {
17 let stages = stages.clamp(2, 12);
18 Self {
19 stages,
20 rate: rate.clamp(0.1, 10.0),
21 depth: depth.clamp(0.0, 1.0),
22 feedback: feedback.clamp(0.0, 0.95),
23 mix: mix.clamp(0.0, 1.0),
24 phase: 0.0,
25 allpass_states: vec![[0.0, 0.0]; stages],
26 }
27 }
28}
29
30impl Default for PhaserProcessor {
31 fn default() -> Self {
32 Self::new(4, 0.5, 0.7, 0.5, 0.5)
33 }
34}
35
36impl EffectProcessor for PhaserProcessor {
37 fn process(&mut self, samples: &mut [f32], sample_rate: u32) {
38 for i in (0..samples.len()).step_by(2) {
39 self.phase += self.rate / sample_rate as f32;
41 if self.phase >= 1.0 {
42 self.phase -= 1.0;
43 }
44
45 let lfo = (2.0 * PI * self.phase).sin();
47 let coeff = self.depth * lfo * 0.95; for ch in 0..2 {
51 if i + ch < samples.len() {
52 let mut signal = samples[i + ch];
53
54 for stage in 0..self.stages {
56 let state = self.allpass_states[stage][ch];
57 let output = -signal + coeff * (signal - state);
58 self.allpass_states[stage][ch] = signal;
59 signal = output + state;
60 }
61
62 signal = signal * self.feedback;
64
65 samples[i + ch] = samples[i + ch] * (1.0 - self.mix) + signal * self.mix;
67 }
68 }
69 }
70 }
71
72 fn reset(&mut self) {
73 self.phase = 0.0;
74 for state in &mut self.allpass_states {
75 state[0] = 0.0;
76 state[1] = 0.0;
77 }
78 }
79
80 fn name(&self) -> &str {
81 "Phaser"
82 }
83}