1use std::collections::VecDeque;
2
3#[derive(Debug, Clone)]
4pub struct ReverbParams {
5 pub room_size: f32,
6 pub damping: f32,
7 pub wet: f32,
8 pub width: f32,
9}
10
11impl Default for ReverbParams {
12 fn default() -> Self {
13 ReverbParams {
14 room_size: 0.5,
15 damping: 0.5,
16 wet: 0.3,
17 width: 1.0,
18 }
19 }
20}
21
22#[derive(Debug, Clone)]
23pub struct DelayParams {
24 pub time: f32,
25 pub feedback: f32,
26 pub wet: f32,
27}
28
29impl Default for DelayParams {
30 fn default() -> Self {
31 DelayParams {
32 time: 0.25,
33 feedback: 0.4,
34 wet: 0.3,
35 }
36 }
37}
38
39#[derive(Debug, Clone)]
40pub struct DistortionParams {
41 pub drive: f32,
42 pub tone: f32,
43 pub wet: f32,
44}
45
46impl Default for DistortionParams {
47 fn default() -> Self {
48 DistortionParams {
49 drive: 2.0,
50 tone: 0.7,
51 wet: 0.5,
52 }
53 }
54}
55
56#[derive(Debug, Clone)]
57pub struct FilterParams {
58 pub cutoff: f32, pub resonance: f32, pub filter_type: FilterType,
61}
62
63#[derive(Debug, Clone, Copy, PartialEq)]
64pub enum FilterType {
65 LowPass,
66 HighPass,
67 BandPass,
68}
69
70#[derive(Debug, Clone)]
71pub struct EffectsChain {
72 pub reverb: Option<ReverbParams>,
73 pub delay: Option<DelayParams>,
74 pub distortion: Option<DistortionParams>,
75 pub filter: Option<FilterParams>,
76}
77
78impl EffectsChain {
79 pub fn has_any(&self) -> bool {
80 self.reverb.is_some() || self.delay.is_some() || self.distortion.is_some() || self.filter.is_some()
81 }
82}
83
84
85impl Default for EffectsChain {
86 fn default() -> Self {
87 EffectsChain {
88 reverb: None,
89 delay: None,
90 distortion: None,
91 filter: None,
92 }
93 }
94}
95
96pub struct EffectsProcessor {
97 sample_rate: f32,
98 comb_buffers: Vec<VecDeque<f32>>,
99 comb_filter_state: Vec<f32>,
100 allpass_buffers: Vec<VecDeque<f32>>,
101 delay_buffer: VecDeque<f32>,
102 lowpass_state: f32,
103 filter_state: (f32, f32), }
105
106impl EffectsProcessor {
107 pub fn new(sample_rate: f32) -> Self {
108 let scale = sample_rate / 44100.0;
109 let comb_delays = vec![ (1116.0 * scale) as usize,
111 (1188.0 * scale) as usize,
112 (1277.0 * scale) as usize,
113 (1356.0 * scale) as usize,
114 (1422.0 * scale) as usize,
115 (1491.0 * scale) as usize,
116 (1557.0 * scale) as usize,
117 (1617.0 * scale) as usize,
118 ];
119
120 let allpass_delays = vec![
121 (556.0 * scale) as usize,
122 (441.0 * scale) as usize,
123 (341.0 * scale) as usize,
124 (225.0 * scale) as usize,
125 ];
126
127 EffectsProcessor {
128 sample_rate,
129 comb_buffers: comb_delays.iter()
130 .map(|&size| VecDeque::from(vec![0.0; size]))
131 .collect(),
132 comb_filter_state: vec![0.0; 8],
133 allpass_buffers: allpass_delays.iter()
134 .map(|&size| VecDeque::from(vec![0.0; size]))
135 .collect(),
136 delay_buffer: VecDeque::from(vec![0.0; (sample_rate * 2.0) as usize]),
137 lowpass_state: 0.0,
138 filter_state: (0.0, 0.0),
139 }
140 }
141
142 pub fn process(&mut self, input: f32, effects: &EffectsChain) -> f32 {
143 let mut output = input;
144
145 if let Some(filter) = &effects.filter {
147 output = self.apply_filter(output, filter);
148 }
149
150 if let Some(dist) = &effects.distortion {
151 output = self.apply_distortion(output, dist);
152 }
153
154 if let Some(delay) = &effects.delay {
155 output = self.apply_delay(output, delay);
156 }
157
158 if let Some(reverb) = &effects.reverb {
159 output = self.apply_reverb(output, reverb);
160 }
161
162 output
163 }
164
165 fn apply_filter(&mut self, input: f32, params: &FilterParams) -> f32 {
167 let omega = std::f32::consts::TAU * params.cutoff / self.sample_rate;
168 let alpha = omega.sin() * params.resonance;
169
170 let (b0, b1, b2, a0, a1, a2) = match params.filter_type {
172 FilterType::LowPass => {
173 let cos_omega = omega.cos();
174 (
175 (1.0 - cos_omega) / 2.0,
176 1.0 - cos_omega,
177 (1.0 - cos_omega) / 2.0,
178 1.0 + alpha,
179 -2.0 * cos_omega,
180 1.0 - alpha,
181 )
182 }
183 FilterType::HighPass => {
184 let cos_omega = omega.cos();
185 (
186 (1.0 + cos_omega) / 2.0,
187 -(1.0 + cos_omega),
188 (1.0 + cos_omega) / 2.0,
189 1.0 + alpha,
190 -2.0 * cos_omega,
191 1.0 - alpha,
192 )
193 }
194 FilterType::BandPass => {
195 let cos_omega = omega.cos();
196 (
197 alpha,
198 0.0,
199 -alpha,
200 1.0 + alpha,
201 -2.0 * cos_omega,
202 1.0 - alpha,
203 )
204 }
205 };
206
207 let output = (b0 * input + b1 * self.filter_state.0 + b2 * self.filter_state.1
209 - a1 * self.filter_state.0 - a2 * self.filter_state.1) / a0;
210
211 self.filter_state.1 = self.filter_state.0;
212 self.filter_state.0 = output;
213
214 output
215 }
216
217 fn apply_distortion(&mut self, input: f32, params: &DistortionParams) -> f32 {
218 let driven = input * params.drive;
219 let distorted = if driven > 1.0 {
220 2.0 / 3.0
221 } else if driven < -1.0 {
222 -2.0 / 3.0
223 } else {
224 driven - (driven.powi(3) / 3.0)
225 };
226
227 let alpha = 1.0 - params.tone;
228 self.lowpass_state = self.lowpass_state * alpha + distorted * (1.0 - alpha);
229
230 input * (1.0 - params.wet) + self.lowpass_state * params.wet
231 }
232
233 fn apply_delay(&mut self, input: f32, params: &DelayParams) -> f32 {
234 let delay_samples = (params.time * self.sample_rate) as usize;
235 let delay_samples = delay_samples.min(self.delay_buffer.len() - 1);
236
237 let delayed = self.delay_buffer[delay_samples];
238
239 Self::cycle_buffer(&mut self.delay_buffer, input + delayed * params.feedback);
240
241 input * (1.0 - params.wet) + delayed * params.wet
242 }
243
244 fn apply_reverb(&mut self, input: f32, params: &ReverbParams) -> f32 {
245 let mut output = 0.0;
246
247 for i in 0..8 {
248 let delayed = self.comb_buffers[i].back().copied().unwrap_or(0.0);
249
250 self.comb_filter_state[i] = delayed * (1.0 - params.damping) +
251 self.comb_filter_state[i] * params.damping;
252
253 let feedback = self.comb_filter_state[i] * params.room_size;
254
255 Self::cycle_buffer(&mut self.comb_buffers[i], input + feedback);
256
257 output += delayed;
258 }
259
260 output /= 8.0;
261
262 for buffer in &mut self.allpass_buffers {
263 let delayed = buffer.back().copied().unwrap_or(0.0);
264 let new_val = output + delayed * 0.5;
265 Self::cycle_buffer(buffer, new_val);
266 output = delayed - output * 0.5;
267 }
268
269 input * (1.0 - params.wet) + output * params.wet
270 }
271
272 #[inline]
273 fn cycle_buffer(buffer: &mut VecDeque<f32>, new_value: f32) {
274 buffer.pop_back();
275 buffer.push_front(new_value);
276 }
277}