1use fugue::{addr, Trace};
13use fugue_evo::error::GenomeError;
14use fugue_evo::genome::bounds::MultiBounds;
15use fugue_evo::genome::trace_genome::{ChoiceValue, TraceGenome};
16use fugue_evo::genome::traits::EvolutionaryGenome;
17use rand::Rng;
18
19use crate::prior::PatchGrammarPrior;
20use crate::term::{
21 AmpEnv, AudioNode, DriveMode, FilterKind, ModNode, ModOp, NoiseColor, PairOp, PatchTree,
22 TableShape, Uid, Waveform,
23};
24
25impl EvolutionaryGenome for PatchTree {
26 type Allele = f64;
27 type Phenotype = PatchTree;
28
29 fn decode(&self) -> Self::Phenotype {
30 self.clone()
31 }
32
33 fn dimension(&self) -> usize {
34 self.site_count()
35 }
36
37 fn generate<R: Rng>(rng: &mut R, _bounds: &MultiBounds) -> Self {
41 PatchGrammarPrior::default().sample_with_rng(rng)
42 }
43
44 fn distance(&self, other: &Self) -> f64 {
49 let amp = (self.amp.attack - other.amp.attack).abs()
50 + (self.amp.decay - other.amp.decay).abs()
51 + (self.amp.sustain - other.amp.sustain).abs()
52 + (self.amp.release - other.amp.release).abs();
53 amp + node_distance(&self.root, &other.root)
54 }
55
56 fn try_distance(&self, other: &Self) -> Result<f64, GenomeError> {
57 Ok(self.distance(other))
58 }
59}
60
61fn mod_distance(a: &ModNode, b: &ModNode) -> f64 {
62 match (a, b) {
63 (ModNode::None, ModNode::None) => 0.0,
64 (
65 ModNode::Lfo {
66 wave: wa, rate: ra, ..
67 },
68 ModNode::Lfo {
69 wave: wb, rate: rb, ..
70 },
71 ) => (if wa == wb { 0.0 } else { 1.0 }) + (ra - rb).abs(),
72 (
73 ModNode::Env {
74 attack: aa,
75 decay: da,
76 ..
77 },
78 ModNode::Env {
79 attack: ab,
80 decay: db,
81 ..
82 },
83 ) => (aa - ab).abs() + (da - db).abs(),
84 (
85 ModNode::Rand {
86 rate: ra,
87 glide: ga,
88 ..
89 },
90 ModNode::Rand {
91 rate: rb,
92 glide: gb,
93 ..
94 },
95 ) => (ra - rb).abs() + (ga - gb).abs(),
96 (
97 ModNode::Follow {
98 sens: sa,
99 release: ra,
100 ..
101 },
102 ModNode::Follow {
103 sens: sb,
104 release: rb,
105 ..
106 },
107 ) => (sa - sb).abs() + (ra - rb).abs(),
108 (
109 ModNode::Euclid {
110 rate: ra,
111 steps: sa,
112 pulses: pa,
113 ..
114 },
115 ModNode::Euclid {
116 rate: rb,
117 steps: sb,
118 pulses: pb,
119 ..
120 },
121 ) => (ra - rb).abs() + (sa - sb).abs() + (pa - pb).abs(),
122 (
125 ModNode::Op {
126 kind: ka,
127 p0: p0a,
128 p1: p1a,
129 input: ia,
130 ..
131 },
132 ModNode::Op {
133 kind: kb,
134 p0: p0b,
135 p1: p1b,
136 input: ib,
137 ..
138 },
139 ) if ka == kb => (p0a - p0b).abs() + (p1a - p1b).abs() + mod_distance(ia, ib),
140 (
141 ModNode::Pair {
142 kind: ka,
143 a: aa,
144 b: ba,
145 ..
146 },
147 ModNode::Pair {
148 kind: kb,
149 a: ab,
150 b: bb,
151 ..
152 },
153 ) if ka == kb => mod_distance(aa, ab) + mod_distance(ba, bb),
154 (a, b) => 2.0 + (a.size() as f64 - b.size() as f64).abs(),
158 }
159}
160
161fn node_distance(a: &AudioNode, b: &AudioNode) -> f64 {
162 use AudioNode::*;
163 match (a, b) {
164 (
165 Vco {
166 wave: wa,
167 octave: oa,
168 detune: da,
169 mod_depth: mda,
170 modulation: moda,
171 ..
172 },
173 Vco {
174 wave: wb,
175 octave: ob,
176 detune: db,
177 mod_depth: mdb,
178 modulation: modb,
179 ..
180 },
181 ) => {
182 (if wa == wb { 0.0 } else { 1.0 })
183 + (*oa as f64 - *ob as f64).abs() / 4.0
184 + (da - db).abs()
185 + (mda - mdb).abs()
186 + mod_distance(moda, modb)
187 }
188 (
189 Supersaw {
190 octave: oa,
191 detune: da,
192 mix: ma,
193 mod_depth: mda,
194 modulation: moda,
195 ..
196 },
197 Supersaw {
198 octave: ob,
199 detune: db,
200 mix: mb,
201 mod_depth: mdb,
202 modulation: modb,
203 ..
204 },
205 ) => {
206 (*oa as f64 - *ob as f64).abs() / 4.0
207 + (da - db).abs()
208 + (ma - mb).abs()
209 + (mda - mdb).abs()
210 + mod_distance(moda, modb)
211 }
212 (
213 Formant {
214 vowel: va,
215 shift: sa,
216 octave: oa,
217 mod_depth: mda,
218 modulation: moda,
219 ..
220 },
221 Formant {
222 vowel: vb,
223 shift: sb,
224 octave: ob,
225 mod_depth: mdb,
226 modulation: modb,
227 ..
228 },
229 ) => {
230 (va - vb).abs()
231 + (sa - sb).abs()
232 + (*oa as f64 - *ob as f64).abs() / 4.0
233 + (mda - mdb).abs()
234 + mod_distance(moda, modb)
235 }
236 (Noise { color: ca, .. }, Noise { color: cb, .. }) => {
237 if ca == cb {
238 0.0
239 } else {
240 1.0
241 }
242 }
243 (
244 Wavetable {
245 table: ta,
246 octave: oa,
247 morph: ma,
248 mod_depth: da,
249 modulation: moda,
250 ..
251 },
252 Wavetable {
253 table: tb,
254 octave: ob,
255 morph: mb,
256 mod_depth: db,
257 modulation: modb,
258 ..
259 },
260 ) => {
261 (if ta == tb { 0.0 } else { 1.0 })
262 + (*oa as f64 - *ob as f64).abs() / 4.0
263 + (ma - mb).abs()
264 + (da - db).abs()
265 + mod_distance(moda, modb)
266 }
267 (
268 Pluck {
269 octave: oa,
270 damping: da,
271 brightness: ba,
272 mod_depth: mda,
273 modulation: moda,
274 ..
275 },
276 Pluck {
277 octave: ob,
278 damping: db,
279 brightness: bb,
280 mod_depth: mdb,
281 modulation: modb,
282 ..
283 },
284 ) => {
285 (*oa as f64 - *ob as f64).abs() / 4.0
286 + (da - db).abs()
287 + (ba - bb).abs()
288 + (mda - mdb).abs()
289 + mod_distance(moda, modb)
290 }
291 (
292 Mix {
293 balance: la,
294 a: aa,
295 b: ba,
296 ..
297 },
298 Mix {
299 balance: lb,
300 a: ab,
301 b: bb,
302 ..
303 },
304 ) => (la - lb).abs() + node_distance(aa, ab) + node_distance(ba, bb),
305 (
306 RingMod {
307 mix: la,
308 a: aa,
309 b: ba,
310 ..
311 },
312 RingMod {
313 mix: lb,
314 a: ab,
315 b: bb,
316 ..
317 },
318 ) => (la - lb).abs() + node_distance(aa, ab) + node_distance(ba, bb),
319 (
320 Filter {
321 kind: ka,
322 cutoff: ca,
323 resonance: ra,
324 mod_depth: ma,
325 input: ia,
326 modulation: moda,
327 ..
328 },
329 Filter {
330 kind: kb,
331 cutoff: cb,
332 resonance: rb,
333 mod_depth: mb,
334 input: ib,
335 modulation: modb,
336 ..
337 },
338 ) => {
339 (if ka == kb { 0.0 } else { 1.0 })
340 + (ca - cb).abs()
341 + (ra - rb).abs()
342 + (ma - mb).abs()
343 + mod_distance(moda, modb)
344 + node_distance(ia, ib)
345 }
346 (
347 Fold {
348 threshold: ta,
349 mod_depth: ma,
350 input: ia,
351 modulation: moda,
352 ..
353 },
354 Fold {
355 threshold: tb,
356 mod_depth: mb,
357 input: ib,
358 modulation: modb,
359 ..
360 },
361 ) => (ta - tb).abs() + (ma - mb).abs() + mod_distance(moda, modb) + node_distance(ia, ib),
362 (
363 Delay {
364 time: ta,
365 feedback: fa,
366 mix: ma,
367 mod_depth: dpa,
368 input: ia,
369 modulation: moda,
370 ..
371 },
372 Delay {
373 time: tb,
374 feedback: fb,
375 mix: mb,
376 mod_depth: dpb,
377 input: ib,
378 modulation: modb,
379 ..
380 },
381 ) => {
382 (ta - tb).abs()
383 + (fa - fb).abs()
384 + (ma - mb).abs()
385 + (dpa - dpb).abs()
386 + mod_distance(moda, modb)
387 + node_distance(ia, ib)
388 }
389 (
390 Chorus {
391 rate: ra,
392 depth: da,
393 mix: ma,
394 mod_depth: dpa,
395 input: ia,
396 modulation: moda,
397 ..
398 },
399 Chorus {
400 rate: rb,
401 depth: db,
402 mix: mb,
403 mod_depth: dpb,
404 input: ib,
405 modulation: modb,
406 ..
407 },
408 ) => {
409 (ra - rb).abs()
410 + (da - db).abs()
411 + (ma - mb).abs()
412 + (dpa - dpb).abs()
413 + mod_distance(moda, modb)
414 + node_distance(ia, ib)
415 }
416 (
417 Reverb {
418 size: sa,
419 damp: da,
420 mix: ma,
421 mod_depth: dpa,
422 input: ia,
423 modulation: moda,
424 ..
425 },
426 Reverb {
427 size: sb,
428 damp: db,
429 mix: mb,
430 mod_depth: dpb,
431 input: ib,
432 modulation: modb,
433 ..
434 },
435 ) => {
436 (sa - sb).abs()
437 + (da - db).abs()
438 + (ma - mb).abs()
439 + (dpa - dpb).abs()
440 + mod_distance(moda, modb)
441 + node_distance(ia, ib)
442 }
443 (
444 Distortion {
445 drive: ga,
446 tone: ta,
447 mode: ka,
448 mod_depth: dpa,
449 input: ia,
450 modulation: moda,
451 ..
452 },
453 Distortion {
454 drive: gb,
455 tone: tb,
456 mode: kb,
457 mod_depth: dpb,
458 input: ib,
459 modulation: modb,
460 ..
461 },
462 ) => {
463 (ga - gb).abs()
464 + (ta - tb).abs()
465 + (if ka == kb { 0.0 } else { 1.0 })
466 + (dpa - dpb).abs()
467 + mod_distance(moda, modb)
468 + node_distance(ia, ib)
469 }
470 (
471 Bitcrush {
472 bits: ba,
473 downsample: sa,
474 mod_depth: dpa,
475 input: ia,
476 modulation: moda,
477 ..
478 },
479 Bitcrush {
480 bits: bb,
481 downsample: sb,
482 mod_depth: dpb,
483 input: ib,
484 modulation: modb,
485 ..
486 },
487 ) => {
488 (ba - bb).abs()
489 + (sa - sb).abs()
490 + (dpa - dpb).abs()
491 + mod_distance(moda, modb)
492 + node_distance(ia, ib)
493 }
494 (
495 Phaser {
496 rate: ra,
497 depth: da,
498 feedback: fa,
499 mod_depth: dpa,
500 input: ia,
501 modulation: moda,
502 ..
503 },
504 Phaser {
505 rate: rb,
506 depth: db,
507 feedback: fb,
508 mod_depth: dpb,
509 input: ib,
510 modulation: modb,
511 ..
512 },
513 ) => {
514 (ra - rb).abs()
515 + (da - db).abs()
516 + (fa - fb).abs()
517 + (dpa - dpb).abs()
518 + mod_distance(moda, modb)
519 + node_distance(ia, ib)
520 }
521 (
522 Flanger {
523 rate: xa,
524 depth: ya,
525 feedback: za,
526 mod_depth: dpa,
527 input: ia,
528 modulation: moda,
529 ..
530 },
531 Flanger {
532 rate: xb,
533 depth: yb,
534 feedback: zb,
535 mod_depth: dpb,
536 input: ib,
537 modulation: modb,
538 ..
539 },
540 ) => {
541 (xa - xb).abs()
542 + (ya - yb).abs()
543 + (za - zb).abs()
544 + (dpa - dpb).abs()
545 + mod_distance(moda, modb)
546 + node_distance(ia, ib)
547 }
548 (
549 Tremolo {
550 rate: xa,
551 depth: ya,
552 shape: za,
553 mod_depth: dpa,
554 input: ia,
555 modulation: moda,
556 ..
557 },
558 Tremolo {
559 rate: xb,
560 depth: yb,
561 shape: zb,
562 mod_depth: dpb,
563 input: ib,
564 modulation: modb,
565 ..
566 },
567 ) => {
568 (xa - xb).abs()
569 + (ya - yb).abs()
570 + (za - zb).abs()
571 + (dpa - dpb).abs()
572 + mod_distance(moda, modb)
573 + node_distance(ia, ib)
574 }
575 (
576 Vibrato {
577 rate: xa,
578 depth: ya,
579 mix: za,
580 mod_depth: dpa,
581 input: ia,
582 modulation: moda,
583 ..
584 },
585 Vibrato {
586 rate: xb,
587 depth: yb,
588 mix: zb,
589 mod_depth: dpb,
590 input: ib,
591 modulation: modb,
592 ..
593 },
594 ) => {
595 (xa - xb).abs()
596 + (ya - yb).abs()
597 + (za - zb).abs()
598 + (dpa - dpb).abs()
599 + mod_distance(moda, modb)
600 + node_distance(ia, ib)
601 }
602 (
603 Eq {
604 low: xa,
605 mid: ya,
606 high: za,
607 mod_depth: dpa,
608 input: ia,
609 modulation: moda,
610 ..
611 },
612 Eq {
613 low: xb,
614 mid: yb,
615 high: zb,
616 mod_depth: dpb,
617 input: ib,
618 modulation: modb,
619 ..
620 },
621 ) => {
622 (xa - xb).abs()
623 + (ya - yb).abs()
624 + (za - zb).abs()
625 + (dpa - dpb).abs()
626 + mod_distance(moda, modb)
627 + node_distance(ia, ib)
628 }
629 (
630 Granular {
631 position: xa,
632 size: ya,
633 density: za,
634 mod_depth: dpa,
635 input: ia,
636 modulation: moda,
637 ..
638 },
639 Granular {
640 position: xb,
641 size: yb,
642 density: zb,
643 mod_depth: dpb,
644 input: ib,
645 modulation: modb,
646 ..
647 },
648 ) => {
649 (xa - xb).abs()
650 + (ya - yb).abs()
651 + (za - zb).abs()
652 + (dpa - dpb).abs()
653 + mod_distance(moda, modb)
654 + node_distance(ia, ib)
655 }
656 (
657 Shift {
658 semis: xa,
659 window: ya,
660 mix: za,
661 mod_depth: dpa,
662 input: ia,
663 modulation: moda,
664 ..
665 },
666 Shift {
667 semis: xb,
668 window: yb,
669 mix: zb,
670 mod_depth: dpb,
671 input: ib,
672 modulation: modb,
673 ..
674 },
675 ) => {
676 (xa - xb).abs()
677 + (ya - yb).abs()
678 + (za - zb).abs()
679 + (dpa - dpb).abs()
680 + mod_distance(moda, modb)
681 + node_distance(ia, ib)
682 }
683 (
686 Comp {
687 threshold: xa,
688 ratio: ya,
689 makeup: za,
690 mod_depth: dpa,
691 input: ia,
692 sidechain: sa,
693 modulation: moda,
694 ..
695 },
696 Comp {
697 threshold: xb,
698 ratio: yb,
699 makeup: zb,
700 mod_depth: dpb,
701 input: ib,
702 sidechain: sb,
703 modulation: modb,
704 ..
705 },
706 ) => {
707 (xa - xb).abs()
708 + (ya - yb).abs()
709 + (za - zb).abs()
710 + (dpa - dpb).abs()
711 + mod_distance(moda, modb)
712 + node_distance(ia, ib)
713 + node_distance(sa, sb)
714 }
715 (
716 Duck {
717 amount: xa,
718 threshold: ya,
719 release: za,
720 mod_depth: dpa,
721 input: ia,
722 key: ka,
723 modulation: moda,
724 ..
725 },
726 Duck {
727 amount: xb,
728 threshold: yb,
729 release: zb,
730 mod_depth: dpb,
731 input: ib,
732 key: kb,
733 modulation: modb,
734 ..
735 },
736 ) => {
737 (xa - xb).abs()
738 + (ya - yb).abs()
739 + (za - zb).abs()
740 + (dpa - dpb).abs()
741 + mod_distance(moda, modb)
742 + node_distance(ia, ib)
743 + node_distance(ka, kb)
744 }
745 (
746 Gate {
747 threshold: xa,
748 range: ya,
749 release: za,
750 mod_depth: dpa,
751 input: ia,
752 sidechain: sa,
753 modulation: moda,
754 ..
755 },
756 Gate {
757 threshold: xb,
758 range: yb,
759 release: zb,
760 mod_depth: dpb,
761 input: ib,
762 sidechain: sb,
763 modulation: modb,
764 ..
765 },
766 ) => {
767 (xa - xb).abs()
768 + (ya - yb).abs()
769 + (za - zb).abs()
770 + (dpa - dpb).abs()
771 + mod_distance(moda, modb)
772 + node_distance(ia, ib)
773 + node_distance(sa, sb)
774 }
775 (
776 Vocoder {
777 bands: xa,
778 attack: ya,
779 release: za,
780 mod_depth: dpa,
781 carrier: ca,
782 modulator: ma,
783 modulation: moda,
784 ..
785 },
786 Vocoder {
787 bands: xb,
788 attack: yb,
789 release: zb,
790 mod_depth: dpb,
791 carrier: cb,
792 modulator: mb,
793 modulation: modb,
794 ..
795 },
796 ) => {
797 (xa - xb).abs()
798 + (ya - yb).abs()
799 + (za - zb).abs()
800 + (dpa - dpb).abs()
801 + mod_distance(moda, modb)
802 + node_distance(ca, cb)
803 + node_distance(ma, mb)
804 }
805 _ => (a.size() + b.size()) as f64,
807 }
808}
809
810fn child_key(key: &str, i: usize) -> String {
815 format!("{key}/{i}")
816}
817
818fn mod_key(key: &str) -> String {
819 format!("{key}/m")
820}
821
822fn put_f64(t: &mut Trace, key: &str, site: &str, v: f64) {
823 t.insert_choice(addr!(key, site), ChoiceValue::F64(v), 0.0);
824}
825
826fn put_usize(t: &mut Trace, key: &str, site: &str, v: usize) {
827 t.insert_choice(addr!(key, site), ChoiceValue::Usize(v), 0.0);
828}
829
830fn put_bool(t: &mut Trace, key: &str, site: &str, v: bool) {
831 t.insert_choice(addr!(key, site), ChoiceValue::Bool(v), 0.0);
832}
833
834fn encode_mod(m: &ModNode, key: &str, t: &mut Trace) {
835 match m {
836 ModNode::None => put_usize(t, key, "mod", 0),
837 ModNode::Lfo { wave, rate, .. } => {
838 put_usize(t, key, "mod", 1);
839 put_usize(t, key, "wave", wave.index());
840 put_f64(t, key, "rate", *rate);
841 }
842 ModNode::Env { attack, decay, .. } => {
843 put_usize(t, key, "mod", 2);
844 put_f64(t, key, "att", *attack);
845 put_f64(t, key, "dec", *decay);
846 }
847 ModNode::Rand { rate, glide, .. } => {
848 put_usize(t, key, "mod", 3);
849 put_f64(t, key, "rate", *rate);
850 put_f64(t, key, "glide", *glide);
851 }
852 ModNode::Follow { sens, release, .. } => {
853 put_usize(t, key, "mod", 4);
854 put_f64(t, key, "sens", *sens);
855 put_f64(t, key, "rel", *release);
856 }
857 ModNode::Euclid {
858 rate,
859 steps,
860 pulses,
861 ..
862 } => {
863 put_usize(t, key, "mod", 5);
864 put_f64(t, key, "erate", *rate);
865 put_f64(t, key, "esteps", *steps);
866 put_f64(t, key, "epulses", *pulses);
867 }
868 ModNode::Op {
872 kind,
873 p0,
874 p1,
875 input,
876 ..
877 } => {
878 put_usize(t, key, "mod", 6);
879 put_usize(t, key, "modop", kind.index());
880 let sites = kind.param_sites();
881 put_f64(t, key, sites[0], *p0);
882 if let Some(site) = sites.get(1) {
883 put_f64(t, key, site, *p1);
884 }
885 encode_mod(input, &child_key(key, 0), t);
886 }
887 ModNode::Pair { kind, a, b, .. } => {
888 put_usize(t, key, "mod", 7);
889 put_usize(t, key, "pairop", kind.index());
890 encode_mod(a, &child_key(key, 0), t);
891 encode_mod(b, &child_key(key, 1), t);
892 }
893 }
894}
895
896fn encode_node(n: &AudioNode, key: &str, t: &mut Trace) {
897 use AudioNode::*;
898 match n {
899 Vco {
900 wave,
901 octave,
902 detune,
903 mod_depth,
904 modulation,
905 ..
906 } => {
907 put_bool(t, key, "leaf", true);
908 put_usize(t, key, "src", 0);
909 put_usize(t, key, "wave", wave.index());
910 put_usize(t, key, "oct", (octave + 2) as usize);
911 put_f64(t, key, "det", *detune);
912 put_f64(t, key, "mdepth", *mod_depth);
913 encode_mod(modulation, &mod_key(key), t);
914 }
915 Supersaw {
916 octave,
917 detune,
918 mix,
919 mod_depth,
920 modulation,
921 ..
922 } => {
923 put_bool(t, key, "leaf", true);
924 put_usize(t, key, "src", 1);
925 put_usize(t, key, "oct", (octave + 2) as usize);
926 put_f64(t, key, "det", *detune);
927 put_f64(t, key, "smix", *mix);
928 put_f64(t, key, "mdepth", *mod_depth);
929 encode_mod(modulation, &mod_key(key), t);
930 }
931 Noise { color, .. } => {
932 put_bool(t, key, "leaf", true);
933 put_usize(t, key, "src", 2);
934 put_usize(t, key, "color", color.index());
935 }
936 Silence { .. } => {
939 put_bool(t, key, "leaf", true);
940 put_usize(t, key, "src", 6);
941 }
942 Wavetable {
943 table,
944 octave,
945 morph,
946 mod_depth,
947 modulation,
948 ..
949 } => {
950 put_bool(t, key, "leaf", true);
951 put_usize(t, key, "src", 3);
952 put_usize(t, key, "table", table.index());
953 put_usize(t, key, "oct", (octave + 2) as usize);
954 put_f64(t, key, "morph", *morph);
955 put_f64(t, key, "mdepth", *mod_depth);
956 encode_mod(modulation, &mod_key(key), t);
957 }
958 Pluck {
959 octave,
960 damping,
961 brightness,
962 mod_depth,
963 modulation,
964 ..
965 } => {
966 put_bool(t, key, "leaf", true);
967 put_usize(t, key, "src", 4);
968 put_usize(t, key, "oct", (octave + 2) as usize);
969 put_f64(t, key, "damp", *damping);
970 put_f64(t, key, "bright", *brightness);
971 put_f64(t, key, "mdepth", *mod_depth);
972 encode_mod(modulation, &mod_key(key), t);
973 }
974 Formant {
975 vowel,
976 shift,
977 octave,
978 mod_depth,
979 modulation,
980 ..
981 } => {
982 put_bool(t, key, "leaf", true);
983 put_usize(t, key, "src", 5);
984 put_f64(t, key, "vowel", *vowel);
985 put_f64(t, key, "fshift", *shift);
986 put_usize(t, key, "oct", (octave + 2) as usize);
987 put_f64(t, key, "mdepth", *mod_depth);
988 encode_mod(modulation, &mod_key(key), t);
989 }
990 Mix { balance, a, b, .. } => {
991 put_bool(t, key, "leaf", false);
992 put_usize(t, key, "op", 0);
993 put_f64(t, key, "bal", *balance);
994 encode_node(a, &child_key(key, 0), t);
995 encode_node(b, &child_key(key, 1), t);
996 }
997 Filter {
998 kind,
999 cutoff,
1000 resonance,
1001 mod_depth,
1002 input,
1003 modulation,
1004 ..
1005 } => {
1006 put_bool(t, key, "leaf", false);
1007 put_usize(t, key, "op", 1);
1008 put_usize(t, key, "fkind", kind.index());
1009 put_f64(t, key, "cut", *cutoff);
1010 put_f64(t, key, "res", *resonance);
1011 put_f64(t, key, "mdepth", *mod_depth);
1012 encode_mod(modulation, &mod_key(key), t);
1013 encode_node(input, &child_key(key, 0), t);
1014 }
1015 Fold {
1016 threshold,
1017 mod_depth,
1018 input,
1019 modulation,
1020 ..
1021 } => {
1022 put_bool(t, key, "leaf", false);
1023 put_usize(t, key, "op", 2);
1024 put_f64(t, key, "thresh", *threshold);
1025 put_f64(t, key, "mdepth", *mod_depth);
1026 encode_mod(modulation, &mod_key(key), t);
1027 encode_node(input, &child_key(key, 0), t);
1028 }
1029 Delay {
1030 time,
1031 feedback,
1032 mix,
1033 mod_depth,
1034 input,
1035 modulation,
1036 ..
1037 } => {
1038 put_bool(t, key, "leaf", false);
1039 put_usize(t, key, "op", 3);
1040 put_f64(t, key, "time", *time);
1041 put_f64(t, key, "fb", *feedback);
1042 put_f64(t, key, "dmix", *mix);
1043 put_f64(t, key, "mdepth", *mod_depth);
1044 encode_mod(modulation, &mod_key(key), t);
1045 encode_node(input, &child_key(key, 0), t);
1046 }
1047 Chorus {
1048 rate,
1049 depth,
1050 mix,
1051 mod_depth,
1052 input,
1053 modulation,
1054 ..
1055 } => {
1056 put_bool(t, key, "leaf", false);
1057 put_usize(t, key, "op", 4);
1058 put_f64(t, key, "crate", *rate);
1059 put_f64(t, key, "cdepth", *depth);
1060 put_f64(t, key, "cmix", *mix);
1061 put_f64(t, key, "mdepth", *mod_depth);
1062 encode_mod(modulation, &mod_key(key), t);
1063 encode_node(input, &child_key(key, 0), t);
1064 }
1065 Reverb {
1066 size,
1067 damp,
1068 mix,
1069 mod_depth,
1070 input,
1071 modulation,
1072 ..
1073 } => {
1074 put_bool(t, key, "leaf", false);
1075 put_usize(t, key, "op", 5);
1076 put_f64(t, key, "rsize", *size);
1077 put_f64(t, key, "rdamp", *damp);
1078 put_f64(t, key, "rmix", *mix);
1079 put_f64(t, key, "mdepth", *mod_depth);
1080 encode_mod(modulation, &mod_key(key), t);
1081 encode_node(input, &child_key(key, 0), t);
1082 }
1083 Distortion {
1084 drive,
1085 tone,
1086 mode,
1087 mod_depth,
1088 input,
1089 modulation,
1090 ..
1091 } => {
1092 put_bool(t, key, "leaf", false);
1093 put_usize(t, key, "op", 6);
1094 put_f64(t, key, "drive", *drive);
1095 put_f64(t, key, "tone", *tone);
1096 put_usize(t, key, "dmode", mode.index());
1097 put_f64(t, key, "mdepth", *mod_depth);
1098 encode_mod(modulation, &mod_key(key), t);
1099 encode_node(input, &child_key(key, 0), t);
1100 }
1101 Bitcrush {
1102 bits,
1103 downsample,
1104 mod_depth,
1105 input,
1106 modulation,
1107 ..
1108 } => {
1109 put_bool(t, key, "leaf", false);
1110 put_usize(t, key, "op", 7);
1111 put_f64(t, key, "bits", *bits);
1112 put_f64(t, key, "dsamp", *downsample);
1113 put_f64(t, key, "mdepth", *mod_depth);
1114 encode_mod(modulation, &mod_key(key), t);
1115 encode_node(input, &child_key(key, 0), t);
1116 }
1117 Phaser {
1118 rate,
1119 depth,
1120 feedback,
1121 mod_depth,
1122 input,
1123 modulation,
1124 ..
1125 } => {
1126 put_bool(t, key, "leaf", false);
1127 put_usize(t, key, "op", 8);
1128 put_f64(t, key, "prate", *rate);
1129 put_f64(t, key, "pdepth", *depth);
1130 put_f64(t, key, "pfb", *feedback);
1131 put_f64(t, key, "mdepth", *mod_depth);
1132 encode_mod(modulation, &mod_key(key), t);
1133 encode_node(input, &child_key(key, 0), t);
1134 }
1135 Flanger {
1136 rate,
1137 depth,
1138 feedback,
1139 mod_depth,
1140 input,
1141 modulation,
1142 ..
1143 } => {
1144 put_bool(t, key, "leaf", false);
1145 put_usize(t, key, "op", 10);
1146 put_f64(t, key, "frate", *rate);
1147 put_f64(t, key, "fdepth", *depth);
1148 put_f64(t, key, "ffb", *feedback);
1149 put_f64(t, key, "mdepth", *mod_depth);
1150 encode_mod(modulation, &mod_key(key), t);
1151 encode_node(input, &child_key(key, 0), t);
1152 }
1153 Tremolo {
1154 rate,
1155 depth,
1156 shape,
1157 mod_depth,
1158 input,
1159 modulation,
1160 ..
1161 } => {
1162 put_bool(t, key, "leaf", false);
1163 put_usize(t, key, "op", 11);
1164 put_f64(t, key, "trate", *rate);
1165 put_f64(t, key, "tdepth", *depth);
1166 put_f64(t, key, "tshape", *shape);
1167 put_f64(t, key, "mdepth", *mod_depth);
1168 encode_mod(modulation, &mod_key(key), t);
1169 encode_node(input, &child_key(key, 0), t);
1170 }
1171 Vibrato {
1172 rate,
1173 depth,
1174 mix,
1175 mod_depth,
1176 input,
1177 modulation,
1178 ..
1179 } => {
1180 put_bool(t, key, "leaf", false);
1181 put_usize(t, key, "op", 12);
1182 put_f64(t, key, "vrate", *rate);
1183 put_f64(t, key, "vdepth", *depth);
1184 put_f64(t, key, "vmix", *mix);
1185 put_f64(t, key, "mdepth", *mod_depth);
1186 encode_mod(modulation, &mod_key(key), t);
1187 encode_node(input, &child_key(key, 0), t);
1188 }
1189 Eq {
1190 low,
1191 mid,
1192 high,
1193 mod_depth,
1194 input,
1195 modulation,
1196 ..
1197 } => {
1198 put_bool(t, key, "leaf", false);
1199 put_usize(t, key, "op", 13);
1200 put_f64(t, key, "low", *low);
1201 put_f64(t, key, "mid", *mid);
1202 put_f64(t, key, "high", *high);
1203 put_f64(t, key, "mdepth", *mod_depth);
1204 encode_mod(modulation, &mod_key(key), t);
1205 encode_node(input, &child_key(key, 0), t);
1206 }
1207 Granular {
1208 position,
1209 size,
1210 density,
1211 mod_depth,
1212 input,
1213 modulation,
1214 ..
1215 } => {
1216 put_bool(t, key, "leaf", false);
1217 put_usize(t, key, "op", 14);
1218 put_f64(t, key, "gpos", *position);
1219 put_f64(t, key, "gsize", *size);
1220 put_f64(t, key, "gdens", *density);
1221 put_f64(t, key, "mdepth", *mod_depth);
1222 encode_mod(modulation, &mod_key(key), t);
1223 encode_node(input, &child_key(key, 0), t);
1224 }
1225 RingMod { mix, a, b, .. } => {
1226 put_bool(t, key, "leaf", false);
1227 put_usize(t, key, "op", 9);
1228 put_f64(t, key, "rgmix", *mix);
1229 encode_node(a, &child_key(key, 0), t);
1230 encode_node(b, &child_key(key, 1), t);
1231 }
1232 Shift {
1233 semis,
1234 window,
1235 mix,
1236 mod_depth,
1237 input,
1238 modulation,
1239 ..
1240 } => {
1241 put_bool(t, key, "leaf", false);
1242 put_usize(t, key, "op", 15);
1243 put_f64(t, key, "semis", *semis);
1244 put_f64(t, key, "window", *window);
1245 put_f64(t, key, "smix", *mix);
1246 put_f64(t, key, "mdepth", *mod_depth);
1247 encode_mod(modulation, &mod_key(key), t);
1248 encode_node(input, &child_key(key, 0), t);
1249 }
1250 Comp {
1254 threshold,
1255 ratio,
1256 makeup,
1257 mod_depth,
1258 input,
1259 sidechain,
1260 modulation,
1261 ..
1262 } => {
1263 put_bool(t, key, "leaf", false);
1264 put_usize(t, key, "op", 16);
1265 put_f64(t, key, "thresh", *threshold);
1266 put_f64(t, key, "ratio", *ratio);
1267 put_f64(t, key, "makeup", *makeup);
1268 put_f64(t, key, "mdepth", *mod_depth);
1269 encode_mod(modulation, &mod_key(key), t);
1270 encode_node(input, &child_key(key, 0), t);
1271 encode_node(sidechain, &child_key(key, 1), t);
1272 }
1273 Duck {
1274 amount,
1275 threshold,
1276 release,
1277 mod_depth,
1278 input,
1279 key: key_input,
1280 modulation,
1281 ..
1282 } => {
1283 put_bool(t, key, "leaf", false);
1284 put_usize(t, key, "op", 17);
1285 put_f64(t, key, "amount", *amount);
1286 put_f64(t, key, "dthresh", *threshold);
1287 put_f64(t, key, "drel", *release);
1288 put_f64(t, key, "mdepth", *mod_depth);
1289 encode_mod(modulation, &mod_key(key), t);
1290 encode_node(input, &child_key(key, 0), t);
1291 encode_node(key_input, &child_key(key, 1), t);
1292 }
1293 Gate {
1294 threshold,
1295 range,
1296 release,
1297 mod_depth,
1298 input,
1299 sidechain,
1300 modulation,
1301 ..
1302 } => {
1303 put_bool(t, key, "leaf", false);
1304 put_usize(t, key, "op", 18);
1305 put_f64(t, key, "gthresh", *threshold);
1306 put_f64(t, key, "range", *range);
1307 put_f64(t, key, "grel", *release);
1308 put_f64(t, key, "mdepth", *mod_depth);
1309 encode_mod(modulation, &mod_key(key), t);
1310 encode_node(input, &child_key(key, 0), t);
1311 encode_node(sidechain, &child_key(key, 1), t);
1312 }
1313 Vocoder {
1314 bands,
1315 attack,
1316 release,
1317 mod_depth,
1318 carrier,
1319 modulator,
1320 modulation,
1321 ..
1322 } => {
1323 put_bool(t, key, "leaf", false);
1324 put_usize(t, key, "op", 19);
1325 put_f64(t, key, "bands", *bands);
1326 put_f64(t, key, "vatt", *attack);
1327 put_f64(t, key, "vrel", *release);
1328 put_f64(t, key, "mdepth", *mod_depth);
1329 encode_mod(modulation, &mod_key(key), t);
1330 encode_node(carrier, &child_key(key, 0), t);
1331 encode_node(modulator, &child_key(key, 1), t);
1332 }
1333 }
1334}
1335
1336fn get_f64(t: &Trace, key: &str, site: &str) -> Result<f64, GenomeError> {
1337 let a = addr!(key, site);
1338 t.get_f64(&a)
1339 .ok_or_else(|| GenomeError::MissingAddress(a.to_string()))
1340}
1341
1342fn get_usize(t: &Trace, key: &str, site: &str) -> Result<usize, GenomeError> {
1343 let a = addr!(key, site);
1344 t.get_usize(&a)
1345 .ok_or_else(|| GenomeError::MissingAddress(a.to_string()))
1346}
1347
1348fn get_bool(t: &Trace, key: &str, site: &str) -> Result<bool, GenomeError> {
1349 let a = addr!(key, site);
1350 t.get_bool(&a)
1351 .ok_or_else(|| GenomeError::MissingAddress(a.to_string()))
1352}
1353
1354fn get_f64_or(t: &Trace, key: &str, site: &str, default: f64) -> f64 {
1361 t.get_f64(&addr!(key, site)).unwrap_or(default)
1362}
1363
1364fn decode_mod(t: &Trace, key: &str) -> Result<ModNode, GenomeError> {
1365 match get_usize(t, key, "mod")? {
1366 0 => Ok(ModNode::None),
1367 1 => Ok(ModNode::Lfo {
1368 uid: Uid::NEW,
1369 wave: Waveform::from_index(get_usize(t, key, "wave")?),
1370 rate: get_f64(t, key, "rate")?,
1371 }),
1372 2 => Ok(ModNode::Env {
1373 uid: Uid::NEW,
1374 attack: get_f64(t, key, "att")?,
1375 decay: get_f64(t, key, "dec")?,
1376 }),
1377 3 => Ok(ModNode::Rand {
1378 uid: Uid::NEW,
1379 rate: get_f64(t, key, "rate")?,
1380 glide: get_f64_or(t, key, "glide", 0.0),
1382 }),
1383 4 => Ok(ModNode::Follow {
1384 uid: Uid::NEW,
1385 sens: get_f64(t, key, "sens")?,
1386 release: get_f64(t, key, "rel")?,
1387 }),
1388 5 => Ok(ModNode::Euclid {
1389 uid: Uid::NEW,
1390 rate: get_f64(t, key, "erate")?,
1391 steps: get_f64(t, key, "esteps")?,
1392 pulses: get_f64(t, key, "epulses")?,
1393 }),
1394 6 => {
1395 let kind = ModOp::from_index(get_usize(t, key, "modop")?);
1396 let sites = kind.param_sites();
1397 Ok(ModNode::Op {
1398 uid: Uid::NEW,
1399 kind,
1400 p0: get_f64(t, key, sites[0])?,
1401 p1: match sites.get(1) {
1404 Some(site) => get_f64(t, key, site)?,
1405 None => 0.0,
1406 },
1407 input: Box::new(decode_mod(t, &child_key(key, 0))?),
1408 })
1409 }
1410 7 => Ok(ModNode::Pair {
1411 uid: Uid::NEW,
1412 kind: PairOp::from_index(get_usize(t, key, "pairop")?),
1413 a: Box::new(decode_mod(t, &child_key(key, 0))?),
1414 b: Box::new(decode_mod(t, &child_key(key, 1))?),
1415 }),
1416 k => Err(GenomeError::InvalidStructure(format!(
1417 "mod kind {k} out of range at {key}"
1418 ))),
1419 }
1420}
1421
1422fn decode_new_mod(t: &Trace, key: &str) -> Result<ModNode, GenomeError> {
1427 if t.get_usize(&addr!(key, "mod")).is_none() {
1428 return Ok(ModNode::None);
1429 }
1430 decode_mod(t, key)
1431}
1432
1433const DEFAULT_MOD_DEPTH: f64 = 0.3;
1437
1438fn decode_node(t: &Trace, key: &str) -> Result<AudioNode, GenomeError> {
1439 if get_bool(t, key, "leaf")? {
1440 match get_usize(t, key, "src")? {
1441 0 => Ok(AudioNode::Vco {
1445 uid: Uid::NEW,
1446 wave: Waveform::from_index(get_usize(t, key, "wave")?),
1447 octave: get_usize(t, key, "oct")? as i8 - 2,
1448 detune: get_f64(t, key, "det")?,
1449 mod_depth: get_f64_or(t, key, "mdepth", DEFAULT_MOD_DEPTH),
1450 modulation: decode_new_mod(t, &mod_key(key))?,
1451 }),
1452 1 => Ok(AudioNode::Supersaw {
1453 uid: Uid::NEW,
1454 octave: get_usize(t, key, "oct")? as i8 - 2,
1455 detune: get_f64(t, key, "det")?,
1456 mix: get_f64(t, key, "smix")?,
1457 mod_depth: get_f64_or(t, key, "mdepth", DEFAULT_MOD_DEPTH),
1458 modulation: decode_new_mod(t, &mod_key(key))?,
1459 }),
1460 2 => Ok(AudioNode::Noise {
1461 uid: Uid::NEW,
1462 color: NoiseColor::from_index(get_usize(t, key, "color")?),
1463 }),
1464 3 => Ok(AudioNode::Wavetable {
1465 uid: Uid::NEW,
1466 table: TableShape::from_index(get_usize(t, key, "table")?),
1467 octave: get_usize(t, key, "oct")? as i8 - 2,
1468 morph: get_f64(t, key, "morph")?,
1469 mod_depth: get_f64(t, key, "mdepth")?,
1470 modulation: decode_new_mod(t, &mod_key(key))?,
1471 }),
1472 4 => Ok(AudioNode::Pluck {
1473 uid: Uid::NEW,
1474 octave: get_usize(t, key, "oct")? as i8 - 2,
1475 damping: get_f64(t, key, "damp")?,
1476 brightness: get_f64(t, key, "bright")?,
1477 mod_depth: get_f64(t, key, "mdepth")?,
1478 modulation: decode_new_mod(t, &mod_key(key))?,
1479 }),
1480 5 => Ok(AudioNode::Formant {
1481 uid: Uid::NEW,
1482 vowel: get_f64(t, key, "vowel")?,
1483 shift: get_f64(t, key, "fshift")?,
1484 octave: get_usize(t, key, "oct")? as i8 - 2,
1485 mod_depth: get_f64(t, key, "mdepth")?,
1486 modulation: decode_mod(t, &mod_key(key))?,
1487 }),
1488 6 => Ok(AudioNode::Silence { uid: Uid::NEW }),
1489 k => Err(GenomeError::InvalidStructure(format!(
1490 "source kind {k} out of range at {key}"
1491 ))),
1492 }
1493 } else {
1494 match get_usize(t, key, "op")? {
1495 0 => Ok(AudioNode::Mix {
1496 uid: Uid::NEW,
1497 balance: get_f64(t, key, "bal")?,
1498 a: Box::new(decode_node(t, &child_key(key, 0))?),
1499 b: Box::new(decode_node(t, &child_key(key, 1))?),
1500 }),
1501 1 => Ok(AudioNode::Filter {
1502 uid: Uid::NEW,
1503 kind: FilterKind::from_index(get_usize(t, key, "fkind")?),
1504 cutoff: get_f64(t, key, "cut")?,
1505 resonance: get_f64(t, key, "res")?,
1506 mod_depth: get_f64(t, key, "mdepth")?,
1507 modulation: decode_mod(t, &mod_key(key))?,
1508 input: Box::new(decode_node(t, &child_key(key, 0))?),
1509 }),
1510 2 => Ok(AudioNode::Fold {
1511 uid: Uid::NEW,
1512 threshold: get_f64(t, key, "thresh")?,
1513 mod_depth: get_f64(t, key, "mdepth")?,
1514 modulation: decode_mod(t, &mod_key(key))?,
1515 input: Box::new(decode_node(t, &child_key(key, 0))?),
1516 }),
1517 3 => Ok(AudioNode::Delay {
1518 uid: Uid::NEW,
1519 time: get_f64(t, key, "time")?,
1520 feedback: get_f64(t, key, "fb")?,
1521 mix: get_f64(t, key, "dmix")?,
1522 mod_depth: get_f64_or(t, key, "mdepth", DEFAULT_MOD_DEPTH),
1523 modulation: decode_new_mod(t, &mod_key(key))?,
1524 input: Box::new(decode_node(t, &child_key(key, 0))?),
1525 }),
1526 4 => Ok(AudioNode::Chorus {
1527 uid: Uid::NEW,
1528 rate: get_f64(t, key, "crate")?,
1529 depth: get_f64(t, key, "cdepth")?,
1530 mix: get_f64(t, key, "cmix")?,
1531 mod_depth: get_f64_or(t, key, "mdepth", DEFAULT_MOD_DEPTH),
1532 modulation: decode_new_mod(t, &mod_key(key))?,
1533 input: Box::new(decode_node(t, &child_key(key, 0))?),
1534 }),
1535 5 => Ok(AudioNode::Reverb {
1536 uid: Uid::NEW,
1537 size: get_f64(t, key, "rsize")?,
1538 damp: get_f64(t, key, "rdamp")?,
1539 mix: get_f64(t, key, "rmix")?,
1540 mod_depth: get_f64_or(t, key, "mdepth", DEFAULT_MOD_DEPTH),
1541 modulation: decode_new_mod(t, &mod_key(key))?,
1542 input: Box::new(decode_node(t, &child_key(key, 0))?),
1543 }),
1544 6 => Ok(AudioNode::Distortion {
1545 uid: Uid::NEW,
1546 drive: get_f64(t, key, "drive")?,
1547 tone: get_f64(t, key, "tone")?,
1548 mode: DriveMode::from_index(get_usize(t, key, "dmode")?),
1549 mod_depth: get_f64(t, key, "mdepth")?,
1550 modulation: decode_mod(t, &mod_key(key))?,
1551 input: Box::new(decode_node(t, &child_key(key, 0))?),
1552 }),
1553 7 => Ok(AudioNode::Bitcrush {
1554 uid: Uid::NEW,
1555 bits: get_f64(t, key, "bits")?,
1556 downsample: get_f64(t, key, "dsamp")?,
1557 mod_depth: get_f64(t, key, "mdepth")?,
1558 modulation: decode_mod(t, &mod_key(key))?,
1559 input: Box::new(decode_node(t, &child_key(key, 0))?),
1560 }),
1561 8 => Ok(AudioNode::Phaser {
1562 uid: Uid::NEW,
1563 rate: get_f64(t, key, "prate")?,
1564 depth: get_f64(t, key, "pdepth")?,
1565 feedback: get_f64(t, key, "pfb")?,
1566 mod_depth: get_f64(t, key, "mdepth")?,
1567 modulation: decode_mod(t, &mod_key(key))?,
1568 input: Box::new(decode_node(t, &child_key(key, 0))?),
1569 }),
1570 9 => Ok(AudioNode::RingMod {
1571 uid: Uid::NEW,
1572 mix: get_f64(t, key, "rgmix")?,
1573 a: Box::new(decode_node(t, &child_key(key, 0))?),
1574 b: Box::new(decode_node(t, &child_key(key, 1))?),
1575 }),
1576 10 => Ok(AudioNode::Flanger {
1577 uid: Uid::NEW,
1578 rate: get_f64(t, key, "frate")?,
1579 depth: get_f64(t, key, "fdepth")?,
1580 feedback: get_f64(t, key, "ffb")?,
1581 mod_depth: get_f64(t, key, "mdepth")?,
1582 modulation: decode_mod(t, &mod_key(key))?,
1583 input: Box::new(decode_node(t, &child_key(key, 0))?),
1584 }),
1585 11 => Ok(AudioNode::Tremolo {
1586 uid: Uid::NEW,
1587 rate: get_f64(t, key, "trate")?,
1588 depth: get_f64(t, key, "tdepth")?,
1589 shape: get_f64(t, key, "tshape")?,
1590 mod_depth: get_f64(t, key, "mdepth")?,
1591 modulation: decode_mod(t, &mod_key(key))?,
1592 input: Box::new(decode_node(t, &child_key(key, 0))?),
1593 }),
1594 12 => Ok(AudioNode::Vibrato {
1595 uid: Uid::NEW,
1596 rate: get_f64(t, key, "vrate")?,
1597 depth: get_f64(t, key, "vdepth")?,
1598 mix: get_f64(t, key, "vmix")?,
1599 mod_depth: get_f64(t, key, "mdepth")?,
1600 modulation: decode_mod(t, &mod_key(key))?,
1601 input: Box::new(decode_node(t, &child_key(key, 0))?),
1602 }),
1603 13 => Ok(AudioNode::Eq {
1604 uid: Uid::NEW,
1605 low: get_f64(t, key, "low")?,
1606 mid: get_f64(t, key, "mid")?,
1607 high: get_f64(t, key, "high")?,
1608 mod_depth: get_f64(t, key, "mdepth")?,
1609 modulation: decode_mod(t, &mod_key(key))?,
1610 input: Box::new(decode_node(t, &child_key(key, 0))?),
1611 }),
1612 14 => Ok(AudioNode::Granular {
1613 uid: Uid::NEW,
1614 position: get_f64(t, key, "gpos")?,
1615 size: get_f64(t, key, "gsize")?,
1616 density: get_f64(t, key, "gdens")?,
1617 mod_depth: get_f64(t, key, "mdepth")?,
1618 modulation: decode_mod(t, &mod_key(key))?,
1619 input: Box::new(decode_node(t, &child_key(key, 0))?),
1620 }),
1621 15 => Ok(AudioNode::Shift {
1622 uid: Uid::NEW,
1623 semis: get_f64(t, key, "semis")?,
1624 window: get_f64(t, key, "window")?,
1625 mix: get_f64(t, key, "smix")?,
1626 mod_depth: get_f64(t, key, "mdepth")?,
1627 modulation: decode_mod(t, &mod_key(key))?,
1628 input: Box::new(decode_node(t, &child_key(key, 0))?),
1629 }),
1630 16 => Ok(AudioNode::Comp {
1631 uid: Uid::NEW,
1632 threshold: get_f64(t, key, "thresh")?,
1633 ratio: get_f64(t, key, "ratio")?,
1634 makeup: get_f64(t, key, "makeup")?,
1635 mod_depth: get_f64(t, key, "mdepth")?,
1636 modulation: decode_mod(t, &mod_key(key))?,
1637 input: Box::new(decode_node(t, &child_key(key, 0))?),
1638 sidechain: Box::new(decode_node(t, &child_key(key, 1))?),
1639 }),
1640 17 => Ok(AudioNode::Duck {
1641 uid: Uid::NEW,
1642 amount: get_f64(t, key, "amount")?,
1643 threshold: get_f64(t, key, "dthresh")?,
1644 release: get_f64(t, key, "drel")?,
1645 mod_depth: get_f64(t, key, "mdepth")?,
1646 modulation: decode_mod(t, &mod_key(key))?,
1647 input: Box::new(decode_node(t, &child_key(key, 0))?),
1648 key: Box::new(decode_node(t, &child_key(key, 1))?),
1649 }),
1650 18 => Ok(AudioNode::Gate {
1651 uid: Uid::NEW,
1652 threshold: get_f64(t, key, "gthresh")?,
1653 range: get_f64(t, key, "range")?,
1654 release: get_f64(t, key, "grel")?,
1655 mod_depth: get_f64(t, key, "mdepth")?,
1656 modulation: decode_mod(t, &mod_key(key))?,
1657 input: Box::new(decode_node(t, &child_key(key, 0))?),
1658 sidechain: Box::new(decode_node(t, &child_key(key, 1))?),
1659 }),
1660 19 => Ok(AudioNode::Vocoder {
1661 uid: Uid::NEW,
1662 bands: get_f64(t, key, "bands")?,
1663 attack: get_f64(t, key, "vatt")?,
1664 release: get_f64(t, key, "vrel")?,
1665 mod_depth: get_f64(t, key, "mdepth")?,
1666 modulation: decode_mod(t, &mod_key(key))?,
1667 carrier: Box::new(decode_node(t, &child_key(key, 0))?),
1668 modulator: Box::new(decode_node(t, &child_key(key, 1))?),
1669 }),
1670 k => Err(GenomeError::InvalidStructure(format!(
1671 "op kind {k} out of range at {key}"
1672 ))),
1673 }
1674 }
1675}
1676
1677impl TraceGenome for PatchTree {
1678 fn to_trace(&self) -> Trace {
1679 let mut t = Trace::default();
1680 put_f64(&mut t, "amp", "attack", self.amp.attack);
1681 put_f64(&mut t, "amp", "decay", self.amp.decay);
1682 put_f64(&mut t, "amp", "sustain", self.amp.sustain);
1683 put_f64(&mut t, "amp", "release", self.amp.release);
1684 encode_node(&self.root, "node", &mut t);
1685 t
1686 }
1687
1688 fn from_trace(trace: &Trace) -> Result<Self, GenomeError> {
1689 Ok(PatchTree {
1690 amp: AmpEnv {
1691 attack: get_f64(trace, "amp", "attack")?,
1692 decay: get_f64(trace, "amp", "decay")?,
1693 sustain: get_f64(trace, "amp", "sustain")?,
1694 release: get_f64(trace, "amp", "release")?,
1695 },
1696 root: decode_node(trace, "node")?,
1697 })
1698 }
1699
1700 fn trace_prefix() -> &'static str {
1701 "node"
1702 }
1703}
1704
1705pub const PARAM_DOMAIN: std::ops::RangeInclusive<f64> = 0.0..=1.0;
1717
1718pub fn in_domain(v: f64) -> bool {
1723 v.is_finite() && PARAM_DOMAIN.contains(&v)
1724}
1725
1726impl PatchTree {
1727 pub fn domain_violations(&self) -> Vec<(String, f64)> {
1737 let mut out: Vec<(String, f64)> = self
1738 .to_trace()
1739 .choices
1740 .iter()
1741 .filter_map(|(a, c)| match c.value {
1742 ChoiceValue::F64(v) if !in_domain(v) => Some((a.to_string(), v)),
1743 _ => None,
1744 })
1745 .collect();
1746 out.sort_by(|a, b| a.0.cmp(&b.0));
1747 out
1748 }
1749
1750 pub fn clamp_domains(&mut self) -> usize {
1770 let mut trace = self.to_trace();
1771 let mut fixed = 0usize;
1772 for c in trace.choices.values_mut() {
1773 if let ChoiceValue::F64(v) = c.value {
1774 if !in_domain(v) {
1775 let repaired = if v.is_nan() {
1776 (PARAM_DOMAIN.start() + PARAM_DOMAIN.end()) / 2.0
1777 } else {
1778 v.clamp(*PARAM_DOMAIN.start(), *PARAM_DOMAIN.end())
1779 };
1780 c.value = ChoiceValue::F64(repaired);
1781 fixed += 1;
1782 }
1783 }
1784 }
1785 if fixed == 0 {
1786 return 0;
1787 }
1788 if let Ok(mut repaired) = PatchTree::from_trace(&trace) {
1794 repaired.inherit_uids(self);
1795 *self = repaired;
1796 }
1797 fixed
1798 }
1799}
1800
1801#[cfg(test)]
1802mod tests {
1803 use super::*;
1804 use crate::term::FilterKind;
1805
1806 #[test]
1815 fn a_v1_trace_still_decodes() {
1816 let mut t = Trace::default();
1817 for (site, v) in [
1818 ("attack", 0.1),
1819 ("decay", 0.3),
1820 ("sustain", 0.6),
1821 ("release", 0.2),
1822 ] {
1823 put_f64(&mut t, "amp", site, v);
1824 }
1825 put_bool(&mut t, "node", "leaf", false);
1827 put_usize(&mut t, "node", "op", 3);
1828 put_f64(&mut t, "node", "time", 0.6);
1829 put_f64(&mut t, "node", "fb", 0.4);
1830 put_f64(&mut t, "node", "dmix", 0.35);
1831 put_bool(&mut t, "node/0", "leaf", false);
1833 put_usize(&mut t, "node/0", "op", 1);
1834 put_usize(&mut t, "node/0", "fkind", 3);
1835 put_f64(&mut t, "node/0", "cut", 0.5);
1836 put_f64(&mut t, "node/0", "res", 0.4);
1837 put_f64(&mut t, "node/0", "mdepth", 0.5);
1838 put_usize(&mut t, "node/0/m", "mod", 3);
1839 put_f64(&mut t, "node/0/m", "rate", 0.62);
1840 put_bool(&mut t, "node/0/0", "leaf", true);
1842 put_usize(&mut t, "node/0/0", "src", 0);
1843 put_usize(&mut t, "node/0/0", "wave", 2);
1844 put_usize(&mut t, "node/0/0", "oct", 1);
1845 put_f64(&mut t, "node/0/0", "det", 0.5);
1846
1847 let tree = PatchTree::from_trace(&t).expect("a v1 trace must still load");
1848 let AudioNode::Delay {
1849 mod_depth,
1850 modulation,
1851 input,
1852 ..
1853 } = &tree.root
1854 else {
1855 panic!("decoded the wrong node: {}", tree.root.to_sexpr());
1856 };
1857 assert_eq!(*mod_depth, 0.3, "new mod depth did not default");
1858 assert_eq!(*modulation, ModNode::None, "absent slot must decode empty");
1859 let AudioNode::Filter {
1860 kind, modulation, ..
1861 } = &**input
1862 else {
1863 panic!("decoded the wrong child: {}", input.to_sexpr());
1864 };
1865 assert_eq!(*kind, FilterKind::Ladder);
1866 assert_eq!(
1867 *modulation,
1868 ModNode::Rand {
1869 uid: Uid::NEW,
1870 rate: 0.62,
1871 glide: 0.0
1872 },
1873 "a v1 S&H must come back as hard steps"
1874 );
1875 let AudioNode::Filter { input, .. } = &**input else {
1880 unreachable!("checked above")
1881 };
1882 assert_eq!(
1883 **input,
1884 AudioNode::Vco {
1885 uid: Uid::NEW,
1886 wave: Waveform::Saw,
1887 octave: -1,
1888 detune: 0.5,
1889 mod_depth: DEFAULT_MOD_DEPTH,
1890 modulation: ModNode::None,
1891 },
1892 "a v1 vco must decode with its pitch slot empty"
1893 );
1894
1895 let back = PatchTree::from_trace(&tree.to_trace()).expect("re-encoded trace decodes");
1898 assert_eq!(back, tree);
1899 }
1900}
1901
1902#[cfg(test)]
1903mod domain_tests {
1904 use super::*;
1905 use crate::mutate::{apply_struct_op, validate_tree, StructOp};
1906 use crate::term::{FilterKind, Waveform};
1907 use rand::rngs::StdRng;
1908 use rand::SeedableRng;
1909
1910 fn filter_over_vco(cutoff: f64) -> PatchTree {
1911 PatchTree {
1912 amp: AmpEnv {
1913 attack: 0.1,
1914 decay: 0.3,
1915 sustain: 0.6,
1916 release: 0.2,
1917 },
1918 root: AudioNode::Filter {
1919 uid: Uid(7),
1920 kind: FilterKind::SvfBp,
1921 cutoff,
1922 resonance: 0.4,
1923 mod_depth: 0.5,
1924 input: Box::new(AudioNode::Vco {
1925 uid: Uid(9),
1926 wave: Waveform::Saw,
1927 octave: 0,
1928 detune: 0.5,
1929 mod_depth: 0.3,
1930 modulation: ModNode::None,
1931 }),
1932 modulation: ModNode::None,
1933 },
1934 }
1935 }
1936
1937 #[test]
1942 fn every_prior_draw_is_in_domain() {
1943 let prior = PatchGrammarPrior::default();
1944 let mut rng = StdRng::seed_from_u64(20260802);
1945 for _ in 0..400 {
1946 let t = prior.sample_with_rng(&mut rng);
1947 assert!(
1948 t.domain_violations().is_empty(),
1949 "the prior drew an out-of-domain site: {:?}",
1950 t.domain_violations()
1951 );
1952 }
1953 }
1954
1955 #[test]
1961 fn clamp_repairs_the_sentinel_and_keeps_identity() {
1962 let mut t = filter_over_vco(1e30);
1963 t.amp.sustain = 1e30;
1964 assert_eq!(t.domain_violations().len(), 2);
1965
1966 assert_eq!(t.clamp_domains(), 2);
1967 assert!(t.domain_violations().is_empty());
1968 assert_eq!(t.amp.sustain, 1.0);
1969 assert_eq!(t.amp.attack, 0.1, "a clean site must not move");
1970 let AudioNode::Filter {
1971 uid,
1972 cutoff,
1973 resonance,
1974 input,
1975 ..
1976 } = &t.root
1977 else {
1978 panic!("the repair changed the term's shape");
1979 };
1980 assert_eq!(*cutoff, 1.0);
1981 assert_eq!(*resonance, 0.4);
1982 assert_eq!(*uid, Uid(7), "the repair reissued an identity");
1983 let AudioNode::Vco { uid, .. } = &**input else {
1984 panic!("the repair changed the child");
1985 };
1986 assert_eq!(*uid, Uid(9));
1987
1988 assert_eq!(t.clamp_domains(), 0);
1990 }
1991
1992 #[test]
1995 fn nan_lands_mid_range() {
1996 let mut t = filter_over_vco(f64::NAN);
1997 assert_eq!(t.clamp_domains(), 1);
1998 let AudioNode::Filter { cutoff, .. } = &t.root else {
1999 unreachable!()
2000 };
2001 assert_eq!(*cutoff, 0.5);
2002 }
2003
2004 #[test]
2008 fn validate_tree_refuses_an_out_of_domain_site() {
2009 assert!(validate_tree(&filter_over_vco(0.6)).is_ok());
2010 let err = validate_tree(&filter_over_vco(1e30)).expect_err("must refuse");
2011 assert!(
2012 err.contains("node#cut"),
2013 "the reason must name the site: {err}"
2014 );
2015 assert!(err.contains("out of range"), "{err}");
2016 }
2017
2018 #[test]
2022 fn an_explicit_fragment_cannot_seat_a_bad_value() {
2023 let host = filter_over_vco(0.6);
2024 let bad = AudioNode::Fold {
2025 uid: Uid::NEW,
2026 threshold: 1e30,
2027 mod_depth: 0.3,
2028 input: Box::new(AudioNode::Noise {
2029 uid: Uid::NEW,
2030 color: crate::term::NoiseColor::White,
2031 }),
2032 modulation: ModNode::None,
2033 };
2034 let out = apply_struct_op(
2035 &host,
2036 &StructOp::InsertTree {
2037 key: "node/0".into(),
2038 node: bad,
2039 },
2040 )
2041 .expect("a repairable fragment must still land");
2042 assert!(
2043 out.domain_violations().is_empty(),
2044 "finish() seated {:?}",
2045 out.domain_violations()
2046 );
2047 }
2048
2049 #[test]
2057 fn silence_round_trips_at_source_index_six() {
2058 let tree = PatchTree {
2059 amp: crate::term::AmpEnv {
2060 attack: 0.1,
2061 decay: 0.3,
2062 sustain: 0.6,
2063 release: 0.2,
2064 },
2065 root: AudioNode::Mix {
2066 uid: Uid::NEW,
2067 balance: 0.5,
2068 a: Box::new(AudioNode::Silence { uid: Uid::NEW }),
2069 b: Box::new(AudioNode::Noise {
2070 uid: Uid::NEW,
2071 color: crate::term::NoiseColor::White,
2072 }),
2073 },
2074 };
2075
2076 let t = tree.to_trace();
2077 assert_eq!(
2078 get_usize(&t, "node/0", "src").expect("a source index"),
2079 6,
2080 "Silence must stay source index 6 — the index is the wire format"
2081 );
2082 assert_eq!(
2084 t.choices.keys().filter(|k| k.starts_with("node/0")).count(),
2085 2,
2086 "Silence should write only #leaf and #src"
2087 );
2088
2089 let back = PatchTree::from_trace(&t).expect("round trips");
2090 assert_eq!(back.to_sexpr(), tree.to_sexpr());
2091 }
2092}