1use rill_core::math::Transcendental;
6use rill_core::traits::{Algorithm, ProcessResult};
7
8use crate::builtin::{BlockBuiltin, SampleBuiltin};
9use crate::error::CompileError;
10use crate::ir::{Ir, ParamDef};
11use crate::schedule::{build_schedule, Schedule};
12
13pub(crate) enum BuiltinInst<T: Transcendental> {
15 Sample(Box<dyn SampleBuiltin<T>>),
17 Block(Box<dyn BlockBuiltin<T>>),
19}
20
21pub struct RillProgram<T: Transcendental> {
23 pub(crate) ir: Ir,
24 pub(crate) schedule: Schedule,
25 pub(crate) state: Vec<f64>,
27 pub(crate) state_next: Vec<f64>,
29 pub(crate) delays: Vec<DelayRing>,
31 pub(crate) block_regs: Vec<Vec<T>>,
33 pub(crate) regs_scalar: Vec<f64>,
35 pub(crate) builtins: Vec<BuiltinInst<T>>,
37 pub(crate) params: Vec<f64>,
39 pub(crate) params_meta: Vec<ParamDef>,
41}
42
43pub(crate) struct DelayRing {
45 pub(crate) buf: Vec<f64>,
46 pub(crate) head: usize,
47}
48
49impl DelayRing {
50 pub(crate) fn new(len: usize) -> Self {
51 Self {
52 buf: vec![0.0; len.max(1)],
53 head: 0,
54 }
55 }
56 pub(crate) fn read(&self) -> f64 {
57 self.buf[self.head]
58 }
59 pub(crate) fn write(&mut self, v: f64) {
60 self.buf[self.head] = v;
61 self.head = (self.head + 1) % self.buf.len();
62 }
63}
64
65impl<T: Transcendental> RillProgram<T> {
66 pub(crate) fn new(ir: Ir) -> Self {
67 let state = vec![0.0; ir.state.state_slots];
68 let state_next = state.clone();
69 let delays = ir
70 .state
71 .delay_lens
72 .iter()
73 .map(|&l| DelayRing::new(l))
74 .collect();
75 let block_regs = vec![Vec::new(); ir.num_regs];
76 let regs_scalar = vec![0.0; ir.num_regs];
77 let schedule = build_schedule(&ir);
78 let params_meta = ir.params.clone();
79 let params = ir.params.iter().map(|p| p.default).collect();
80 Self {
81 ir,
82 schedule,
83 state,
84 state_next,
85 delays,
86 block_regs,
87 regs_scalar,
88 builtins: Vec::new(),
89 params,
90 params_meta,
91 }
92 }
93
94 pub(crate) fn new_with(
95 ir: Ir,
96 registry: &crate::builtin::Registry<T>,
97 sample_rate: f32,
98 ) -> Result<Self, CompileError> {
99 let mut builtins = Vec::with_capacity(ir.builtins.len());
100 for bi in &ir.builtins {
101 let entry = registry.get(&bi.name).ok_or_else(|| {
102 CompileError::Unsupported(format!("unknown built-in '{}'", bi.name))
103 })?;
104 match bi.kind {
105 crate::builtin::BuiltinKind::Sample => {
106 let mut b = entry
107 .build_sample(&bi.params, sample_rate)
108 .expect("registry build_sample failed for sample builtin");
109 b.init(sample_rate);
110 builtins.push(BuiltinInst::Sample(b));
111 }
112 crate::builtin::BuiltinKind::Block => {
113 let mut b = entry
114 .build_block(&bi.params, sample_rate)
115 .expect("registry build_block failed for block builtin");
116 Algorithm::init(b.as_mut(), sample_rate);
117 builtins.push(BuiltinInst::Block(b));
118 }
119 }
120 }
121 let state = vec![0.0; ir.state.state_slots];
122 let state_next = state.clone();
123 let delays = ir
124 .state
125 .delay_lens
126 .iter()
127 .map(|&l| DelayRing::new(l))
128 .collect();
129 let block_regs = vec![Vec::new(); ir.num_regs];
130 let regs_scalar = vec![0.0; ir.num_regs];
131 let schedule = build_schedule(&ir);
132 let params_meta = ir.params.clone();
133 let params = ir.params.iter().map(|p| p.default).collect();
134 Ok(Self {
135 ir,
136 schedule,
137 state,
138 state_next,
139 delays,
140 block_regs,
141 regs_scalar,
142 builtins,
143 params,
144 params_meta,
145 })
146 }
147
148 pub(crate) fn ensure_block_len(&mut self, n: usize) {
150 for r in &mut self.block_regs {
151 if r.len() < n {
152 r.resize(n, T::ZERO);
153 }
154 }
155 }
156
157 pub fn param_index(&self, name: &str) -> Option<usize> {
159 self.params_meta.iter().position(|p| p.name == name)
160 }
161
162 pub fn set_param(&mut self, idx: usize, value: f64) {
164 if let Some(def) = self.params_meta.get(idx) {
165 self.params[idx] = value.clamp(def.min, def.max);
166 }
167 }
168
169 pub fn param(&self, idx: usize) -> f64 {
171 self.params.get(idx).copied().unwrap_or(0.0)
172 }
173
174 pub fn params_meta(&self) -> &[ParamDef] {
176 &self.params_meta
177 }
178
179 pub fn process_reference(
182 &mut self,
183 input: Option<&[T]>,
184 output: &mut [T],
185 ) -> ProcessResult<()> {
186 crate::backend::interp::run_block_reference(self, input, output);
187 Ok(())
188 }
189
190 pub fn init(&mut self, sample_rate: f32) {
192 for b in &mut self.builtins {
193 match b {
194 BuiltinInst::Sample(inst) => inst.init(sample_rate),
195 BuiltinInst::Block(inst) => Algorithm::init(inst.as_mut(), sample_rate),
196 }
197 }
198 }
199}
200
201impl<T: Transcendental> Algorithm<T> for RillProgram<T> {
202 fn process(&mut self, input: Option<&[T]>, output: &mut [T]) -> ProcessResult<()> {
203 crate::backend::interp::run_block_hybrid(self, input, output);
204 Ok(())
205 }
206
207 fn reset(&mut self) {
208 for s in &mut self.state {
209 *s = 0.0;
210 }
211 for s in &mut self.state_next {
212 *s = 0.0;
213 }
214 for d in &mut self.delays {
215 for v in &mut d.buf {
216 *v = 0.0;
217 }
218 d.head = 0;
219 }
220 for b in &mut self.builtins {
221 match b {
222 BuiltinInst::Sample(inst) => inst.reset(),
223 BuiltinInst::Block(inst) => Algorithm::reset(inst.as_mut()),
224 }
225 }
226 }
227}