proteus_lib/dsp/effects/basic_reverb/
mod.rs1use log::info;
4use serde::{Deserialize, Serialize};
5
6use super::EffectContext;
7
8const DEFAULT_DURATION_MS: u64 = 100;
9const MAX_AMPLITUDE: f32 = 0.8;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12#[serde(default)]
13pub struct DelayReverbSettings {
14 pub duration_ms: u64,
15 pub amplitude: f32,
16}
17
18impl DelayReverbSettings {
19 pub fn new(duration_ms: u64, amplitude: f32) -> Self {
20 Self {
21 duration_ms: duration_ms.clamp(0, u64::MAX),
22 amplitude: amplitude.clamp(0.0, MAX_AMPLITUDE),
23 }
24 }
25
26 fn amplitude(&self) -> f32 {
27 self.amplitude.clamp(0.0, MAX_AMPLITUDE)
28 }
29}
30
31impl Default for DelayReverbSettings {
32 fn default() -> Self {
33 Self {
34 duration_ms: DEFAULT_DURATION_MS,
35 amplitude: 0.7,
36 }
37 }
38}
39
40#[derive(Clone, Serialize, Deserialize)]
42#[serde(default)]
43pub struct DelayReverbEffect {
44 pub enabled: bool,
45 #[serde(alias = "dry_wet", alias = "wet_dry")]
46 pub mix: f32,
47 #[serde(flatten)]
48 pub settings: DelayReverbSettings,
49 #[serde(skip)]
50 state: Option<DelayReverbState>,
51}
52
53impl Default for DelayReverbEffect {
54 fn default() -> Self {
55 Self {
56 enabled: true,
57 mix: 0.0,
58 settings: DelayReverbSettings::default(),
59 state: None,
60 }
61 }
62}
63
64impl std::fmt::Debug for DelayReverbEffect {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 f.debug_struct("DelayReverbEffect")
67 .field("enabled", &self.enabled)
68 .field("mix", &self.mix)
69 .field("settings", &self.settings)
70 .finish()
71 }
72}
73
74impl DelayReverbEffect {
75 pub fn new(mix: f32) -> Self {
77 Self {
78 mix: mix.clamp(0.0, 1.0),
79 ..Default::default()
80 }
81 }
82
83 pub fn process(&mut self, samples: &[f32], context: &EffectContext, _drain: bool) -> Vec<f32> {
85 self.ensure_state(context);
86 if !self.enabled || self.mix <= 0.0 {
87 return samples.to_vec();
88 }
89
90 let Some(state) = self.state.as_mut() else {
91 return samples.to_vec();
92 };
93
94 let amplitude = if self.mix > 0.0 {
95 self.mix.clamp(0.0, MAX_AMPLITUDE)
96 } else {
97 self.settings.amplitude()
98 };
99
100 if samples.is_empty() {
101 if _drain {
102 return state.drain_tail(amplitude);
103 }
104 return Vec::new();
105 }
106
107 let mut output = Vec::with_capacity(samples.len());
108 state.process_samples(samples, amplitude, &mut output);
109 output
110 }
111
112 pub fn reset_state(&mut self) {
114 if let Some(state) = self.state.as_mut() {
115 state.reset();
116 }
117 self.state = None;
118 }
119
120 pub fn settings_mut(&mut self) -> &mut DelayReverbSettings {
122 &mut self.settings
123 }
124
125 fn ensure_state(&mut self, context: &EffectContext) {
126 let delay_samples = delay_samples(
127 context.sample_rate,
128 context.channels,
129 self.settings.duration_ms,
130 );
131 let needs_reset = self
132 .state
133 .as_ref()
134 .map(|state| state.delay_samples != delay_samples)
135 .unwrap_or(true);
136 if needs_reset {
137 self.state = Some(DelayReverbState::new(delay_samples));
138 }
139 }
140}
141
142#[derive(Clone)]
143struct DelayReverbState {
144 delay_samples: usize,
145 delay_line: Vec<f32>,
146 write_pos: usize,
147}
148
149impl DelayReverbState {
150 fn new(delay_samples: usize) -> Self {
151 info!("Using Delay Reverb!");
152 Self {
153 delay_samples,
154 delay_line: vec![0.0; delay_samples.max(1)],
155 write_pos: 0,
156 }
157 }
158
159 fn reset(&mut self) {
160 self.delay_line.fill(0.0);
161 self.write_pos = 0;
162 }
163
164 fn process_samples(&mut self, samples: &[f32], amplitude: f32, out: &mut Vec<f32>) {
165 if self.delay_samples == 0 {
166 out.extend_from_slice(samples);
167 return;
168 }
169
170 let delay_len = self.delay_line.len();
171 for &sample in samples {
172 let delayed = self.delay_line[self.write_pos];
173 let output = sample + (delayed * amplitude);
174 out.push(output);
175
176 self.delay_line[self.write_pos] = sample + (delayed * amplitude);
178 self.write_pos += 1;
179 if self.write_pos >= delay_len {
180 self.write_pos = 0;
181 }
182 }
183 }
184
185 fn drain_tail(&mut self, amplitude: f32) -> Vec<f32> {
186 if self.delay_samples == 0 {
187 return Vec::new();
188 }
189
190 let delay_len = self.delay_line.len();
191 let mut out = Vec::with_capacity(delay_len);
192 for _ in 0..delay_len {
193 let delayed = self.delay_line[self.write_pos];
194 let output = delayed * amplitude;
195 out.push(output);
196
197 self.delay_line[self.write_pos] = delayed * amplitude;
199 self.write_pos += 1;
200 if self.write_pos >= delay_len {
201 self.write_pos = 0;
202 }
203 }
204
205 out
206 }
207}
208
209fn delay_samples(sample_rate: u32, channels: usize, duration_ms: u64) -> usize {
210 if duration_ms == 0 {
211 return 0;
212 }
213 let ns = duration_ms.saturating_mul(1_000_000);
214 let samples = ns.saturating_mul(sample_rate as u64) / 1_000_000_000 * channels as u64;
215 samples as usize
216}
217
218#[deprecated(note = "Use DelayReverbSettings instead.")]
219pub type BasicReverbSettings = DelayReverbSettings;
220
221#[deprecated(note = "Use DelayReverbEffect instead.")]
222pub type BasicReverbEffect = DelayReverbEffect;