use std::f32::consts::PI; // This started as me trying a bunch of different ways to make a StereoChorus without success // I ended up liking this weird modulation behavior more // Maybe I'll figure out chorus in future but for now here's buffer mod - Ardura #[derive(Clone)] pub struct BufferModulator { sample_rate: f32, depth: f32, rate: f32, spread: f32, buffer_tracker: f32, delay_left: usize, delay_right: usize, time_left: f32, time_right: f32, delay_line_left: Vec<f32>, delay_line_right: Vec<f32>, } impl BufferModulator { pub fn new(sample_rate: f32, depth: f32, rate: f32) -> Self { let delay_left = (sample_rate / 3.0) as usize; let delay_right = (sample_rate / 3.0 * rate) as usize; BufferModulator { sample_rate, depth, rate, spread: 0.0, buffer_tracker: 0.0, delay_left, delay_right, time_left: 0.0, time_right: 0.0, delay_line_left: vec![0.0; delay_left], delay_line_right: vec![0.0; delay_right], } } pub fn update(&mut self, sample_rate: f32, depth: f32, rate: f32, spread: f32, buffer: f32) { self.sample_rate = sample_rate; self.depth = depth; self.rate = rate; self.spread = spread.clamp(0.0, 1.0); if self.buffer_tracker != buffer { self.buffer_tracker = buffer; let temp = (buffer / 3.0).max(2.0) as usize; self.delay_left = temp; self.delay_right = temp; self.delay_line_left = vec![0.0; self.delay_left]; self.delay_line_right = vec![0.0; self.delay_right]; } } pub fn process(&mut self, input_left: f32, input_right: f32, amount: f32) -> (f32, f32) { // Update time variables self.time_left += 1.0 / self.sample_rate; // self.time_right += rate / self.sample_rate; self.time_right += 1.0 + self.spread / self.sample_rate; // Calculate modulation signals let modulation_left = (self.time_left * 2.0 * PI * self.rate).sin(); let modulation_right = (self.time_right * 2.0 * PI * self.rate).sin(); // Apply effect to the left channel let delayed_sample_left = self.delay_line_left.remove(0); let output_left = self.depth * delayed_sample_left * modulation_left; self.delay_line_left.push(input_left + output_left); // Apply effect to the right channel let delayed_sample_right = self.delay_line_right.remove(0); let output_right = self.depth * delayed_sample_right * modulation_right; self.delay_line_right.push(input_right + output_right); ( output_left * amount + input_left * (1.0 - amount), output_right * amount + input_right * (1.0 - amount), ) } }