rill_patchbay/automaton/
mod.rs1pub mod cellular;
11pub mod envelope;
12pub mod function;
13pub mod lfo;
14pub mod random;
15pub mod sequencer;
16
17pub use cellular::*;
18pub use envelope::*;
19pub use function::*;
20pub use lfo::*;
21pub use random::*;
22pub use sequencer::*;
23
24use std::fmt::Debug;
25
26#[derive(Debug, Clone, Copy, PartialEq)]
32pub enum SyncMode {
33 Free,
34 Sync,
35 OneShot,
36}
37
38#[derive(Debug, Clone, Copy)]
40pub struct Range {
41 pub min: f64,
42 pub max: f64,
43}
44
45impl Range {
46 pub const fn new(min: f64, max: f64) -> Self {
47 Self { min, max }
48 }
49
50 pub const fn unipolar() -> Self {
51 Self { min: 0.0, max: 1.0 }
52 }
53
54 pub const fn bipolar() -> Self {
55 Self {
56 min: -1.0,
57 max: 1.0,
58 }
59 }
60
61 pub fn clamp(&self, value: f64) -> f64 {
62 value.clamp(self.min, self.max)
63 }
64
65 pub fn normalize(&self, value: f64) -> f64 {
66 (value - self.min) / (self.max - self.min)
67 }
68
69 pub fn denormalize(&self, norm: f64) -> f64 {
70 self.min + norm * (self.max - self.min)
71 }
72}
73
74#[derive(Debug)]
80pub struct AutomatonComparison;
81
82impl AutomatonComparison {
83 pub fn types() -> &'static str {
85 "Типы автоматов:\n\
86 ┌─────────────────┬─────────────────────────────┬─────────────────┐\n\
87 │ Автомат │ Характеристики │ Применение │\n\
88 ├─────────────────┼─────────────────────────────┼─────────────────┤\n\
89 │ LFO │ Гармонические/релаксационные│ Вибрато, тремоло│\n\
90 │ Envelope │ ADSR, AR, ASR │ Амплитудные ог. │\n\
91 │ Function │ Произвольная функция времени│ Сложные модуляции│\n\
92 │ Sequencer │ Паттерны, ступени │ Ритмические │\n\
93 │ RandomWalk │ Случайные блуждания │ Генеративные │\n\
94 │ Chaos │ Детерминированный хаос │ Непредсказуемые │\n\
95 │ Cellular │ Клеточные автоматы │ Органические │\n\
96 └─────────────────┴─────────────────────────────┴─────────────────┘"
97 }
98
99 pub fn selection_guide() -> &'static str {
101 "Как выбрать автомат:\n\n\
102 🎯 **Периодическая модуляция**:\n\
103 → LFO (Sine, Triangle, Saw, Square)\n\n\
104 🎯 **Однократные события**:\n\
105 → Envelope (ADSR, AR, ASR)\n\n\
106 🎯 **Сложные функции**:\n\
107 → Function с произвольным замыканием\n\n\
108 🎯 **Ритмические паттерны**:\n\
109 → Sequencer с шагами и длительностями\n\n\
110 🎯 **Генеративные процессы**:\n\
111 → RandomWalk, Chaos, Cellular\n\n\
112 🎯 **Случайные значения**:\n\
113 → Sample & Hold (LFO в режиме S&H)"
114 }
115
116 pub fn performance_guide() -> &'static str {
118 "Производительность (относительная):\n\
119 ⚡ **Function** - 1x (простые функции)\n\
120 ⚡⚡ **LFO** - 2x (тригонометрия)\n\
121 ⚡⚡⚡ **Envelope** - 3x (логика переходов)\n\
122 ⚡⚡⚡ **RandomWalk** - 3x (RNG)\n\
123 ⚡⚡⚡⚡ **Sequencer** - 4x (паттерны)\n\
124 ⚡⚡⚡⚡ **Chaos** - 4x (итерации)\n\
125 ⚡⚡⚡⚡⚡ **Cellular** - 5x (соседи)"
126 }
127}
128
129#[cfg(test)]
134mod tests {
135 use crate::control::Automaton as _;
136
137 #[test]
138 fn test_automaton_types_are_debug() {
139 fn assert_debug<T: std::fmt::Debug>(_: &T) {}
141 let lfo = super::LfoAutomaton::new("test", 1.0, 1.0, 0.0, super::LfoWaveform::Sine);
142 assert_debug(&lfo);
143 let env = super::EnvelopeAutomaton::adsr("test", 0.1, 0.2, 0.7, 0.3);
144 assert_debug(&env);
145 let func = super::FunctionAutomaton::new("test", |t| t);
146 assert_debug(&func);
147 }
148
149 #[test]
150 fn test_comparison_guides() {
151 assert!(!super::AutomatonComparison::types().is_empty());
152 assert!(!super::AutomatonComparison::selection_guide().is_empty());
153 assert!(!super::AutomatonComparison::performance_guide().is_empty());
154 }
155}