use std::time::Instant;
use rodio::{
buffer::SamplesBuffer,
dynamic_mixer::{self, DynamicMixer},
Source,
};
use crate::effects::convolution::Convolver;
use crate::effects::spring_impulse_response::SPRING_IMPULSE_RESPONSE;
const FFT_SIZE: usize = 24576;
pub struct Reverb {
previous_tails: Vec<Vec<f32>>,
channels: usize,
dry_wet: f32,
convolvers: Vec<Convolver>,
}
impl Reverb {
pub fn new(channels: usize, dry_wet: f32) -> Self {
Self { previous_tails: vec![vec![0.0; channels]], channels, dry_wet, convolvers: vec![Convolver::new(SPRING_IMPULSE_RESPONSE, FFT_SIZE); channels] }
}
pub fn process(&mut self, input_buffer: &[f32]) -> Vec<f32> {
let channels = self.split_channels(input_buffer);
let mut processed = Vec::with_capacity(self.channels);
for (i, channel) in channels.iter().enumerate() {
let processed_channel = self.process_channel(channel, i);
processed.push(processed_channel);
}
let mixed = self.mix_channels(&channels, &processed);
mixed
}
pub fn process_mixer(&mut self, mixer: DynamicMixer<f32>) -> SamplesBuffer<f32> {
let sample_rate = mixer.sample_rate();
let mixer_buffered = mixer.buffered();
let vector_samples = mixer_buffered.clone().into_iter().collect::<Vec<f32>>();
let processed = self.process(&vector_samples);
SamplesBuffer::new(mixer_buffered.channels(), sample_rate, processed)
}
fn process_channel(&mut self, channel: &[f32], index: usize) -> Vec<f32> {
let start = Instant::now();
let convolver = &mut self.convolvers[index];
println!("Convolver fft size: {:?}", convolver.fft_size);
println!("Channel length: {:?}", channel.len());
let time_to_create_convolver = Instant::now();
println!("Time taken to create convolver #{}: {:?}", index, time_to_create_convolver.duration_since(start));
let processed = convolver.process(channel);
let end = Instant::now();
println!("Time taken to process channel #{}: {:?}", index, end.duration_since(start));
processed
}
fn split_channels(&self, input_buffer: &[f32]) -> Vec<Vec<f32>> {
let mut unzipped = Vec::with_capacity(self.channels);
for i in 0..self.channels {
unzipped.push(input_buffer.iter().skip(i).step_by(self.channels).cloned().collect::<Vec<f32>>());
}
unzipped
}
fn mix_channels(&self, dry: &Vec<Vec<f32>>, wet: &Vec<Vec<f32>>) -> Vec<f32> {
let mut mixed = Vec::with_capacity(dry[0].len() * self.channels);
let dry_amount = 1.0 - self.dry_wet;
let wet_amount = self.dry_wet;
for i in 0..dry[0].len() {
for ch in 0..self.channels {
let mixed_sample = (dry[ch][i] * dry_amount) + (wet[ch][i] * wet_amount);
mixed.push(mixed_sample);
}
}
mixed
}
pub fn clear_tail(&mut self) {
for tail in &mut self.previous_tails {
tail.fill(0.0);
}
}
}