1use std::f32::consts::PI;
3
4pub trait EffectProcessor: Send + std::fmt::Debug {
6 fn process(&mut self, samples: &mut [f32], sample_rate: u32);
8
9 fn reset(&mut self);
11
12 fn name(&self) -> &str;
14}
15
16#[derive(Debug)]
18pub struct ChorusProcessor {
19 depth: f32,
20 rate: f32,
21 mix: f32,
22 phase: f32,
23 delay_buffer: Vec<f32>,
24 buffer_pos: usize,
25}
26
27impl ChorusProcessor {
28 pub fn new(depth: f32, rate: f32, mix: f32) -> Self {
29 Self {
30 depth: depth.clamp(0.0, 1.0),
31 rate: rate.clamp(0.1, 10.0),
32 mix: mix.clamp(0.0, 1.0),
33 phase: 0.0,
34 delay_buffer: vec![0.0; 8820], buffer_pos: 0,
36 }
37 }
38}
39
40impl Default for ChorusProcessor {
41 fn default() -> Self {
42 Self::new(0.7, 0.5, 0.5)
43 }
44}
45
46impl EffectProcessor for ChorusProcessor {
47 fn process(&mut self, samples: &mut [f32], sample_rate: u32) {
48 let max_delay_samples = (0.020 * sample_rate as f32) as usize; for i in (0..samples.len()).step_by(2) {
51 self.phase += self.rate / sample_rate as f32;
53 if self.phase >= 1.0 {
54 self.phase -= 1.0;
55 }
56
57 let lfo = (2.0 * PI * self.phase).sin();
59 let delay_samples =
60 (self.depth * max_delay_samples as f32 * (lfo + 1.0) / 2.0) as usize;
61 let delay_samples = delay_samples.min(self.delay_buffer.len() - 1);
62
63 for ch in 0..2 {
65 if i + ch < samples.len() {
66 let input = samples[i + ch];
67
68 self.delay_buffer[self.buffer_pos] = input;
70
71 let read_pos = (self.buffer_pos + self.delay_buffer.len() - delay_samples)
73 % self.delay_buffer.len();
74 let delayed = self.delay_buffer[read_pos];
75
76 samples[i + ch] = input * (1.0 - self.mix) + delayed * self.mix;
78 }
79 }
80
81 self.buffer_pos = (self.buffer_pos + 1) % self.delay_buffer.len();
82 }
83 }
84
85 fn reset(&mut self) {
86 self.phase = 0.0;
87 self.delay_buffer.fill(0.0);
88 self.buffer_pos = 0;
89 }
90
91 fn name(&self) -> &str {
92 "Chorus"
93 }
94}
95
96#[derive(Debug)]
98pub struct FlangerProcessor {
99 depth: f32,
100 rate: f32,
101 feedback: f32,
102 mix: f32,
103 phase: f32,
104 delay_buffer: Vec<f32>,
105 buffer_pos: usize,
106}
107
108impl FlangerProcessor {
109 pub fn new(depth: f32, rate: f32, feedback: f32, mix: f32) -> Self {
110 Self {
111 depth: depth.clamp(0.0, 1.0),
112 rate: rate.clamp(0.1, 10.0),
113 feedback: feedback.clamp(0.0, 0.95),
114 mix: mix.clamp(0.0, 1.0),
115 phase: 0.0,
116 delay_buffer: vec![0.0; 882], buffer_pos: 0,
118 }
119 }
120}
121
122impl Default for FlangerProcessor {
123 fn default() -> Self {
124 Self::new(0.7, 0.5, 0.5, 0.5)
125 }
126}
127
128impl EffectProcessor for FlangerProcessor {
129 fn process(&mut self, samples: &mut [f32], sample_rate: u32) {
130 let max_delay_samples = (0.010 * sample_rate as f32) as usize; for i in (0..samples.len()).step_by(2) {
133 self.phase += self.rate / sample_rate as f32;
135 if self.phase >= 1.0 {
136 self.phase -= 1.0;
137 }
138
139 let lfo = (2.0 * PI * self.phase).sin();
141 let delay_samples =
142 (self.depth * max_delay_samples as f32 * (lfo + 1.0) / 2.0) as usize;
143 let delay_samples = delay_samples.min(self.delay_buffer.len() - 1);
144
145 for ch in 0..2 {
147 if i + ch < samples.len() {
148 let input = samples[i + ch];
149
150 let read_pos = (self.buffer_pos + self.delay_buffer.len() - delay_samples)
152 % self.delay_buffer.len();
153 let delayed = self.delay_buffer[read_pos];
154
155 let output = input + delayed * self.feedback;
157
158 self.delay_buffer[self.buffer_pos] = output;
160
161 samples[i + ch] = input * (1.0 - self.mix) + delayed * self.mix;
163 }
164 }
165
166 self.buffer_pos = (self.buffer_pos + 1) % self.delay_buffer.len();
167 }
168 }
169
170 fn reset(&mut self) {
171 self.phase = 0.0;
172 self.delay_buffer.fill(0.0);
173 self.buffer_pos = 0;
174 }
175
176 fn name(&self) -> &str {
177 "Flanger"
178 }
179}
180
181#[derive(Debug)]
183pub struct PhaserProcessor {
184 stages: usize,
185 rate: f32,
186 depth: f32,
187 feedback: f32,
188 mix: f32,
189 phase: f32,
190 allpass_states: Vec<[f32; 2]>, }
192
193impl PhaserProcessor {
194 pub fn new(stages: usize, rate: f32, depth: f32, feedback: f32, mix: f32) -> Self {
195 let stages = stages.clamp(2, 12);
196 Self {
197 stages,
198 rate: rate.clamp(0.1, 10.0),
199 depth: depth.clamp(0.0, 1.0),
200 feedback: feedback.clamp(0.0, 0.95),
201 mix: mix.clamp(0.0, 1.0),
202 phase: 0.0,
203 allpass_states: vec![[0.0, 0.0]; stages],
204 }
205 }
206}
207
208impl Default for PhaserProcessor {
209 fn default() -> Self {
210 Self::new(4, 0.5, 0.7, 0.5, 0.5)
211 }
212}
213
214impl EffectProcessor for PhaserProcessor {
215 fn process(&mut self, samples: &mut [f32], sample_rate: u32) {
216 for i in (0..samples.len()).step_by(2) {
217 self.phase += self.rate / sample_rate as f32;
219 if self.phase >= 1.0 {
220 self.phase -= 1.0;
221 }
222
223 let lfo = (2.0 * PI * self.phase).sin();
225 let coeff = self.depth * lfo * 0.95; for ch in 0..2 {
229 if i + ch < samples.len() {
230 let mut signal = samples[i + ch];
231
232 for stage in 0..self.stages {
234 let state = self.allpass_states[stage][ch];
235 let output = -signal + coeff * (signal - state);
236 self.allpass_states[stage][ch] = signal;
237 signal = output + state;
238 }
239
240 signal = signal * self.feedback;
242
243 samples[i + ch] = samples[i + ch] * (1.0 - self.mix) + signal * self.mix;
245 }
246 }
247 }
248 }
249
250 fn reset(&mut self) {
251 self.phase = 0.0;
252 for state in &mut self.allpass_states {
253 state[0] = 0.0;
254 state[1] = 0.0;
255 }
256 }
257
258 fn name(&self) -> &str {
259 "Phaser"
260 }
261}
262
263#[derive(Debug)]
265pub struct CompressorProcessor {
266 threshold: f32,
267 ratio: f32,
268 attack: f32,
269 release: f32,
270 envelope: f32,
271}
272
273impl CompressorProcessor {
274 pub fn new(threshold: f32, ratio: f32, attack: f32, release: f32) -> Self {
275 Self {
276 threshold,
277 ratio: ratio.max(1.0),
278 attack: attack.max(0.001),
279 release: release.max(0.001),
280 envelope: 0.0,
281 }
282 }
283}
284
285impl Default for CompressorProcessor {
286 fn default() -> Self {
287 Self::new(-20.0, 4.0, 0.005, 0.1)
288 }
289}
290
291impl EffectProcessor for CompressorProcessor {
292 fn process(&mut self, samples: &mut [f32], sample_rate: u32) {
293 let attack_coeff = (-1.0 / (self.attack * sample_rate as f32)).exp();
294 let release_coeff = (-1.0 / (self.release * sample_rate as f32)).exp();
295
296 for i in (0..samples.len()).step_by(2) {
297 let left = samples[i];
299 let right = if i + 1 < samples.len() {
300 samples[i + 1]
301 } else {
302 left
303 };
304 let rms = ((left * left + right * right) / 2.0).sqrt();
305
306 let db = if rms > 0.0001 {
308 20.0 * rms.log10()
309 } else {
310 -100.0
311 };
312
313 let target = if db > self.threshold {
315 self.threshold + (db - self.threshold) / self.ratio
316 } else {
317 db
318 };
319
320 let coeff = if target > self.envelope {
321 attack_coeff
322 } else {
323 release_coeff
324 };
325
326 self.envelope = target + coeff * (self.envelope - target);
327
328 let gain_db = self.envelope - db;
330 let gain = 10.0_f32.powf(gain_db / 20.0);
331
332 samples[i] *= gain;
334 if i + 1 < samples.len() {
335 samples[i + 1] *= gain;
336 }
337 }
338 }
339
340 fn reset(&mut self) {
341 self.envelope = 0.0;
342 }
343
344 fn name(&self) -> &str {
345 "Compressor"
346 }
347}
348
349#[derive(Debug)]
351pub struct DistortionProcessor {
352 drive: f32,
353 mix: f32,
354}
355
356impl DistortionProcessor {
357 pub fn new(drive: f32, mix: f32) -> Self {
358 Self {
359 drive: drive.max(1.0),
360 mix: mix.clamp(0.0, 1.0),
361 }
362 }
363}
364
365impl Default for DistortionProcessor {
366 fn default() -> Self {
367 Self::new(10.0, 0.5)
368 }
369}
370
371impl EffectProcessor for DistortionProcessor {
372 fn process(&mut self, samples: &mut [f32], _sample_rate: u32) {
373 for sample in samples.iter_mut() {
374 let input = *sample;
375
376 let driven = input * self.drive;
378
379 let distorted = driven.tanh();
381
382 *sample = input * (1.0 - self.mix) + distorted * self.mix;
384 }
385 }
386
387 fn reset(&mut self) {
388 }
390
391 fn name(&self) -> &str {
392 "Distortion"
393 }
394}
395
396#[derive(Debug)]
398pub struct DelayProcessor {
399 time_ms: f32,
400 feedback: f32,
401 mix: f32,
402 delay_buffer_l: Vec<f32>,
403 delay_buffer_r: Vec<f32>,
404 buffer_pos: usize,
405}
406
407impl DelayProcessor {
408 pub fn new(time_ms: f32, feedback: f32, mix: f32) -> Self {
409 let max_samples = 88200; Self {
412 time_ms: time_ms.clamp(1.0, 2000.0),
413 feedback: feedback.clamp(0.0, 0.95),
414 mix: mix.clamp(0.0, 1.0),
415 delay_buffer_l: vec![0.0; max_samples],
416 delay_buffer_r: vec![0.0; max_samples],
417 buffer_pos: 0,
418 }
419 }
420}
421
422impl Default for DelayProcessor {
423 fn default() -> Self {
424 Self::new(250.0, 0.4, 0.3)
425 }
426}
427
428impl EffectProcessor for DelayProcessor {
429 fn process(&mut self, samples: &mut [f32], sample_rate: u32) {
430 let delay_samples = ((self.time_ms / 1000.0) * sample_rate as f32) as usize;
431 let delay_samples = delay_samples.min(self.delay_buffer_l.len() - 1);
432
433 for i in (0..samples.len()).step_by(2) {
434 let input_l = samples[i];
435 let input_r = if i + 1 < samples.len() {
436 samples[i + 1]
437 } else {
438 input_l
439 };
440
441 let read_pos = (self.buffer_pos + self.delay_buffer_l.len() - delay_samples)
443 % self.delay_buffer_l.len();
444 let delayed_l = self.delay_buffer_l[read_pos];
445 let delayed_r = self.delay_buffer_r[read_pos];
446
447 self.delay_buffer_l[self.buffer_pos] = input_l + delayed_l * self.feedback;
449 self.delay_buffer_r[self.buffer_pos] = input_r + delayed_r * self.feedback;
450
451 samples[i] = input_l * (1.0 - self.mix) + delayed_l * self.mix;
453 if i + 1 < samples.len() {
454 samples[i + 1] = input_r * (1.0 - self.mix) + delayed_r * self.mix;
455 }
456
457 self.buffer_pos = (self.buffer_pos + 1) % self.delay_buffer_l.len();
458 }
459 }
460
461 fn reset(&mut self) {
462 self.delay_buffer_l.fill(0.0);
463 self.delay_buffer_r.fill(0.0);
464 self.buffer_pos = 0;
465 }
466
467 fn name(&self) -> &str {
468 "Delay"
469 }
470}
471
472#[derive(Debug)]
474pub struct ReverbProcessor {
475 room_size: f32,
476 damping: f32,
477 mix: f32,
478 comb_buffers: Vec<Vec<f32>>,
480 comb_positions: Vec<usize>,
481 comb_feedback: Vec<f32>,
482 allpass_buffers: Vec<Vec<f32>>,
484 allpass_positions: Vec<usize>,
485}
486
487impl ReverbProcessor {
488 pub fn new(room_size: f32, damping: f32, mix: f32) -> Self {
489 let room_size = room_size.clamp(0.0, 1.0);
490 let damping = damping.clamp(0.0, 1.0);
491
492 let comb_delays = [1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617];
494 let mut comb_buffers = Vec::new();
495 let mut comb_feedback = Vec::new();
496
497 for &delay in &comb_delays {
498 comb_buffers.push(vec![0.0; delay]);
499 comb_feedback.push(0.84 + room_size * 0.12);
500 }
501
502 let allpass_delays = [556, 441, 341, 225];
504 let mut allpass_buffers = Vec::new();
505
506 for &delay in &allpass_delays {
507 allpass_buffers.push(vec![0.0; delay]);
508 }
509
510 Self {
511 room_size,
512 damping,
513 mix: mix.clamp(0.0, 1.0),
514 comb_buffers,
515 comb_positions: vec![0; 8],
516 comb_feedback,
517 allpass_buffers,
518 allpass_positions: vec![0; 4],
519 }
520 }
521}
522
523impl Default for ReverbProcessor {
524 fn default() -> Self {
525 Self::new(0.5, 0.5, 0.3)
526 }
527}
528
529impl EffectProcessor for ReverbProcessor {
530 fn process(&mut self, samples: &mut [f32], _sample_rate: u32) {
531 for i in 0..samples.len() {
532 let input = samples[i];
533 let mut output = 0.0;
534
535 for (j, buffer) in self.comb_buffers.iter_mut().enumerate() {
537 let pos = self.comb_positions[j];
538 let delayed = buffer[pos];
539
540 let filtered = delayed * (1.0 - self.damping) + buffer[pos] * self.damping;
542 buffer[pos] = input + filtered * self.comb_feedback[j];
543
544 output += delayed;
545
546 self.comb_positions[j] = (pos + 1) % buffer.len();
547 }
548
549 output /= self.comb_buffers.len() as f32;
550
551 for (j, buffer) in self.allpass_buffers.iter_mut().enumerate() {
553 let pos = self.allpass_positions[j];
554 let delayed = buffer[pos];
555
556 buffer[pos] = output + delayed * 0.5;
557 output = delayed - output * 0.5;
558
559 self.allpass_positions[j] = (pos + 1) % buffer.len();
560 }
561
562 samples[i] = input * (1.0 - self.mix) + output * self.mix;
564 }
565 }
566
567 fn reset(&mut self) {
568 for buffer in &mut self.comb_buffers {
569 buffer.fill(0.0);
570 }
571 for buffer in &mut self.allpass_buffers {
572 buffer.fill(0.0);
573 }
574 self.comb_positions.fill(0);
575 self.allpass_positions.fill(0);
576 }
577
578 fn name(&self) -> &str {
579 "Reverb"
580 }
581}
582
583#[derive(Debug)]
585pub struct DriveProcessor {
586 amount: f32,
587 tone: f32,
588 mix: f32,
589}
590
591impl DriveProcessor {
592 pub fn new(amount: f32, tone: f32, mix: f32) -> Self {
593 Self {
594 amount: amount.clamp(0.0, 1.0),
595 tone: tone.clamp(0.0, 1.0),
596 mix: mix.clamp(0.0, 1.0),
597 }
598 }
599}
600
601impl Default for DriveProcessor {
602 fn default() -> Self {
603 Self::new(0.5, 0.5, 0.7)
604 }
605}
606
607impl EffectProcessor for DriveProcessor {
608 fn process(&mut self, samples: &mut [f32], _sample_rate: u32) {
609 let gain = 1.0 + self.amount * 9.0; for sample in samples.iter_mut() {
612 let input = *sample;
613
614 let driven = input * gain;
616
617 let distorted = if driven > 0.0 {
619 driven / (1.0 + driven.abs())
620 } else {
621 driven / (1.0 + driven.abs() * 1.5) };
623
624 let toned = distorted * self.tone + input * (1.0 - self.tone);
626
627 *sample = input * (1.0 - self.mix) + toned * self.mix;
629 }
630 }
631
632 fn reset(&mut self) {
633 }
635
636 fn name(&self) -> &str {
637 "Drive"
638 }
639}
640
641#[cfg(test)]
642mod tests {
643 use super::*;
644
645 #[test]
646 fn test_chorus_processor() {
647 let mut chorus = ChorusProcessor::default();
648 let mut samples = vec![0.5, 0.5, 0.3, 0.3];
649 chorus.process(&mut samples, 44100);
650
651 assert!(
653 samples
654 .iter()
655 .any(|&s| (s - 0.5).abs() > 0.001 || (s - 0.3).abs() > 0.001)
656 );
657 }
658
659 #[test]
660 fn test_distortion_processor() {
661 let mut distortion = DistortionProcessor::new(5.0, 1.0);
662 let mut samples = vec![0.5, 0.5];
663 distortion.process(&mut samples, 44100);
664
665 assert!(samples[0] > 0.5); assert!(samples[0] < 1.0); assert!(samples[1] > 0.5);
671 assert!(samples[1] < 1.0);
672 }
673
674 #[test]
675 fn test_compressor_processor() {
676 let mut compressor = CompressorProcessor::default();
677 let mut samples = vec![0.9, 0.9, 0.1, 0.1]; compressor.process(&mut samples, 44100);
679
680 let range_before = 0.9 - 0.1;
682 let range_after = (samples[0] - samples[2]).abs();
683 assert!(range_after < range_before);
684 }
685}