ruffbox_synth/building_blocks/
delay.rs1use crate::building_blocks::filters::*;
2use crate::building_blocks::interpolation::*;
3use crate::building_blocks::{
4 Modulator, MonoEffect, SampleBuffer, SynthParameterLabel, SynthParameterValue, ValueOrModulator,
5};
6
7use super::FilterType;
8
9pub struct MonoDelay<const BUFSIZE: usize> {
10 rate: f32,
12 time: f32,
13 feedback: f32,
14
15 buffer: Vec<f32>, buffer_ptr: f32,
18 max_buffer_ptr: f32,
19 dampening_filter: Box<dyn MonoEffect<BUFSIZE> + Sync + Send>,
20 samplerate: f32,
21
22 rate_mod: Option<Modulator<BUFSIZE>>,
24 time_mod: Option<Modulator<BUFSIZE>>,
25 fb_mod: Option<Modulator<BUFSIZE>>,
26}
27
28impl<const BUFSIZE: usize> MonoDelay<BUFSIZE> {
29 pub fn with_filter_type(sr: f32, filter_type: FilterType) -> Self {
30 MonoDelay {
31 rate: 1.0,
32 time: 0.256,
33 buffer: vec![0.0; sr as usize * 2 + 3],
34 buffer_ptr: 1.0,
35 max_buffer_ptr: (sr * 0.256) + 1.0, feedback: 0.5,
37 dampening_filter: match filter_type {
38 FilterType::Dummy => Box::new(DummyFilter::new()),
39 FilterType::Lpf18 => Box::new(Lpf18::new(1500.0, 0.5, 0.1, sr)),
40 FilterType::BiquadLpf12dB => Box::new(BiquadLpf12dB::new(1500.0, 0.5, sr)),
41 FilterType::BiquadLpf24dB => Box::new(BiquadLpf24dB::new(1500.0, 0.5, sr)),
42 FilterType::BiquadHpf12dB => Box::new(BiquadHpf12dB::new(1500.0, 0.5, sr)),
43 FilterType::BiquadHpf24dB => Box::new(BiquadHpf24dB::new(1500.0, 0.5, sr)),
44 FilterType::ButterworthLpf(order) => {
45 Box::new(ButterworthLpf::new(1500.0, order, sr))
46 }
47 FilterType::ButterworthHpf(order) => {
48 Box::new(ButterworthHpf::new(1500.0, order, sr))
49 }
50 FilterType::PeakEQ => Box::new(PeakEq::new(1500.0, 100.0, 0.0, sr)),
51 },
52 samplerate: sr,
53 rate_mod: None,
54 time_mod: None,
55 fb_mod: None,
56 }
57 }
58
59 pub fn new(sr: f32) -> Self {
60 MonoDelay {
61 rate: 1.0,
62 time: 0.256,
63 buffer: vec![0.0; sr as usize * 2 + 3],
64 buffer_ptr: 1.0,
65 max_buffer_ptr: (sr * 0.256) + 1.0, feedback: 0.5,
67 dampening_filter: Box::new(Lpf18::new(3000.0, 0.4, 0.3, 44100.0)),
68 samplerate: sr,
69 rate_mod: None,
70 time_mod: None,
71 fb_mod: None,
72 }
73 }
74}
75
76impl<const BUFSIZE: usize> MonoEffect<BUFSIZE> for MonoDelay<BUFSIZE> {
77 fn set_modulator(
78 &mut self,
79 par: SynthParameterLabel,
80 init: f32,
81 modulator: Modulator<BUFSIZE>,
82 ) {
83 match par {
84 SynthParameterLabel::DelayDampeningFrequency => {
85 self.dampening_filter.set_modulator(
86 SynthParameterLabel::LowpassCutoffFrequency,
87 init,
88 modulator,
89 );
90 }
91 SynthParameterLabel::DelayFeedback => {
92 self.feedback = init;
93 self.fb_mod = Some(modulator);
94 }
95 SynthParameterLabel::DelayRate => {
96 self.rate = init;
97 self.rate_mod = Some(modulator);
98 }
99 SynthParameterLabel::DelayTime => {
100 self.time = init;
101 self.time_mod = Some(modulator);
102 }
103 _ => {}
104 }
105 }
106 fn set_parameter(&mut self, par: SynthParameterLabel, value: &SynthParameterValue) {
108 if let SynthParameterValue::ScalarF32(val) = value {
109 match par {
110 SynthParameterLabel::DelayDampeningFrequency => self
111 .dampening_filter
112 .set_parameter(SynthParameterLabel::LowpassCutoffFrequency, value),
113 SynthParameterLabel::DelayFeedback => self.feedback = *val,
114 SynthParameterLabel::DelayRate => self.rate = *val,
115 SynthParameterLabel::DelayTime => {
116 self.time = *val;
117 self.max_buffer_ptr = self.samplerate * self.time + 1.0;
118 }
119 _ => (),
120 };
121 }
122 }
123
124 fn finish(&mut self) {} fn is_finished(&self) -> bool {
126 false
127 } fn process_block(
131 &mut self,
132 block: [f32; BUFSIZE],
133 start_sample: usize,
134 in_buffers: &[SampleBuffer],
135 ) -> [f32; BUFSIZE] {
136 let mut out_buf: [f32; BUFSIZE] = [0.0; BUFSIZE];
137
138 if self.fb_mod.is_some() || self.rate_mod.is_some() || self.time_mod.is_some() {
139 let fb_buf = if let Some(m) = self.fb_mod.as_mut() {
140 m.process(self.feedback, start_sample, in_buffers)
141 } else {
142 [self.feedback; BUFSIZE]
143 };
144
145 let rate_buf = if let Some(m) = self.rate_mod.as_mut() {
146 m.process(self.rate, start_sample, in_buffers)
147 } else {
148 [self.rate; BUFSIZE]
149 };
150
151 let time_buf = if let Some(m) = self.time_mod.as_mut() {
152 m.process(self.time, start_sample, in_buffers)
153 .map(|x| (self.samplerate * x) + 1.0)
154 } else {
155 [self.samplerate * self.time; BUFSIZE]
156 };
157
158 for i in 0..BUFSIZE {
159 let idx = self.buffer_ptr.floor();
161 let frac = self.buffer_ptr - idx;
162 let idx_u = idx as usize;
163
164 let buf_out = interpolate(
166 frac,
167 self.buffer[idx_u - 1],
168 self.buffer[idx_u],
169 self.buffer[idx_u + 1],
170 self.buffer[idx_u + 2],
171 1.0,
172 );
173
174 self.buffer[idx_u] =
175 (self.dampening_filter.maybe_process_sample(buf_out) * fb_buf[i]) + block[i];
176
177 out_buf[i] = self.buffer[idx_u];
178
179 self.buffer_ptr += rate_buf[i];
181 if self.buffer_ptr >= time_buf[i] {
182 self.buffer_ptr = 1.0 + (self.buffer_ptr - time_buf[i]);
183 }
184 }
185 } else {
186 for i in 0..BUFSIZE {
187 let idx = self.buffer_ptr.floor();
189 let frac = self.buffer_ptr - idx;
190 let idx_u = idx as usize;
191
192 let buf_out = interpolate(
194 frac,
195 self.buffer[idx_u - 1],
196 self.buffer[idx_u],
197 self.buffer[idx_u + 1],
198 self.buffer[idx_u + 2],
199 1.0,
200 );
201
202 self.buffer[idx_u] = (self.dampening_filter.maybe_process_sample(buf_out)
203 * self.feedback)
204 + block[i];
205
206 out_buf[i] = self.buffer[idx_u];
207
208 self.buffer_ptr += self.rate;
210 if self.buffer_ptr >= self.max_buffer_ptr {
211 self.buffer_ptr = 1.0 + (self.buffer_ptr - self.max_buffer_ptr);
212 }
213 }
214 }
215
216 out_buf
217 }
218}
219
220pub struct MultichannelDelay<const BUFSIZE: usize, const NCHAN: usize> {
221 delays: Vec<MonoDelay<BUFSIZE>>,
222}
223
224impl<const BUFSIZE: usize, const NCHAN: usize> MultichannelDelay<BUFSIZE, NCHAN> {
225 pub fn new(sr: f32) -> Self {
226 let mut delays = Vec::new();
227
228 for _ in 0..NCHAN {
229 delays.push(MonoDelay::<BUFSIZE>::new(sr));
230 }
231
232 MultichannelDelay { delays }
233 }
234
235 pub fn set_parameter(&mut self, par: SynthParameterLabel, val: &SynthParameterValue) {
236 for c in 0..NCHAN {
237 self.delays[c].set_parameter(par, val);
238 }
239 }
240
241 pub fn set_param_or_modulator(
242 &mut self,
243 par: SynthParameterLabel,
244 val_or_mod: ValueOrModulator<BUFSIZE>,
245 ) {
246 match val_or_mod {
247 ValueOrModulator::Val(val) => self.set_parameter(par, &val),
248 ValueOrModulator::Mod(init, modulator) => self.set_modulator(par, init, modulator),
249 }
250 }
251
252 pub fn set_modulator(
253 &mut self,
254 par: SynthParameterLabel,
255 init: f32,
256 modulator: Modulator<BUFSIZE>,
257 ) {
258 for c in 0..NCHAN {
259 self.delays[c].set_modulator(par, init, modulator.clone());
263 }
264 }
265
266 pub fn process(
267 &mut self,
268 block: [[f32; BUFSIZE]; NCHAN],
269 sample_buffers: &[SampleBuffer],
270 ) -> [[f32; BUFSIZE]; NCHAN] {
271 let mut out_buf = [[0.0; BUFSIZE]; NCHAN];
272
273 for c in 0..NCHAN {
274 out_buf[c] = self.delays[c].process_block(block[c], 0, sample_buffers);
275 }
276
277 out_buf
278 }
279}