audio_processor_time/mono_delay/
mod.rs1use std::sync::atomic::{AtomicUsize, Ordering};
25use std::time::Duration;
26
27use audio_garbage_collector::Shared;
28use audio_processor_traits::parameters::{
29 make_handle_ref, AudioProcessorHandleProvider, AudioProcessorHandleRef,
30};
31use audio_processor_traits::simple_processor::MonoAudioProcessor;
32use audio_processor_traits::{AtomicF32, AudioContext, Float};
33use augmented_atomics::AtomicValue;
34use generic_handle::GenericHandle;
35
36mod generic_handle;
37
38pub struct MonoDelayProcessorHandle {
39 feedback: AtomicF32,
40 delay_time_secs: AtomicF32,
41 current_write_position: AtomicUsize,
42 current_read_position: AtomicUsize,
43 sample_rate: AtomicF32,
44 buffer_size: AtomicUsize,
45}
46
47impl Default for MonoDelayProcessorHandle {
48 fn default() -> Self {
49 Self {
50 feedback: AtomicF32::from(0.3),
51 delay_time_secs: AtomicF32::from(0.2),
52 current_write_position: AtomicUsize::new(0),
53 sample_rate: AtomicF32::new(44100.0),
54 buffer_size: AtomicUsize::new(1),
55 current_read_position: AtomicUsize::new(0),
56 }
57 }
58}
59
60impl MonoDelayProcessorHandle {
61 pub fn set_feedback(&self, value: f32) {
62 self.feedback.set(value);
63 }
64
65 pub fn set_delay_time_secs(&self, value: f32) {
66 self.delay_time_secs.set(value);
67
68 let write_position = self.current_write_position.get() as i64;
70 let sample_rate = self.sample_rate.get();
71 let buffer_size = self.buffer_size.get() as i64;
72 let offset = (sample_rate * value) as i64;
73 let cursor = write_position - offset + buffer_size;
74 self.current_read_position
75 .store((cursor % buffer_size) as usize, Ordering::Relaxed);
76 }
77}
78
79pub struct MonoDelayProcessor<Sample> {
80 delay_buffer: Vec<Sample>,
81 handle: Shared<MonoDelayProcessorHandle>,
82 max_delay_time: Duration,
83}
84
85impl<Sample> AudioProcessorHandleProvider for MonoDelayProcessor<Sample> {
86 fn generic_handle(&self) -> AudioProcessorHandleRef {
87 make_handle_ref(GenericHandle(self.handle.clone()))
88 }
89}
90
91impl<Sample: Float + From<f32>> Default for MonoDelayProcessor<Sample> {
92 fn default() -> Self {
93 Self::default_with_handle(audio_garbage_collector::handle())
94 }
95}
96
97impl<Sample: Float + From<f32>> MonoDelayProcessor<Sample> {
98 pub fn default_with_handle(handle: &audio_garbage_collector::Handle) -> Self {
99 let max_delay_time = Duration::from_secs(5);
100 let processor_handle = Shared::new(handle, MonoDelayProcessorHandle::default());
101
102 Self::new(max_delay_time, processor_handle)
103 }
104
105 pub fn new(max_delay_time: Duration, handle: Shared<MonoDelayProcessorHandle>) -> Self {
106 Self {
107 handle,
108 max_delay_time,
109 delay_buffer: Self::make_vec(max_delay_time.as_secs() as usize),
110 }
111 }
112
113 pub fn handle(&self) -> &Shared<MonoDelayProcessorHandle> {
114 &self.handle
115 }
116
117 fn make_vec(max_delay_time: usize) -> Vec<Sample> {
118 let mut v = Vec::with_capacity(max_delay_time);
119 v.resize(max_delay_time, 0.0.into());
120 v
121 }
122
123 pub fn read(&self) -> Sample {
124 let delay_samples = self.delay_samples();
125 let offset = delay_samples - delay_samples.floor();
126 let offset: Sample = offset.into();
127 let buffer_size = self.handle.buffer_size.get();
128
129 let mut current_read_position = self.handle().current_read_position.get();
130 let delay_output = interpolate(
131 self.delay_buffer[current_read_position],
132 self.delay_buffer[(current_read_position + 1) % buffer_size],
133 offset,
134 );
135
136 current_read_position += 1;
137 if current_read_position >= buffer_size {
138 current_read_position = 0;
139 }
140 self.handle
141 .current_read_position
142 .store(current_read_position, Ordering::Relaxed);
143
144 delay_output
145 }
146
147 pub fn write(&mut self, sample: Sample) {
148 let mut current_write_position = self.handle().current_write_position.get();
149 self.delay_buffer[current_write_position] = sample;
150
151 current_write_position += 1;
152 if current_write_position >= self.handle.buffer_size.get() {
153 current_write_position = 0;
154 }
155 self.handle
156 .current_write_position
157 .store(current_write_position, Ordering::Relaxed);
158 }
159
160 fn delay_samples(&self) -> f32 {
161 self.handle.delay_time_secs.get() * self.handle.sample_rate.get()
162 }
163}
164
165fn interpolate<S>(s1: S, s2: S, offset: S) -> S
166where
167 S: Float + From<f32>,
168{
169 let one: S = 1.0_f32.into();
170 let offset: S = offset;
171 let rhs = offset * s2;
172 let lhs = (one - offset) * s1;
173 lhs + rhs
176}
177
178impl<Sample: Float + From<f32>> MonoAudioProcessor for MonoDelayProcessor<Sample> {
179 type SampleType = Sample;
180
181 fn m_prepare(&mut self, context: &mut AudioContext) {
182 let settings = context.settings;
183 let buffer_size = (self.max_delay_time.as_secs_f32() * settings.sample_rate()) as usize;
184
185 self.handle
186 .buffer_size
187 .store(buffer_size, Ordering::Relaxed);
188 self.delay_buffer.resize(buffer_size, 0.0.into());
189 self.handle
190 .sample_rate
191 .store(settings.sample_rate(), Ordering::Relaxed);
192
193 self.handle.current_write_position.store(
194 (self.handle.delay_time_secs.get() * settings.sample_rate()) as usize,
195 Ordering::Relaxed,
196 );
197 self.handle
198 .current_read_position
199 .store(0, Ordering::Relaxed);
200 }
201
202 fn m_process(
203 &mut self,
204 _context: &mut AudioContext,
205 sample: Self::SampleType,
206 ) -> Self::SampleType {
207 let delay_output = self.read();
208
209 let write_sample = sample + delay_output * self.handle.feedback.get().into();
210 self.write(write_sample);
211
212 delay_output
213 }
214}