use crate::algorithm::{Algorithm, ParameterizedAlgorithm};
use rill_core::time::ClockTick;
use rill_core::traits::ActionContext;
use rill_core::Transcendental;
pub trait Effect<T: Transcendental>: ParameterizedAlgorithm<T> {
fn num_inputs(&self) -> usize {
1
}
fn num_outputs(&self) -> usize {
1
}
fn process_stereo(&mut self, left: T, right: T) -> (T, T) {
let input = [left, right];
let mut output = [T::ZERO, T::ZERO];
let tick = ClockTick::default();
let ctx = ActionContext::new(&tick);
let _ = self.process(Some(&input), &mut output, &ctx);
(output[0], output[1])
}
fn process_block_vector(&mut self, input: &[T], output: &mut [T]) {
let tick = ClockTick::default();
let ctx = ActionContext::new(&tick);
let _ = self.process(Some(input), output, &ctx);
}
}
pub trait Bypassable<T: Transcendental>: Effect<T> {
fn set_bypass(&mut self, bypass: bool);
fn bypass(&self) -> bool;
fn process_with_bypass(&mut self, input: T) -> T {
if self.bypass() {
input
} else {
let mut output = [T::ZERO];
let tick = ClockTick::default();
let ctx = ActionContext::new(&tick);
let _ = self.process(Some(&[input]), &mut output, &ctx);
output[0]
}
}
}
pub trait DryWet<T: Transcendental>: Effect<T> {
fn set_dry_wet(&mut self, mix: f32);
fn dry_wet(&self) -> f32;
fn process_with_dry_wet(&mut self, input: T, dry: T) -> T {
let mut wet = [T::ZERO];
let tick = ClockTick::default();
let ctx = ActionContext::new(&tick);
let _ = self.process(Some(&[input]), &mut wet, &ctx);
let mix = T::from_f32(self.dry_wet());
let one_minus_mix = T::from_f32(1.0 - self.dry_wet());
dry.mul(one_minus_mix).add(wet[0].mul(mix))
}
}
pub trait Modulatable<T: Transcendental>: Effect<T> {
fn num_mod_inputs(&self) -> usize;
fn apply_modulation(&mut self, index: usize, value: T);
fn modulation_depth(&self, index: usize) -> f32;
fn set_modulation_depth(&mut self, index: usize, depth: f32);
}