rill_patchbay/sequencer/
pattern.rs1use super::step::SequenceStep;
2
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5#[derive(Debug, Clone, Copy, PartialEq)]
6pub enum StepPlayMode {
7 OneShot,
9 Loop,
11 PingPong,
13 Random,
15 Brownian,
17}
18
19impl StepPlayMode {
20 pub fn next_index(&self, current: usize, len: usize) -> usize {
22 if len == 0 {
23 return 0;
24 }
25 match self {
26 StepPlayMode::OneShot => current.min(len.saturating_sub(1)),
27 StepPlayMode::Loop => (current + 1) % len,
28 StepPlayMode::PingPong => {
29 current
30 }
31 StepPlayMode::Random => {
32 use rand::Rng;
33 let mut rng = rand::thread_rng();
34 rng.gen_range(0..len)
35 }
36 StepPlayMode::Brownian => {
37 use rand::Rng;
38 let mut rng = rand::thread_rng();
39 let offset: isize = rng.gen_range(-1..=1);
40 let next = current as isize + offset;
41 next.clamp(0, len.saturating_sub(1) as isize) as usize
42 }
43 }
44 }
45}
46
47#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
49#[derive(Debug, Clone)]
50pub struct Pattern {
51 pub id: String,
53 pub steps: Vec<SequenceStep>,
55 pub play_mode: StepPlayMode,
57}
58
59impl Pattern {
60 pub fn new(id: impl Into<String>, steps: Vec<SequenceStep>) -> Self {
62 Self {
63 id: id.into(),
64 steps,
65 play_mode: StepPlayMode::Loop,
66 }
67 }
68
69 pub fn with_mode(mut self, mode: StepPlayMode) -> Self {
71 self.play_mode = mode;
72 self
73 }
74
75 pub fn is_empty(&self) -> bool {
77 self.steps.is_empty()
78 }
79
80 pub fn len(&self) -> usize {
82 self.steps.len()
83 }
84}