PC Music Generator - a Virtual Modular Synthesizer
at main 117 lines 3.2 kB view raw
1use crate::devices::Device; 2use std::collections::{ 3 BTreeMap, 4 BTreeSet, 5 VecDeque, 6}; 7 8use super::{ 9 CtlGraph, 10 DeviceId, 11}; 12 13type NodeToDevice = BTreeMap<DeviceId, usize>; 14type OutputMap = BTreeMap<usize, ((DeviceId, u8), Vec<(DeviceId, u8)>)>; 15 16pub struct ByteCode { 17 devices: Vec<Box<dyn Device + Send + Sync>>, 18 node_to_device: NodeToDevice, 19 code: Vec<Op>, 20 sample: f32, 21} 22 23impl std::fmt::Debug for ByteCode { 24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 25 f.debug_struct("ByteCode") 26 .field("devices_count", &self.devices.len()) 27 .field("node_to_device", &self.node_to_device) 28 .field("code", &self.code) 29 .field("sample", &self.sample) 30 .finish() 31 } 32} 33 34impl ByteCode { 35 pub fn update_param(&mut self, _pid @ (dev, param): (DeviceId, u8), value: f32) { 36 let d = if let Some(d) = self.node_to_device.get(&dev) { 37 *d 38 } else { 39 return; 40 }; 41 let d = self.devices.get_mut(d).expect("No such device"); 42 d.set_param_indexed(param, value) 43 } 44 45 pub fn sample(&mut self) -> f32 { 46 for op in &self.code { 47 match op { 48 Op::Sample(d, oid) => { 49 self.sample = self.devices[*d as usize].get_output_indexed(*oid); 50 } 51 Op::Output => break, 52 Op::Parametrise(d, pid) => { 53 self.devices[*d as usize].set_param_indexed(*pid, self.sample) 54 } 55 } 56 } 57 self.sample 58 } 59} 60 61#[derive(Debug)] 62enum Op { 63 Sample(u16, u8), 64 Output, 65 Parametrise(u16, u8), 66} 67pub fn compile(ctl_graph: &CtlGraph, sample_rate: f32) -> ByteCode { 68 let mut graph = ctl_graph.graph.clone(); 69 let mut code = VecDeque::new(); 70 let mut node_to_device = BTreeMap::new(); 71 let mut devices = Vec::new(); 72 let mut output_params: OutputMap = BTreeMap::new(); 73 74 let mut last = ctl_graph.end; 75 let mut counter = 0; 76 77 let mut prevs = BTreeSet::new(); 78 while let Some((dev, params)) = graph.remove(&last) { 79 let device_idx = dev.make()(&mut devices, sample_rate); 80 node_to_device.insert(last, device_idx); 81 82 for (pid, params) in params.into_iter().enumerate() { 83 if let Some((source_did, source_pid)) = params { 84 prevs.insert(source_did); 85 86 let (_, to_parametrise) = output_params 87 .entry(counter) 88 .or_insert(((source_did, source_pid), Vec::new())); 89 counter += 1; 90 91 to_parametrise.push((last, pid as u8)); 92 } 93 } 94 if let Some(new) = prevs.pop_first() { 95 last = new; 96 } else { 97 break; 98 } 99 } 100 101 for ((nid, oid), params) in output_params.into_values().rev() { 102 code.push_back(Op::Sample(node_to_device[&nid] as u16, oid)); 103 for (puid, pid) in params { 104 code.push_back(Op::Parametrise(node_to_device[&puid] as u16, pid)); 105 } 106 } 107 108 code.push_back(Op::Output); 109 110 let code = code.into(); 111 ByteCode { 112 devices, 113 node_to_device, 114 code, 115 sample: 0.0, 116 } 117}