1use super::signal::*;
2use crate::{as_any_mut, std_signal};
3use pitch_calc::{hz_from_letter_octave, Letter, LetterOctave, Octave};
4use std::any::Any;
5use rand::thread_rng;
6use rand::seq::SliceRandom;
7
8fn tick(clock: Real, seq_len: usize, bps: Real, sample_rate: Real) -> Real {
9 let n = seq_len as Real;
10 (clock + 1.0) % (sample_rate / bps * n)
11}
12
13fn idx(clock: Real, bps: Real, sample_rate: Real) -> usize {
14 (clock / sample_rate * bps) as usize
15}
16
17#[derive(Clone)]
18pub struct Note {
19 pitch: LetterOctave,
20 gate: bool,
21}
22
23impl Note {
24 pub fn new(letter: Letter, octave: Octave, gate: bool) -> Self {
25 Self {
26 pitch: LetterOctave(letter, octave),
27 gate,
28 }
29 }
30}
31
32#[derive(Clone)]
33pub struct Sequencer {
34 sequence: Vec<Note>,
35 bpm: In, clock: Real,
37}
38
39impl Sequencer {
40 pub fn new() -> Self {
41 Sequencer {
42 sequence: vec![],
43 bpm: 120.into(),
44 clock: 0.0,
45 }
46 }
47
48 pub fn sequence(&mut self, arg: Vec<Note>) -> &mut Self {
49 self.sequence = arg;
50 self
51 }
52
53 pub fn bpm<T: Into<In>>(&mut self, arg: T) -> &mut Self {
54 self.bpm = arg.into();
55 self
56 }
57}
58
59impl Builder for Sequencer {}
60
61#[derive(Clone)]
62pub struct PitchSeq {
63 tag: Tag,
64 seq: Sequencer,
65}
66
67impl PitchSeq {
68 pub fn new(seq: Sequencer) -> Self {
69 Self { tag: mk_tag(), seq }
70 }
71}
72
73impl Builder for PitchSeq {}
74
75impl Signal for PitchSeq {
76 std_signal!();
77 fn signal(&mut self, rack: &Rack, sample_rate: Real) -> Real {
78 let bps = In::val(&rack, self.seq.bpm) / 60.0;
79 let idx = idx(self.seq.clock, bps, sample_rate);
80 if idx == 0 {
81 let mut rng = thread_rng();
82 self.seq.sequence.shuffle(&mut rng);
83 }
84 self.seq.clock = tick(self.seq.clock, self.seq.sequence.len(), bps, sample_rate);
85 let LetterOctave(letter, octave) = self.seq.sequence[idx].pitch;
86 hz_from_letter_octave(letter, octave) as Real
87 }
88}
89
90#[derive(Clone)]
91pub struct GateSeq {
92 tag: Tag,
93 seq: Sequencer,
94}
95
96impl GateSeq {
97 pub fn new(seq: Sequencer) -> Self {
98 Self { tag: mk_tag(), seq }
99 }
100}
101
102impl Builder for GateSeq {}
103
104impl Signal for GateSeq {
105 std_signal!();
106 fn signal(&mut self, rack: &Rack, sample_rate: Real) -> Real {
107 let bps = In::val(&rack, self.seq.bpm) / 60.0;
108 let idx = idx(self.seq.clock, bps, sample_rate);
109 self.seq.clock = tick(self.seq.clock, self.seq.sequence.len(), bps, sample_rate);
110 self.seq.sequence[idx].gate as usize as Real
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117 use crate::utils::signals;
118 use pitch_calc::Letter;
119
120 #[test]
121 fn pitch_seq() {
122 let notes: Vec<Note> = vec![
123 Note::new(Letter::A, 2, true),
124 Note::new(Letter::A, 3, false),
125 Note::new(Letter::A, 4, true),
126 Note::new(Letter::A, 5, false),
127 ];
128 let seq: Sequencer = Sequencer::new().sequence(notes).build();
129 let mut ps = PitchSeq::new(seq);
130 let sigs = signals(&mut ps, 0, 16, 4.0);
131 let s0 = sigs[0].1.round();
132 let s1 = sigs[1].1.round();
133 let s2 = sigs[2].1.round();
134 let s14 = sigs[14].1.round();
135
136 assert_eq!(s0, 110.0, "0 - Expected 110 actual: {}", s0);
137 assert_eq!(s1, 110.0, "1 - Expected 110 actual: {}", s1);
138 assert_eq!(s2, 220.0, "2 - Expected 220 actual: {}", s2);
139 assert_eq!(s14, 880.0, "14 - Expected 880 actual: {}", s14);
140 }
141
142 #[test]
143 fn gate_seq() {
144 let notes: Vec<Note> = vec![
145 Note::new(Letter::A, 2, true),
146 Note::new(Letter::A, 3, false),
147 Note::new(Letter::A, 4, true),
148 Note::new(Letter::A, 5, false),
149 ];
150 let seq: Sequencer = Sequencer::new().sequence(notes).build();
151 let mut ps = GateSeq::new(seq);
152 let sigs = signals(&mut ps, 0, 16, 4.0);
153 let s0 = sigs[0].1;
154 let s1 = sigs[1].1;
155 let s2 = sigs[2].1;
156 let s14 = sigs[14].1;
157
158 assert_eq!(s0, 1.0, "0 - Expected true actual: {}", s0);
159 assert_eq!(s1, 1.0, "1 - Expected true actual: {}", s1);
160 assert_eq!(s2, 0.0, "2 - Expected false actual: {}", s2);
161 assert_eq!(s14, 0.0, "14 - Expected true actual: {}", s14);
162 }
163}