proteus_lib/effects/reverb.rs
1use std::time::Instant;
2
3use log::debug;
4use rodio::{
5 buffer::SamplesBuffer,
6 dynamic_mixer::{self, DynamicMixer},
7 Source,
8};
9
10use crate::effects::convolution::Convolver;
11use crate::effects::spring_impulse_response::SPRING_IMPULSE_RESPONSE;
12
13const FFT_SIZE: usize = 24576;
14// const FFT_SIZE: usize = 4096;
15// const FFT_SIZE: usize = 1024;
16
17pub struct Reverb {
18 previous_tails: Vec<Vec<f32>>,
19 channels: usize,
20 dry_wet: f32,
21 convolvers: Vec<Convolver>,
22}
23
24impl Reverb {
25 pub fn new(channels: usize, dry_wet: f32) -> Self {
26 Self {
27 previous_tails: vec![vec![0.0; channels]],
28 channels,
29 dry_wet,
30 convolvers: vec![Convolver::new(SPRING_IMPULSE_RESPONSE, FFT_SIZE); channels],
31 }
32 }
33
34 pub fn process(&mut self, input_buffer: &[f32]) -> Vec<f32> {
35 let channels = self.split_channels(input_buffer);
36 let mut processed = Vec::with_capacity(self.channels);
37 for (i, channel) in channels.iter().enumerate() {
38 let processed_channel = self.process_channel(channel, i);
39 processed.push(processed_channel);
40 }
41 let mixed = self.mix_channels(&channels, &processed);
42 mixed
43 }
44
45 pub fn process_mixer(&mut self, mixer: DynamicMixer<f32>) -> SamplesBuffer<f32> {
46 let sample_rate = mixer.sample_rate();
47 let mixer_buffered = mixer.buffered();
48 let vector_samples = mixer_buffered.clone().into_iter().collect::<Vec<f32>>();
49 let processed = self.process(&vector_samples);
50 SamplesBuffer::new(mixer_buffered.channels(), sample_rate, processed)
51 }
52
53 fn process_channel(&mut self, channel: &[f32], index: usize) -> Vec<f32> {
54 let start = Instant::now();
55 let convolver = &mut self.convolvers[index];
56 // convolver.fft_size = channel.len();
57 // let mut convolver = Convolver::new(SPRING_IMPULSE_RESPONSE, FFT_SIZE);
58
59 debug!("Convolver fft size: {:?}", convolver.fft_size);
60 debug!("Channel length: {:?}", channel.len());
61
62 let time_to_create_convolver = Instant::now();
63 debug!(
64 "Time taken to create convolver #{}: {:?}",
65 index,
66 time_to_create_convolver.duration_since(start)
67 );
68 // println!("Channel length: {:?}", channel.len());
69 // println!("Previous tail length: {:?}", self.previous_tails.len());
70 // convolver.previous_tail = if self.previous_tails.len() > index {
71 // self.previous_tails[index].clone()
72 // } else {
73 // self.previous_tails.push(vec![0.0; channel.len()]);
74 // self.previous_tails[index].clone()
75 // };
76 let processed = convolver.process(channel);
77 // self.previous_tails[index] = convolver.previous_tail;
78 let end = Instant::now();
79 debug!(
80 "Time taken to process channel #{}: {:?}",
81 index,
82 end.duration_since(start)
83 );
84 processed
85 }
86
87 fn split_channels(&self, input_buffer: &[f32]) -> Vec<Vec<f32>> {
88 let mut unzipped = Vec::with_capacity(self.channels);
89 for i in 0..self.channels {
90 unzipped.push(
91 input_buffer
92 .iter()
93 .skip(i)
94 .step_by(self.channels)
95 .cloned()
96 .collect::<Vec<f32>>(),
97 );
98 }
99 unzipped
100 }
101
102 fn mix_channels(&self, dry: &Vec<Vec<f32>>, wet: &Vec<Vec<f32>>) -> Vec<f32> {
103 let mut mixed = Vec::with_capacity(dry[0].len() * self.channels);
104 let dry_amount = 1.0 - self.dry_wet;
105 let wet_amount = self.dry_wet;
106
107 // For each sample position
108 for i in 0..dry[0].len() {
109 // For each channel
110 for ch in 0..self.channels {
111 let mixed_sample = (dry[ch][i] * dry_amount) + (wet[ch][i] * wet_amount);
112 mixed.push(mixed_sample);
113 }
114 }
115
116 mixed
117 }
118
119 pub fn clear_tail(&mut self) {
120 for tail in &mut self.previous_tails {
121 tail.fill(0.0);
122 }
123 }
124}
125
126// pub fn apply_reverb(samples: Vec<f32>, dry_wet: f32) -> Vec<f32> {
127// // Clamp dry_wet between 0 and 1
128// let dry_wet = dry_wet.clamp(0.0, 1.0);
129// let dry_amount = 1.0 - dry_wet;
130// let wet_amount = dry_wet;
131
132// println!("Samples length: {:?}", samples.len());
133// let left_samples = samples.iter().step_by(2).cloned().collect::<Vec<f32>>();
134// let right_samples = samples
135// .iter()
136// .skip(1)
137// .step_by(2)
138// .cloned()
139// .collect::<Vec<f32>>();
140
141// let mut convolver_left = Convolver::new(SPRING_IMPULSE_RESPONSE, left_samples.len());
142// let mut convolver_right = Convolver::new(SPRING_IMPULSE_RESPONSE, right_samples.len());
143
144// let processed_left = convolver_left.process(&left_samples);
145// let processed_right = convolver_right.process(&right_samples);
146
147// let previous_tail_left = convolver_left.previous_tail;
148// let previous_tail_right = convolver_right.previous_tail;
149
150// println!("Previous tail left: {:?}", previous_tail_left.len());
151// println!("Previous tail right: {:?}", previous_tail_right.len());
152
153// // Mix dry and wet signals
154// let mut processed = Vec::with_capacity(processed_left.len() * 2);
155// for ((dry_l, dry_r), (wet_l, wet_r)) in left_samples.iter().zip(right_samples.iter())
156// .zip(processed_left.iter().zip(processed_right.iter()))
157// {
158// // Mix left channel
159// let mixed_l = (dry_l * dry_amount) + (wet_l * wet_amount);
160// // Mix right channel
161// let mixed_r = (dry_r * dry_amount) + (wet_r * wet_amount);
162
163// processed.push(mixed_l);
164// processed.push(mixed_r);
165// }
166
167// println!("Processed length: {:?}", processed.len());
168// processed
169// }