1#![no_std]
2
3extern crate smallvec;
4use smallvec::SmallVec;
5
6pub struct SyncDevice {
7 pub tracks: SmallVec<[SyncTrack; 64]>,
9 pub rpb: u8,
11 pub bpm: f64,
13 pub rps: f64,
15 pub is_paused: bool,
16 pub row: u32,
18 pub time: u32,
20}
21
22impl SyncDevice {
23 pub fn new(bpm: f64, rpb: u8) -> SyncDevice {
24 SyncDevice {
25 tracks: SmallVec::new(),
26 rpb: rpb,
27 bpm: bpm,
28 rps: rps(bpm, rpb),
29 is_paused: true,
30 row: 0,
31 time: 0,
32 }
33 }
34
35 pub fn set_row_from_time(&mut self) {
36 let r: f64 = (self.time as f64 / 1000.0) * self.rps + 0.5;
37 self.row = r as u32;
38 }
39
40 pub fn get_track_value(&self, track_id: usize) -> Result<f64, SyncError> {
41 if self.tracks.len() > track_id {
42 return Ok(self.tracks[track_id].value_at(self.row));
43 } else {
44 return Err(SyncError::TrackDoesntExist);
45 }
46 }
47}
48
49pub struct SyncTrack {
50 pub keys: SmallVec<[TrackKey; 64]>,
52}
53
54pub enum SyncError {
55 TrackDoesntExist
56}
57
58pub struct TrackKey {
59 pub row: u32,
60 pub value: f32,
61 pub key_type: KeyType,
63}
64
65pub enum KeyType {
66 Step, Linear, Smooth, Ramp, NOOP,
71}
72
73pub enum ActiveKeyIdx {
74 ExactRow(usize),
76 PrevRow(usize),
78 BeforeFirstRow,
80 AfterLastRow,
82}
83
84impl SyncTrack {
85 pub fn new() -> SyncTrack {
86 SyncTrack {
87 keys: SmallVec::new(),
88 }
89 }
90
91 pub fn add_key(&mut self, track_key: TrackKey) {
93
94 let res = self.find_active_key_idx_for_row(track_key.row);
95
96 if let Some(idx) = res {
97 use self::ActiveKeyIdx::*;
99 match idx {
100 ExactRow(n) => self.keys[n] = track_key,
102
103 PrevRow(n) => self.keys.insert(n+1, track_key),
105 BeforeFirstRow => self.keys.insert(0, track_key),
106 AfterLastRow => self.keys.push(track_key),
107 }
108 } else {
109 self.keys.push(track_key);
111 }
112 }
113
114 pub fn delete_key(&mut self, row: u32) {
116 if let Some(idx) = self.find_key_idx_by_row(row) {
117 self.keys.remove(idx);
118 }
119 }
120
121 pub fn find_key_idx_by_row(&self, row: u32) -> Option<usize> {
123 for (idx, key) in self.keys.iter().enumerate() {
124 if key.row == row {
125 return Some(idx);
126 }
127 }
128
129 None
130 }
131
132 pub fn value_at(&self, row: u32) -> f64 {
133
134 let hit_idx: usize;
135
136 if let Some(hit) = self.find_active_key_idx_for_row(row) {
137 use self::ActiveKeyIdx::*;
138 match hit {
139 ExactRow(n) => return self.keys[n].value as f64,
140
141 PrevRow(n) => hit_idx = n,
142
143 AfterLastRow => return self.keys[self.keys.len() - 1].value as f64,
145
146 BeforeFirstRow => return self.keys[0].value as f64,
147 }
148 } else {
149 return 0.0;
150 }
151
152 let cur_key = &self.keys[hit_idx];
154 let next_key = &self.keys[hit_idx + 1];
155
156 let t: f64 = ((row - cur_key.row) as f64) / ((next_key.row - cur_key.row) as f64);
157 let a: f64 = cur_key.value as f64;
158 let b: f64 = (next_key.value - cur_key.value) as f64;
159
160 use self::KeyType::*;
161 match cur_key.key_type {
162 Step => return a,
163
164 Linear => return a + b * t,
165
166 Smooth => return a + b * (t*t * (3.0 - 2.0 * t)),
167
168 Ramp => return a + b * t*t,
169
170 NOOP => return 0.0,
171 }
172
173 }
174
175 pub fn find_active_key_idx_for_row(&self, row: u32) -> Option<ActiveKeyIdx> {
177 if self.keys.len() == 0 {
178 return None;
179 }
180
181 let mut hit_idx: usize = 0;
184 let mut ret: Option<ActiveKeyIdx> = None;
185
186 for (idx, key) in self.keys.iter().enumerate() {
187 if key.row == row {
188 return Some(ActiveKeyIdx::ExactRow(idx));
189 } else if key.row < row {
190 hit_idx = idx;
191 ret = Some(ActiveKeyIdx::PrevRow(hit_idx));
192 }
193 }
194
195 if hit_idx == self.keys.len() - 1 {
196 return Some(ActiveKeyIdx::AfterLastRow);
197 }
198
199 if hit_idx == 0 && ret.is_none() {
200 return Some(ActiveKeyIdx::BeforeFirstRow);
201 }
202
203 ret
204 }
205}
206
207impl TrackKey {
208 pub fn new() -> TrackKey {
209 TrackKey {
210 row: 0,
211 value: 0.0,
212 key_type: KeyType::Step,
213 }
214 }
215}
216
217pub fn rps(bpm: f64, rpb: u8) -> f64 {
219 (bpm / 60.0) * (rpb as f64)
220}
221
222pub fn key_to_code(key: &KeyType) -> u8 {
223 use self::KeyType::*;
224 match *key {
225 Step => 0,
226 Linear => 1,
227 Smooth => 2,
228 Ramp => 3,
229 NOOP => 255,
230 }
231}
232
233pub fn code_to_key(code: u8) -> KeyType {
234 use self::KeyType::*;
235 match code {
236 0 => Step,
237 1 => Linear,
238 2 => Smooth,
239 3 => Ramp,
240 _ => NOOP,
241 }
242}