Skip to main content

rill_core_dsp/
effect.rs

1//! Traits for effects
2
3use crate::algorithm::ParameterizedAlgorithm;
4use rill_core::Transcendental;
5
6/// Base trait for effects
7pub trait Effect<T: Transcendental>: ParameterizedAlgorithm<T> {
8    /// Get number of input channels
9    fn num_inputs(&self) -> usize {
10        1
11    }
12
13    /// Get number of output channels
14    fn num_outputs(&self) -> usize {
15        1
16    }
17
18    /// Process stereo pair (if supported)
19    fn process_stereo(&mut self, left: T, right: T) -> (T, T) {
20        let input = [left, right];
21        let mut output = [T::ZERO, T::ZERO];
22        let _ = self.process(Some(&input), &mut output);
23        (output[0], output[1])
24    }
25
26    /// Process block using vector eDSL (optional)
27    fn process_block_vector(&mut self, input: &[T], output: &mut [T]) {
28        let _ = self.process(Some(input), output);
29    }
30}
31
32/// Effect with bypass support
33pub trait Bypassable<T: Transcendental>: Effect<T> {
34    /// Enable/disable bypass
35    fn set_bypass(&mut self, bypass: bool);
36
37    /// Current bypass state
38    fn bypass(&self) -> bool;
39
40    /// Process with bypass consideration
41    fn process_with_bypass(&mut self, input: T) -> T {
42        if self.bypass() {
43            input
44        } else {
45            let mut output = [T::ZERO];
46            let _ = self.process(Some(&[input]), &mut output);
47            output[0]
48        }
49    }
50}
51
52/// Effect with dry/wet support
53pub trait DryWet<T: Transcendental>: Effect<T> {
54    /// Set dry/wet ratio (0.0 = fully dry, 1.0 = fully wet)
55    fn set_dry_wet(&mut self, mix: f32);
56
57    /// Current dry/wet value
58    fn dry_wet(&self) -> f32;
59
60    /// Process with dry/wet consideration
61    fn process_with_dry_wet(&mut self, input: T, dry: T) -> T {
62        let mut wet = [T::ZERO];
63        let _ = self.process(Some(&[input]), &mut wet);
64        let mix = T::from_f32(self.dry_wet());
65        let one_minus_mix = T::from_f32(1.0 - self.dry_wet());
66
67        dry.mul(one_minus_mix).add(wet[0].mul(mix))
68    }
69}
70
71/// Effect with modulation
72pub trait Modulatable<T: Transcendental>: Effect<T> {
73    /// Number of modulation inputs
74    fn num_mod_inputs(&self) -> usize;
75
76    /// Apply modulation
77    fn apply_modulation(&mut self, index: usize, value: T);
78
79    /// Modulation depth
80    fn modulation_depth(&self, index: usize) -> f32;
81
82    /// Set modulation depth
83    fn set_modulation_depth(&mut self, index: usize, depth: f32);
84}