1use super::channel::{ChannelConfig, ChannelState};
4use super::send::{SendConfig, SendType};
5use rill_core::traits::{
6 Node, NodeCategory, NodeId, NodeMetadata, NodeState, NodeTypeId, ParamMetadata, ParamRange,
7 ParamType, ParamValue, ParameterId, Port,
8};
9use rill_core::RenderContext;
10use rill_core::{ProcessError, ProcessResult};
11use std::collections::HashMap;
12
13pub struct MixerNode<const BUF_SIZE: usize> {
15 pub master_volume: f32,
17 pub smoothing: f32,
19 pub channels: Vec<ChannelState>,
21 pub channel_names: HashMap<String, usize>,
23 pub buses: Vec<Vec<f32>>,
25 pub sends: Vec<Vec<SendConfig>>,
27 pub current_master_volume: f32,
29 pub buffer_size: usize,
31 pub sample_rate: f32,
33 pub control_values: Vec<f32>,
35 pub param_ids: HashMap<String, ParameterId>,
37 pub after_param_change_closure: fn(&mut Self, &str, f32),
39 pub id: NodeId,
41 pub input_ports: Vec<Port<f32, BUF_SIZE>>,
43 pub output_ports: Vec<Port<f32, BUF_SIZE>>,
45 pub control_ports: Vec<Port<f32, BUF_SIZE>>,
47 pub state: NodeState<f32, BUF_SIZE>,
49}
50
51impl<const BUF_SIZE: usize> MixerNode<BUF_SIZE> {
52 pub fn new(num_channels: usize, num_buses: usize) -> Self {
54 let mut channels = Vec::with_capacity(num_channels);
55 let mut channel_names = HashMap::new();
56 let mut sends = Vec::with_capacity(num_channels);
57
58 for i in 0..num_channels {
59 let config = ChannelConfig {
60 name: format!("Channel {}", i + 1),
61 ..Default::default()
62 };
63 channel_names.insert(config.name.clone(), i);
64 channels.push(ChannelState::new(config));
65 sends.push(Vec::new()); }
67
68 let mut input_ports = Vec::with_capacity(num_channels);
69 for i in 0..num_channels {
70 input_ports.push(Port::input(
71 NodeId::new(0),
72 i as u16,
73 &format!("ch{}_in", i + 1),
74 ));
75 }
76
77 let mut output_ports = Vec::with_capacity(2 + num_buses);
78 output_ports.push(Port::output(NodeId::new(0), 0, "master_left"));
79 output_ports.push(Port::output(NodeId::new(0), 1, "master_right"));
80 for bus_idx in 0..num_buses {
81 output_ports.push(Port::output(
82 NodeId::new(0),
83 (2 + bus_idx) as u16,
84 &format!("bus{}_out", bus_idx + 1),
85 ));
86 }
87
88 Self {
89 master_volume: 1.0,
90 smoothing: 0.1,
91 channels,
92 channel_names,
93 buses: vec![Vec::new(); num_buses],
94 sends,
95 current_master_volume: 1.0,
96 buffer_size: 0,
97 sample_rate: 44100.0,
98 control_values: Vec::new(),
99 param_ids: HashMap::new(),
100 after_param_change_closure: |_, _, _| {},
101 id: NodeId::new(0),
102 input_ports,
103 output_ports,
104 control_ports: Vec::new(),
105 state: NodeState::new(44100.0),
106 }
107 }
108
109 pub fn num_inputs(&self) -> usize {
111 self.num_signal_inputs()
112 }
113
114 pub fn num_outputs(&self) -> usize {
116 self.num_signal_outputs()
117 }
118
119 pub fn get_param(&self, name: &str) -> Option<ParamValue> {
121 let id = ParameterId::new(name).ok()?;
122 self.get_parameter(&id)
123 }
124
125 pub fn set_param(&mut self, name: &str, value: ParamValue) -> ProcessResult<()> {
127 let id = ParameterId::new(name)
128 .map_err(|e| rill_core::ProcessError::Parameter(e.to_string()))?;
129 self.set_parameter(&id, value)
130 }
131
132 pub fn add_channel(&mut self, config: ChannelConfig) -> usize {
134 let index = self.channels.len();
135 self.channel_names.insert(config.name.clone(), index);
136 self.channels.push(ChannelState::new(config));
137 self.sends.push(Vec::new());
138 self.input_ports.push(Port::input(
139 NodeId::new(0),
140 index as u16,
141 &format!("ch{}_in", index + 1),
142 ));
143 index
144 }
145
146 pub fn remove_channel(&mut self, index: usize) -> Result<(), ProcessError> {
148 if index >= self.channels.len() {
149 return Err(ProcessError::Parameter("Channel index out of range".into()));
150 }
151 let name = self.channels[index].config().name.clone();
152 self.channel_names.remove(&name);
153 self.channels.remove(index);
154 self.sends.remove(index);
155 self.input_ports.remove(index);
156 Ok(())
157 }
158
159 pub fn add_send(&mut self, channel_index: usize, send: SendConfig) -> Result<(), ProcessError> {
161 if channel_index >= self.sends.len() {
162 return Err(ProcessError::Parameter("Channel index out of range".into()));
163 }
164 if send.bus_index >= self.buses.len() {
165 return Err(ProcessError::Parameter("Bus index out of range".into()));
166 }
167 self.sends[channel_index].push(send);
168 Ok(())
169 }
170
171 pub fn clear_sends(&mut self, channel_index: usize) -> Result<(), ProcessError> {
173 if channel_index >= self.sends.len() {
174 return Err(ProcessError::Parameter("Channel index out of range".into()));
175 }
176 self.sends[channel_index].clear();
177 Ok(())
178 }
179
180 pub fn set_channel_volume(
182 &mut self,
183 channel_index: usize,
184 volume: f32,
185 ) -> Result<(), ProcessError> {
186 if channel_index >= self.channels.len() {
187 return Err(ProcessError::Parameter("Channel index out of range".into()));
188 }
189 let mut config = self.channels[channel_index].config().clone();
190 config.volume = volume.clamp(0.0, 1.0);
191 self.channels[channel_index].set_config(config);
192 Ok(())
193 }
194
195 pub fn set_channel_pan(&mut self, channel_index: usize, pan: f32) -> Result<(), ProcessError> {
197 if channel_index >= self.channels.len() {
198 return Err(ProcessError::Parameter("Channel index out of range".into()));
199 }
200 let mut config = self.channels[channel_index].config().clone();
201 config.pan = pan.clamp(-1.0, 1.0);
202 self.channels[channel_index].set_config(config);
203 Ok(())
204 }
205
206 pub fn set_channel_mute(
208 &mut self,
209 channel_index: usize,
210 mute: bool,
211 ) -> Result<(), ProcessError> {
212 if channel_index >= self.channels.len() {
213 return Err(ProcessError::Parameter("Channel index out of range".into()));
214 }
215 let mut config = self.channels[channel_index].config().clone();
216 config.muted = mute;
217 self.channels[channel_index].set_config(config);
218 Ok(())
219 }
220
221 pub fn set_master_volume(&mut self, volume: f32) {
223 self.master_volume = volume.clamp(0.0, 2.0);
224 }
225
226 pub fn set_smoothing(&mut self, factor: f32) {
228 self.smoothing = factor.clamp(0.0, 1.0);
229 for channel in &mut self.channels {
230 channel.set_smoothing(factor);
231 }
232 }
233}
234
235impl<const BUF_SIZE: usize> rill_core::traits::Node<f32, BUF_SIZE> for MixerNode<BUF_SIZE> {
236 fn metadata(&self) -> NodeMetadata {
237 let mut params = vec![ParamMetadata {
238 name: "master_volume".to_string(),
239 description: String::new(),
240 typ: ParamType::Float,
241 default: ParamValue::Float(1.0),
242 range: ParamRange {
243 min: Some(0.0),
244 max: Some(2.0),
245 step: Some(0.01),
246 },
247 unit: Some("gain".to_string()),
248 choices: None,
249 }];
250
251 for i in 0..self.channels.len() {
253 let ch_num = i + 1;
254 params.push(ParamMetadata {
255 name: format!("ch_{}_volume", ch_num),
256 description: String::new(),
257 typ: ParamType::Float,
258 default: ParamValue::Float(1.0),
259 range: ParamRange {
260 min: Some(0.0),
261 max: Some(1.0),
262 step: Some(0.01),
263 },
264 unit: Some("gain".to_string()),
265 choices: None,
266 });
267 params.push(ParamMetadata {
268 name: format!("ch_{}_pan", ch_num),
269 description: String::new(),
270 typ: ParamType::Float,
271 default: ParamValue::Float(0.0),
272 range: ParamRange {
273 min: Some(-1.0),
274 max: Some(1.0),
275 step: Some(0.01),
276 },
277 unit: Some("pan".to_string()),
278 choices: None,
279 });
280 params.push(ParamMetadata {
281 name: format!("ch_{}_mute", ch_num),
282 description: String::new(),
283 typ: ParamType::Bool,
284 default: ParamValue::Bool(false),
285 range: ParamRange {
286 min: None,
287 max: None,
288 step: None,
289 },
290 unit: None,
291 choices: None,
292 });
293 }
294
295 NodeMetadata {
296 name: "Mixer".to_string(),
297 type_name: Some("rill/mixer".to_string()),
298 category: NodeCategory::Utility,
299 description: format!(
300 "Mixer with {} channels and {} buses",
301 self.channels.len(),
302 self.buses.len()
303 ),
304 author: "Rill Mixer".to_string(),
305 version: "0.2.0".to_string(),
306 signal_inputs: self.channels.len(),
307 signal_outputs: 2 + self.buses.len(),
308 control_inputs: 0,
309 control_outputs: 0,
310 clock_inputs: 0,
311 clock_outputs: 0,
312 feedback_ports: 0,
313 parameters: params,
314 }
315 }
316
317 fn node_type_id(&self) -> NodeTypeId
318 where
319 Self: 'static + Sized,
320 {
321 NodeTypeId::of::<Self>()
322 }
323
324 fn init(&mut self, sample_rate: f32) {
325 self.sample_rate = sample_rate;
326 self.state.sample_rate = sample_rate;
327 }
328
329 fn reset(&mut self) {
330 self.current_master_volume = self.master_volume;
331 self.state.reset();
332 for channel in &mut self.channels {
333 channel.set_smoothing(self.smoothing);
334 }
335 }
336
337 fn get_parameter(&self, id: &ParameterId) -> Option<ParamValue> {
338 let name = id.as_str();
339 if name == "master_volume" {
340 return Some(ParamValue::Float(self.master_volume));
341 }
342 if name.starts_with("ch_") {
343 let parts: Vec<&str> = name.split('_').collect();
344 if parts.len() >= 3 {
345 if let Ok(idx) = parts[1].parse::<usize>() {
346 if idx > 0 && idx <= self.channels.len() {
347 let channel = &self.channels[idx - 1];
348 match parts[2] {
349 "volume" => return Some(ParamValue::Float(channel.config().volume)),
350 "pan" => return Some(ParamValue::Float(channel.config().pan)),
351 "mute" => return Some(ParamValue::Bool(channel.config().muted)),
352 _ => {}
353 }
354 }
355 }
356 }
357 }
358 if name == "smoothing" {
359 return Some(ParamValue::Float(self.smoothing));
360 }
361 None
362 }
363
364 fn set_parameter(&mut self, id: &ParameterId, value: ParamValue) -> ProcessResult<()> {
365 let name = id.as_str();
366 if name == "master_volume" {
367 if let ParamValue::Float(v) = value {
368 self.set_master_volume(v);
369 return Ok(());
370 }
371 }
372 if name == "smoothing" {
373 if let ParamValue::Float(v) = value {
374 self.set_smoothing(v);
375 return Ok(());
376 }
377 }
378 if name.starts_with("ch_") {
379 let parts: Vec<&str> = name.split('_').collect();
380 if parts.len() >= 3 {
381 if let Ok(idx) = parts[1].parse::<usize>() {
382 if idx > 0 && idx <= self.channels.len() {
383 match parts[2] {
384 "volume" => {
385 if let ParamValue::Float(v) = value {
386 return self.set_channel_volume(idx - 1, v).map_err(|e| {
387 rill_core::ProcessError::Parameter(e.to_string())
388 });
389 }
390 }
391 "pan" => {
392 if let ParamValue::Float(v) = value {
393 return self.set_channel_pan(idx - 1, v).map_err(|e| {
394 rill_core::ProcessError::Parameter(e.to_string())
395 });
396 }
397 }
398 "mute" => {
399 if let ParamValue::Bool(v) = value {
400 return self.set_channel_mute(idx - 1, v).map_err(|e| {
401 rill_core::ProcessError::Parameter(e.to_string())
402 });
403 }
404 }
405 _ => {}
406 }
407 }
408 }
409 }
410 }
411 Err(rill_core::ProcessError::Parameter(format!(
412 "Unknown parameter: {}",
413 name
414 )))
415 }
416
417 fn id(&self) -> NodeId {
418 self.id
419 }
420
421 fn set_id(&mut self, id: NodeId) {
422 self.id = id;
423 }
424
425 fn input_port(&self, index: usize) -> Option<&Port<f32, BUF_SIZE>> {
426 self.input_ports.get(index)
427 }
428
429 fn input_port_mut(&mut self, index: usize) -> Option<&mut Port<f32, BUF_SIZE>> {
430 self.input_ports.get_mut(index)
431 }
432
433 fn output_port(&self, index: usize) -> Option<&Port<f32, BUF_SIZE>> {
434 self.output_ports.get(index)
435 }
436
437 fn output_port_mut(&mut self, index: usize) -> Option<&mut Port<f32, BUF_SIZE>> {
438 self.output_ports.get_mut(index)
439 }
440
441 fn control_port(&self, index: usize) -> Option<&Port<f32, BUF_SIZE>> {
442 self.control_ports.get(index)
443 }
444
445 fn control_port_mut(&mut self, index: usize) -> Option<&mut Port<f32, BUF_SIZE>> {
446 self.control_ports.get_mut(index)
447 }
448
449 fn state(&self) -> &NodeState<f32, BUF_SIZE> {
450 &self.state
451 }
452
453 fn state_mut(&mut self) -> &mut NodeState<f32, BUF_SIZE> {
454 &mut self.state
455 }
456
457 fn num_signal_inputs(&self) -> usize {
458 self.channels.len()
459 }
460
461 fn num_signal_outputs(&self) -> usize {
462 2 + self.buses.len()
463 }
464
465 fn num_control_inputs(&self) -> usize {
466 0
467 }
468
469 fn num_control_outputs(&self) -> usize {
470 0
471 }
472
473 fn num_clock_inputs(&self) -> usize {
474 0
475 }
476
477 fn num_clock_outputs(&self) -> usize {
478 0
479 }
480
481 fn num_feedback_ports(&self) -> usize {
482 0
483 }
484}
485
486impl<const BUF_SIZE: usize> rill_core::traits::Router<f32, BUF_SIZE> for MixerNode<BUF_SIZE> {
488 fn route(&mut self, ctx: &RenderContext, _inputs: &[&[f32; BUF_SIZE]]) -> ProcessResult<()> {
489 let _num_buses = self.buses.len();
490 let buffer_size = BUF_SIZE;
491
492 self.state.sample_pos = ctx.sample_pos;
494 self.state.blocks_processed = ctx.sample_pos / buffer_size as u64;
495
496 for bus in &mut self.buses {
498 if bus.len() != buffer_size {
499 bus.resize(buffer_size, 0.0);
500 } else {
501 bus.fill(0.0);
502 }
503 }
504
505 let mut master_left = [0.0f32; BUF_SIZE];
507 let mut master_right = [0.0f32; BUF_SIZE];
508
509 for (ch_idx, channel) in self.channels.iter_mut().enumerate() {
511 if ch_idx >= self.input_ports.len() {
512 continue;
513 }
514 let input_buf = self.input_ports[ch_idx].read();
515
516 let channel_volume = channel.config().volume;
517
518 for (i, ((&sample, left), right)) in input_buf
520 .iter()
521 .zip(master_left.iter_mut())
522 .zip(master_right.iter_mut())
523 .enumerate()
524 {
525 let (left_out, right_out) = channel.process_mono(sample);
526
527 *left += left_out;
528 *right += right_out;
529
530 for send in &self.sends[ch_idx] {
531 if send.bus_index < self.buses.len() {
532 let bus = &mut self.buses[send.bus_index];
533
534 let send_signal = match send.send_type {
535 SendType::PreFader => sample,
536 SendType::PostFader => sample * channel_volume,
537 };
538
539 bus[i] += send_signal * send.level;
540 }
541 }
542 }
543 }
544
545 self.current_master_volume +=
547 (self.master_volume - self.current_master_volume) * self.smoothing;
548 let master_gain = self.current_master_volume;
549
550 if self.output_ports.len() >= 2 {
552 let (first, rest) = self.output_ports.split_at_mut(1);
553 let out_l = first[0].write();
554 let out_r = rest[0].write();
555 for ((master_l, master_r), (out_l, out_r)) in master_left
556 .iter()
557 .zip(master_right.iter())
558 .zip(out_l.iter_mut().zip(out_r.iter_mut()))
559 {
560 *out_l = master_l * master_gain;
561 *out_r = master_r * master_gain;
562 }
563 }
564
565 for (bus_idx, bus) in self.buses.iter().enumerate() {
567 let out_idx = 2 + bus_idx;
568 if out_idx < self.output_ports.len() {
569 let out_buf = self.output_ports[out_idx].write();
570 out_buf.copy_from_slice(&bus[..buffer_size]);
571 }
572 }
573
574 Ok(())
575 }
576
577 fn num_route_inputs(&self) -> usize {
578 self.channels.len()
579 }
580
581 fn num_route_outputs(&self) -> usize {
582 2 + self.buses.len()
583 }
584
585 fn set_connection(&mut self, from: usize, to: usize, gain: f32) -> ProcessResult<()> {
586 if from >= self.channels.len() {
590 return Err(ProcessError::Parameter("Channel index out of range".into()));
591 }
592 if to == 0 || to == 1 {
593 self.set_channel_volume(from, gain.clamp(0.0, 1.0))
595 } else if to >= 2 && to < 2 + self.buses.len() {
596 let bus_idx = to - 2;
598 if let Some(existing) = self.sends[from].iter_mut().find(|s| s.bus_index == bus_idx) {
600 existing.level = gain.clamp(0.0, 1.0);
601 Ok(())
602 } else {
603 self.add_send(
604 from,
605 SendConfig {
606 bus_index: bus_idx,
607 level: gain.clamp(0.0, 1.0),
608 send_type: SendType::PostFader,
609 },
610 )
611 }
612 } else {
613 Err(ProcessError::Parameter("Output index out of range".into()))
614 }
615 }
616
617 fn remove_connection(&mut self, from: usize, to: usize) -> ProcessResult<()> {
618 if from >= self.channels.len() {
619 return Err(ProcessError::Parameter("Channel index out of range".into()));
620 }
621 if to == 0 || to == 1 {
622 self.set_channel_mute(from, true)
624 } else if to >= 2 && to < 2 + self.buses.len() {
625 let bus_idx = to - 2;
627 self.sends[from].retain(|s| s.bus_index != bus_idx);
628 Ok(())
629 } else {
630 Err(ProcessError::Parameter("Output index out of range".into()))
631 }
632 }
633
634 fn routing_matrix(&self) -> Vec<Vec<(usize, f32)>> {
635 let n_out = self.num_route_outputs();
636 let mut matrix = vec![Vec::new(); n_out];
637
638 for (ch_idx, ch) in self.channels.iter().enumerate() {
641 if !ch.config().muted {
642 matrix[0].push((ch_idx, ch.config().volume));
643 matrix[1].push((ch_idx, ch.config().volume));
644 }
645 }
646
647 for (ch_idx, ch_sends) in self.sends.iter().enumerate() {
649 for send in ch_sends {
650 let out_idx = 2 + send.bus_index;
651 if out_idx < n_out {
652 matrix[out_idx].push((ch_idx, send.level));
653 }
654 }
655 }
656
657 matrix
658 }
659}