pub mod cellular;
pub mod envelope;
pub mod function;
pub mod lfo;
pub mod random;
pub mod sequencer;
pub use cellular::*;
pub use envelope::*;
pub use function::*;
pub use lfo::*;
pub use random::*;
pub use sequencer::*;
use std::fmt::Debug;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SyncMode {
Free,
Sync,
OneShot,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, Copy)]
pub struct Range {
pub min: f64,
pub max: f64,
}
impl Range {
pub const fn new(min: f64, max: f64) -> Self {
Self { min, max }
}
pub const fn unipolar() -> Self {
Self { min: 0.0, max: 1.0 }
}
pub const fn bipolar() -> Self {
Self {
min: -1.0,
max: 1.0,
}
}
pub fn clamp(&self, value: f64) -> f64 {
value.clamp(self.min, self.max)
}
pub fn normalize(&self, value: f64) -> f64 {
(value - self.min) / (self.max - self.min)
}
pub fn denormalize(&self, norm: f64) -> f64 {
self.min + norm * (self.max - self.min)
}
}
#[derive(Debug)]
pub struct AutomatonComparison;
impl AutomatonComparison {
pub fn types() -> &'static str {
"Automaton types:\n\
┌─────────────────┬─────────────────────────────┬─────────────────┐\n\
│ Automaton │ Characteristics │ Application │\n\
├─────────────────┼─────────────────────────────┼─────────────────┤\n\
│ LFO │ Harmonic/relaxation │ Vibrato, tremolo│\n\
│ Envelope │ ADSR, AR, ASR │ Amplitude env. │\n\
│ Function │ Arbitrary time function │ Complex mod. │\n\
│ Sequencer │ Patterns, steps │ Rhythmic │\n\
│ RandomWalk │ Random walks │ Generative │\n\
│ Chaos │ Deterministic chaos │ Unpredictable │\n\
│ Cellular │ Cellular automata │ Organic │\n\
└─────────────────┴─────────────────────────────┴─────────────────┘"
}
pub fn selection_guide() -> &'static str {
"How to choose an automaton:\n\n\
Periodic modulation:\n\
→ LFO (Sine, Triangle, Saw, Square)\n\n\
One-shot events:\n\
→ Envelope (ADSR, AR, ASR)\n\n\
Complex functions:\n\
→ Function with arbitrary closure\n\n\
Rhythmic patterns:\n\
→ Sequencer with steps and durations\n\n\
Generative processes:\n\
→ RandomWalk, Chaos, Cellular\n\n\
Random values:\n\
→ Sample & Hold (LFO in S&H mode)"
}
pub fn performance_guide() -> &'static str {
"Relative performance:\n\
**Function** — fastest (simple functions)\n\
**LFO** — moderate (trigonometry)\n\
**Envelope** — moderate (transition logic)\n\
**RandomWalk** — moderate (RNG)\n\
**Sequencer** — slower (patterns)\n\
**Chaos** — slower (iterations)\n\
**Cellular** — slowest (neighbour lookups)"
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_automaton_types_are_debug() {
fn assert_debug<T: std::fmt::Debug>(_: &T) {}
let lfo = super::LfoAutomaton::new("test", 1.0, 1.0, 0.0, super::LfoWaveform::Sine);
assert_debug(&lfo);
let env = super::EnvelopeAutomaton::adsr("test", 0.1, 0.2, 0.7, 0.3);
assert_debug(&env);
let func = super::FunctionAutomaton::new("test", |t| t);
assert_debug(&func);
}
#[test]
fn test_comparison_guides() {
assert!(!super::AutomatonComparison::types().is_empty());
assert!(!super::AutomatonComparison::selection_guide().is_empty());
assert!(!super::AutomatonComparison::performance_guide().is_empty());
}
}