1use std::collections::HashMap;
4use std::marker::PhantomData;
5use std::any::{Any, TypeId};
6use std::cell::UnsafeCell;
7use crossbeam::channel::{Receiver, Sender, unbounded};
8
9pub type ComponentFn<E> = Box<dyn FnMut(&mut Runtime<E>, &[f32], &mut [f32], f32) + Send>;
10
11pub struct EventBus<E> {
13 pub tx: Sender<E>,
14 pub rx: Receiver<E>,
15}
16
17impl<E> EventBus<E> {
18 fn new() -> Self {
19 let (tx, rx) = unbounded();
20 Self { tx, rx }
21 }
22
23 pub fn send(&self, event: E) -> Result<(), crossbeam::channel::SendError<E>> {
24 self.tx.send(event)
25 }
26
27 pub fn sender(&self) -> Sender<E> {
28 self.tx.clone()
29 }
30}
31
32impl<E> Clone for EventBus<E> {
33 fn clone(&self) -> Self {
34 Self {
35 tx: self.tx.clone(),
36 rx: self.rx.clone(),
37 }
38 }
39}
40
41pub struct StateHandle<T> {
43 pub(crate) slot: usize,
44 _phantom: PhantomData<T>,
45}
46
47impl<T> Clone for StateHandle<T> {
48 fn clone(&self) -> Self {
49 StateHandle {
50 slot: self.slot,
51 _phantom: PhantomData,
52 }
53 }
54}
55
56impl<T> Copy for StateHandle<T> {}
57
58pub struct ModulatorHandle<T> {
59 pub(crate) slot: usize,
60 _phantom: PhantomData<T>,
61}
62
63impl<T> Clone for ModulatorHandle<T> {
64 fn clone(&self) -> Self {
65 ModulatorHandle {
66 slot: self.slot,
67 _phantom: PhantomData,
68 }
69 }
70}
71
72impl<T> Copy for ModulatorHandle<T> {}
73
74pub struct ParameterHandle<T> {
75 pub(crate) slot: usize,
76 _phantom: PhantomData<T>,
77}
78
79impl<T> Clone for ParameterHandle<T> {
80 fn clone(&self) -> Self {
81 ParameterHandle {
82 slot: self.slot,
83 _phantom: PhantomData,
84 }
85 }
86}
87
88impl<T> Copy for ParameterHandle<T> {}
89
90pub trait Modulator<E>: Send + 'static {
92 fn update(&mut self, sample_rate: f32, event: Option<E>);
93 fn get_value(&self, index: usize) -> f32;
94}
95
96pub trait Parameters: Default + Send + 'static {
97 type Runtime<E: Send + 'static>: ParameterRuntime<E> + Send;
98 type Accessor<'a, E> where E: 'a;
99 type Values: Copy;
100
101 fn create_runtime<E: Send>() -> Self::Runtime<E>;
102 fn create_accessor<E: Send>(runtime: &Self::Runtime<E>) -> Self::Accessor<'_, E>;
103}
104
105pub trait ParameterRuntime<E>: Send {
106 fn update(&mut self, sources: &[Box<dyn Modulator<E>>]);
107 fn route_parameter(&mut self, param_name: &str, source_index: usize, amount: f32);
108}
109
110pub struct Builder<E> {
112 pub(crate) next_state_slot: usize,
113 pub(crate) state_builders: Vec<Box<dyn FnOnce() -> Box<dyn Any + Send>>>,
114 pub(crate) state_map: HashMap<TypeId, usize>,
115
116 pub(crate) next_modulation_slot: usize,
117 pub(crate) modulation_builders: Vec<Box<dyn FnOnce() -> Box<dyn ParameterRuntime<E>>>>,
118 pub(crate) modulation_map: HashMap<TypeId, usize>,
119
120 pub(crate) next_source_slot: usize,
121 pub(crate) modulation_sources: Vec<Box<dyn Modulator<E>>>,
122 pub(crate) source_map: HashMap<TypeId, usize>,
123
124 _phantom: PhantomData<E>,
125}
126
127impl<E: Send + 'static> Builder<E> {
128 fn new() -> Self {
129 Self {
130 next_state_slot: 0,
131 state_builders: Vec::new(),
132 state_map: HashMap::new(),
133 next_modulation_slot: 0,
134 modulation_builders: Vec::new(),
135 modulation_map: HashMap::new(),
136 next_source_slot: 0,
137 modulation_sources: Vec::new(),
138 source_map: HashMap::new(),
139 _phantom: PhantomData,
140 }
141 }
142
143 pub fn use_state<T: Default + Send + 'static>(&mut self) -> StateHandle<T> {
144 let type_id = TypeId::of::<T>();
145 let slot = *self.state_map.entry(type_id).or_insert_with(|| {
146 let slot = self.next_state_slot;
147 self.next_state_slot += 1;
148 self.state_builders.push(Box::new(|| Box::new(T::default())));
149 slot
150 });
151 StateHandle { slot, _phantom: PhantomData }
152 }
153
154 pub fn use_parameters<T: Parameters>(&mut self) -> ParameterHandle<T>
155 where T::Runtime<E>: ParameterRuntime<E> + 'static {
156 let type_id = TypeId::of::<T>();
157 let slot = *self.modulation_map.entry(type_id).or_insert_with(|| {
158 let slot = self.next_modulation_slot;
159 self.next_modulation_slot += 1;
160 self.modulation_builders.push(Box::new(|| Box::new(T::create_runtime::<E>())));
161 slot
162 });
163 ParameterHandle { slot, _phantom: PhantomData }
164 }
165
166 pub fn use_modulator<T: Modulator<E> + Default>(&mut self) -> ModulatorHandle<T> {
167 let type_id = TypeId::of::<T>();
168 let slot = self.next_source_slot;
169 self.next_source_slot += 1;
170
171 self.modulation_sources.push(Box::new(T::default()));
172 self.source_map.insert(type_id, slot);
173
174 ModulatorHandle { slot, _phantom: PhantomData }
175 }
176
177 pub fn build<F>(self, f: F) -> Runtime<E>
178 where
179 F: FnOnce(&mut Builder<E>) -> ComponentFn<E>
180 {
181 let mut builder = self;
182 let component = f(&mut builder);
183
184 Runtime {
185 states: builder.state_builders
186 .into_iter()
187 .map(|builder| UnsafeCell::new(builder()))
188 .collect(),
189 modulation_targets: builder.modulation_builders
190 .into_iter()
191 .map(|builder| UnsafeCell::new(builder()))
192 .collect(),
193 modulation_sources: UnsafeCell::new(builder.modulation_sources),
194 component: UnsafeCell::new(component),
195 }
196 }
197}
198
199pub struct Runtime<E: 'static> {
201 pub(crate) states: Vec<UnsafeCell<Box<dyn Any + Send>>>,
202 pub(crate) modulation_targets: Vec<UnsafeCell<Box<dyn ParameterRuntime<E>>>>,
203 pub(crate) modulation_sources: UnsafeCell<Vec<Box<dyn Modulator<E>>>>,
204 pub(crate) component: UnsafeCell<ComponentFn<E>>,
205}
206
207impl<E: 'static + Send + Clone + Copy> Runtime<E> {
208 pub fn get<T: 'static>(&self, handle: &StateHandle<T>) -> &T {
209 unsafe {
210 (*self.states[handle.slot].get()).downcast_ref().unwrap()
211 }
212 }
213
214 pub fn get_mut<T: 'static>(&self, handle: &StateHandle<T>) -> &mut T {
215 unsafe {
216 (*self.states[handle.slot].get()).downcast_mut().unwrap()
217 }
218 }
219
220 pub fn get_source_mut<T: Modulator<E> + 'static>(&self, handle: &ModulatorHandle<T>) -> &mut T {
221 unsafe {
222 let sources = &mut *self.modulation_sources.get();
223 let boxed_modulator = &mut sources[handle.slot];
224 &mut *(boxed_modulator.as_mut() as *mut dyn Modulator<E> as *mut T)
225 }
226 }
227
228 pub fn route<S: 'static, T: Parameters + 'static>(
229 &mut self,
230 source: ModulatorHandle<S>,
231 target: ParameterHandle<T>,
232 param: &str,
233 amount: f32
234 ) {
235 unsafe {
236 let target_runtime = &mut *self.modulation_targets[target.slot].get();
237 target_runtime.route_parameter(param, source.slot, amount);
238 }
239 }
240
241 pub fn tick(&mut self, sample_rate: f32, event: Option<E>, input: &[f32], output: &mut [f32]) {
242 unsafe {
243 let sources = &mut *self.modulation_sources.get();
244
245 for modulator in sources.iter_mut() {
246 modulator.update(sample_rate, event);
247 }
248
249 let component = &mut *self.component.get();
250 component(self, input, output, sample_rate);
251 }
252 }
253
254 pub fn get_parameters<T: Parameters>(&self, handle: &ParameterHandle<T>) -> T::Accessor<'_, E> {
255 unsafe {
256 let sources = &*self.modulation_sources.get();
257
258 let target_boxed = &mut *self.modulation_targets[handle.slot].get();
259 let concrete_runtime = &mut *(target_boxed.as_mut() as *mut dyn ParameterRuntime<E> as *mut T::Runtime<E>);
260
261 concrete_runtime.update(sources);
262 T::create_accessor(concrete_runtime)
263 }
264 }
265}
266
267pub fn new<E: Clone + Send + 'static>() -> (EventBus<E>, Builder<E>) {
269 (EventBus::new(), Builder::new())
270}
271
272#[macro_export]
274macro_rules! parallel {
275 ($(($weight:expr, $comp:expr)),+) => {
276 |builder: &mut $crate::Builder<_>| -> $crate::ComponentFn<_> {
277 let mut components: Vec<(f32, $crate::ComponentFn<_>)> = vec![$(($weight as f32, $comp(builder))),+];
278 let mut temp_buffers = Vec::new();
279
280 Box::new(move |runtime, input, output, sample_rate| {
281 if temp_buffers.len() != components.len() {
282 temp_buffers.resize(components.len(), Vec::new());
283 }
284 for buf in &mut temp_buffers {
285 if buf.len() != output.len() {
286 buf.resize(output.len(), 0.0);
287 }
288 }
289
290 output.fill(0.0);
291 for ((weight, comp), buf) in components.iter_mut().zip(temp_buffers.iter_mut()) {
292 buf.fill(0.0);
293 comp(runtime, input, buf, sample_rate);
294
295 for (out, &sample) in output.iter_mut().zip(buf.iter()) {
296 *out += sample * *weight;
297 }
298 }
299 })
300 }
301 };
302}
303
304#[macro_export]
305macro_rules! serial {
306 ($($comp:expr),+) => {
307 |builder: &mut $crate::Builder<_>| -> $crate::ComponentFn<_> {
308 let mut components: Vec<$crate::ComponentFn<_>> = vec![$($comp(builder)),+];
309 let mut buffer_a = Vec::new();
310 let mut buffer_b = Vec::new();
311
312 Box::new(move |runtime, input, output, sample_rate| {
313 if components.is_empty() {
314 output.copy_from_slice(input);
315 return;
316 }
317
318 if buffer_a.len() != output.len() {
319 buffer_a.resize(output.len(), 0.0);
320 buffer_b.resize(output.len(), 0.0);
321 }
322
323 buffer_a.copy_from_slice(input);
324
325 for (i, comp) in components.iter_mut().enumerate() {
326 let (inp, out) = if i % 2 == 0 {
327 (&buffer_a[..], &mut buffer_b[..])
328 } else {
329 (&buffer_b[..], &mut buffer_a[..])
330 };
331 out.fill(0.0);
332 comp(runtime, inp, out, sample_rate);
333 }
334
335 let final_buf = if components.len() % 2 == 1 { &buffer_b } else { &buffer_a };
336 output.copy_from_slice(final_buf);
337 })
338 }
339 };
340}
341
342struct ModulationRouting {
343 source_index: usize,
344 amount: f32,
345}