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 => current,
29 StepPlayMode::Random => {
30 use rand::Rng;
31 let mut rng = rand::thread_rng();
32 rng.gen_range(0..len)
33 }
34 StepPlayMode::Brownian => {
35 use rand::Rng;
36 let mut rng = rand::thread_rng();
37 let offset: isize = rng.gen_range(-1..=1);
38 let next = current as isize + offset;
39 next.clamp(0, len.saturating_sub(1) as isize) as usize
40 }
41 }
42 }
43}
44
45#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
47#[derive(Debug, Clone)]
48pub struct Pattern {
49 pub id: String,
51 pub steps: Vec<SequenceStep>,
53 pub play_mode: StepPlayMode,
55}
56
57impl Pattern {
58 pub fn new(id: impl Into<String>, steps: Vec<SequenceStep>) -> Self {
60 Self {
61 id: id.into(),
62 steps,
63 play_mode: StepPlayMode::Loop,
64 }
65 }
66
67 pub fn with_mode(mut self, mode: StepPlayMode) -> Self {
69 self.play_mode = mode;
70 self
71 }
72
73 pub fn is_empty(&self) -> bool {
75 self.steps.is_empty()
76 }
77
78 pub fn len(&self) -> usize {
80 self.steps.len()
81 }
82}