1pub mod trig;
3pub mod types;
5
6use self::{
7 trig::{HoldsTrigFlags, TrigFlags},
8 types::{PadScale, RootNote},
9};
10use super::{plock::ParameterLockPool, Length};
11use crate::{
12 defaults::default_trig_array,
13 error::{ParameterError, RytmError},
14 object::pattern::types::Speed,
15 util::{from_s_u16_t, to_s_u16_t_union_b},
16};
17use bitstream_io::{BigEndian, BitRead, BitReader, BitWrite, BitWriter};
18use derivative::Derivative;
19use parking_lot::Mutex;
20use rytm_rs_macro::parameter_range;
21use rytm_sys::ar_pattern_track_t;
22use serde::Serialize;
23use std::{io::Cursor, sync::Arc};
24use trig::Trig;
25
26#[derive(Derivative, Clone, Serialize)]
30#[derivative(Debug)]
31pub struct Track {
32 pub(crate) is_owner_pattern_work_buffer: bool,
33 pub(crate) owner_pattern_index: usize,
34 pub(crate) index: usize,
35
36 pub(crate) trigs: Vec<Trig>,
37
38 pub(crate) default_trig_flags: TrigFlags,
39 pub(crate) default_trig_note: u8,
40 pub(crate) default_trig_velocity: u8,
41 pub(crate) default_trig_note_length: Length,
42 pub(crate) default_trig_probability: u8,
43
44 pub(crate) number_of_steps: u8,
45 pub(crate) quantize_amount: u8,
46 pub(crate) sends_midi: bool,
47 pub(crate) speed: Speed,
48
49 pub(crate) euclidean_mode: bool,
50 pub(crate) euclidean_pl1: u8,
51 pub(crate) euclidean_pl2: u8,
52 pub(crate) euclidean_ro1: u8,
53 pub(crate) euclidean_ro2: u8,
54 pub(crate) euclidean_tro: u8,
55
56 pub(crate) pad_scale: PadScale,
57 pub(crate) root_note: RootNote,
58
59 #[derivative(Debug = "ignore")]
65 pub(crate) __maybe_useful_flag_from_default_trig_note: u8,
66
67 #[derivative(Debug = "ignore")]
73 pub(crate) __maybe_useful_flags_from_flags_and_speed: u8,
74
75 #[derivative(Debug = "ignore")]
76 #[serde(skip)]
77 pub(crate) parameter_lock_pool: Option<Arc<Mutex<ParameterLockPool>>>,
78
79 #[derivative(Debug = "ignore")]
80 #[allow(dead_code)]
81 #[serde(skip)]
82 pub(crate) fx_track_ref: Option<Arc<Mutex<Track>>>,
83}
84
85impl From<&Track> for ar_pattern_track_t {
86 fn from(track: &Track) -> Self {
87 let mut notes: [u8; 64] = [0; 64];
88 let mut velocities: [u8; 64] = [0; 64];
89 let mut note_lengths: [u8; 64] = [0; 64];
90 let mut micro_timings: [u8; 64] = [0; 64];
91 let mut retrig_lengths: [u8; 64] = [0; 64];
92 let mut retrig_rates: [u8; 64] = [0; 64];
93 let mut retrig_velocity_offsets: [i8; 64] = [0; 64];
94 let mut sound_locks: [u8; 64] = [0; 64];
95
96 let mut encoded_trig_bits: [u8; 112] = [0; 112];
97 let mut bit_writer =
98 BitWriter::endian(Cursor::new(encoded_trig_bits.as_mut_slice()), BigEndian);
99
100 for (i, trig) in track.trigs.iter().enumerate() {
101 bit_writer
103 .write::<u16>(14, trig.raw_trig_flags())
104 .expect("This shouldn't fail.");
105
106 notes[i] = trig.encode_note();
107 velocities[i] = trig.velocity() as u8;
108 note_lengths[i] = trig.note_length().into();
109 micro_timings[i] = trig.encode_micro_timing();
110 retrig_lengths[i] = trig.encode_retrig_length();
111 retrig_rates[i] = trig.encode_retrig_rate();
112 retrig_velocity_offsets[i] = trig.retrig_velocity_offset() as i8;
113 sound_locks[i] = trig.sound_lock() as u8;
114 }
115
116 let mut encoded_flags_and_speed: u8 = 0;
118 encoded_flags_and_speed |= track.speed as u8;
119 encoded_flags_and_speed |= if track.sends_midi { 0b1000_0000 } else { 0 };
120 encoded_flags_and_speed |= track.__maybe_useful_flags_from_flags_and_speed;
121
122 let encoded_euc_mode = if track.euclidean_mode { 128 } else { 0 };
124
125 let encoded_default_trig_note =
127 track.default_trig_note | track.__maybe_useful_flag_from_default_trig_note;
128
129 Self {
130 trig_bits: encoded_trig_bits,
131 notes,
132 velocities,
133 note_lengths,
134 micro_timings,
135 retrig_lengths,
136 retrig_rates,
137 retrig_velocity_offsets,
138 default_note: encoded_default_trig_note,
139 default_velocity: track.default_trig_velocity,
140 default_note_length: track.default_trig_note_length.into(),
141 default_trig_flags: to_s_u16_t_union_b(*track.default_trig_flags),
142 num_steps: track.number_of_steps,
143 quantize_amount: track.quantize_amount,
144 sound_locks,
145 flags_and_speed: encoded_flags_and_speed,
146 trig_probability: track.default_trig_probability,
147 euc_mode: encoded_euc_mode,
148 euc_pl1: track.euclidean_pl1,
149 euc_pl2: track.euclidean_pl2,
150 euc_ro1: track.euclidean_ro1,
151 euc_ro2: track.euclidean_ro2,
152 euc_tro: track.euclidean_tro,
153 pad_scale: track.pad_scale.into(),
154 root_note: track.root_note.into(),
155 }
156 }
157}
158
159impl Track {
160 #[parameter_range(range = "index:0..=12", range = "owner_pattern_index:0..=127")]
161 pub(crate) fn try_default(
162 index: usize,
163 owner_pattern_index: usize,
164 is_owner_pattern_work_buffer: bool,
165 fx_track_ref: Option<Arc<Mutex<Self>>>,
166 ) -> Result<Self, RytmError> {
167 Ok(Self {
168 owner_pattern_index,
169 is_owner_pattern_work_buffer,
170 index,
171 trigs: default_trig_array(index),
172
173 default_trig_flags: TrigFlags::default(),
174 default_trig_note: 60,
175 default_trig_velocity: 100,
176 default_trig_note_length: Length::default(),
177 default_trig_probability: 100,
178
179 number_of_steps: 16,
180 quantize_amount: 0,
181 sends_midi: false,
182 speed: Speed::default(),
183
184 euclidean_mode: false,
185 euclidean_pl1: 0,
186 euclidean_pl2: 0,
187 euclidean_ro1: 63,
188 euclidean_ro2: 63,
189 euclidean_tro: 63,
190
191 pad_scale: PadScale::default(),
192 root_note: RootNote::default(),
193
194 __maybe_useful_flag_from_default_trig_note: 0,
195 __maybe_useful_flags_from_flags_and_speed: 0,
196
197 parameter_lock_pool: None,
198 fx_track_ref,
199 })
200 }
201
202 pub(crate) fn try_from_raw(
203 index: usize,
204 raw_track: &ar_pattern_track_t,
205 parameter_lock_pool: &Arc<Mutex<ParameterLockPool>>,
206 fx_track_ref: Option<Arc<Mutex<Self>>>,
207 ) -> Result<Self, RytmError> {
208 let mut trigs: Vec<Trig> = default_trig_array(index);
209
210 let trig_cursor = Cursor::new(raw_track.trig_bits);
211 let mut bit_reader = BitReader::endian(trig_cursor, BigEndian);
212
213 for (i, trig) in trigs.iter_mut().enumerate() {
214 let parameter_lock_pool_ref = Arc::clone(parameter_lock_pool);
215
216 let raw_trig_flags = bit_reader.read::<u16>(14).unwrap();
217 *trig = Trig::new(
218 i,
220 index,
222 raw_trig_flags,
223 raw_track.notes[i],
224 raw_track.note_lengths[i],
225 raw_track.velocities[i],
226 raw_track.micro_timings[i],
227 raw_track.retrig_rates[i],
228 raw_track.retrig_lengths[i],
229 raw_track.retrig_velocity_offsets[i],
230 raw_track.sound_locks[i],
231 parameter_lock_pool_ref,
232 fx_track_ref.as_ref().map(Arc::clone),
233 )?;
234 }
235
236 let sends_midi = raw_track.flags_and_speed & 0b1000_0000 != 0;
237 let speed: Speed = (raw_track.flags_and_speed & 0b0000_0111).try_into()?;
238
239 #[allow(clippy::no_effect_underscore_binding)]
240 let __maybe_useful_flags_from_flags_and_speed = raw_track.flags_and_speed & 0b0111_1000;
242 #[allow(clippy::no_effect_underscore_binding)]
243 let __maybe_useful_flag_from_default_trig_note = raw_track.default_note & 0b1000_0000;
244
245 let default_trig_note = raw_track.default_note & 0b0111_1111;
246
247 let plock_pool = parameter_lock_pool.lock();
248
249 Ok(Self {
250 is_owner_pattern_work_buffer: plock_pool.is_owner_pattern_work_buffer,
251 owner_pattern_index: plock_pool.owner_pattern_index,
252 index,
253 trigs,
254
255 default_trig_note,
256 default_trig_velocity: raw_track.default_velocity,
257 default_trig_note_length: raw_track.default_note_length.try_into()?,
258 default_trig_flags: unsafe { from_s_u16_t(raw_track.default_trig_flags).into() },
259 default_trig_probability: raw_track.trig_probability,
260
261 number_of_steps: raw_track.num_steps,
262 quantize_amount: raw_track.quantize_amount,
263 sends_midi,
264 speed,
265
266 euclidean_mode: raw_track.euc_mode == 128,
267 euclidean_pl1: raw_track.euc_pl1,
268 euclidean_pl2: raw_track.euc_pl2,
269 euclidean_ro1: raw_track.euc_ro1,
270 euclidean_ro2: raw_track.euc_ro2,
271 euclidean_tro: raw_track.euc_tro,
272
273 pad_scale: raw_track.pad_scale.try_into()?,
274 root_note: raw_track.root_note.try_into()?,
275
276 __maybe_useful_flag_from_default_trig_note,
277 __maybe_useful_flags_from_flags_and_speed,
278
279 parameter_lock_pool: Some(Arc::clone(parameter_lock_pool)),
280 fx_track_ref,
281 })
282 }
283 pub fn trigs_mut(&mut self) -> &mut [Trig] {
287 self.trigs.as_mut_slice()
288 }
289
290 #[parameter_range(range = "default_trig_note:0..=127")]
296 pub fn set_default_trig_note(&mut self, default_trig_note: usize) -> Result<(), RytmError> {
297 self.default_trig_note = default_trig_note as u8;
298 Ok(())
299 }
300
301 #[parameter_range(range = "default_trig_velocity:0..=127")]
305 pub fn set_default_trig_velocity(
306 &mut self,
307 default_trig_velocity: usize,
308 ) -> Result<(), RytmError> {
309 self.default_trig_velocity = default_trig_velocity as u8;
310 Ok(())
311 }
312
313 pub fn set_default_trig_note_length(&mut self, default_trig_note_length: Length) {
317 self.default_trig_note_length = default_trig_note_length;
318 }
319
320 pub fn set_default_trig_flags<F: Into<TrigFlags>>(&mut self, default_trig_flags: F) {
323 self.default_trig_flags = default_trig_flags.into();
324 }
325
326 #[parameter_range(range = "default_trig_probability:0..=100")]
330 pub fn set_default_trig_probability(
331 &mut self,
332 default_trig_probability: usize,
333 ) -> Result<(), RytmError> {
334 self.default_trig_probability = default_trig_probability as u8;
335 Ok(())
336 }
337
338 #[parameter_range(range = "number_of_steps:1..=64")]
342 pub fn set_number_of_steps(&mut self, number_of_steps: usize) -> Result<(), RytmError> {
343 self.number_of_steps = number_of_steps as u8;
344 Ok(())
345 }
346
347 #[parameter_range(range = "quantize_amount:0..=127")]
351 pub fn set_quantize_amount(&mut self, quantize_amount: usize) -> Result<(), RytmError> {
352 self.quantize_amount = quantize_amount as u8;
353 Ok(())
354 }
355
356 pub fn set_sends_midi(&mut self, sends_midi: bool) {
358 self.sends_midi = sends_midi;
359 }
360
361 pub fn set_speed(&mut self, speed: Speed) {
363 self.speed = speed;
364 }
365
366 pub fn set_euclidean_mode(&mut self, euclidean_mode: bool) {
368 self.euclidean_mode = euclidean_mode;
369 }
370
371 #[parameter_range(range = "euclidean_pl1:0..=64")]
377 pub fn set_euclidean_pl1(&mut self, euclidean_pl1: usize) -> Result<(), RytmError> {
378 self.euclidean_pl1 = euclidean_pl1 as u8;
379 Ok(())
380 }
381
382 #[parameter_range(range = "euclidean_pl2:0..=64")]
388 pub fn set_euclidean_pl2(&mut self, euclidean_pl2: usize) -> Result<(), RytmError> {
389 self.euclidean_pl2 = euclidean_pl2 as u8;
390 Ok(())
391 }
392
393 #[parameter_range(range = "euclidean_ro1:0..=126")]
399 pub fn set_euclidean_ro1(&mut self, euclidean_ro1: usize) -> Result<(), RytmError> {
400 self.euclidean_ro1 = euclidean_ro1 as u8;
401 Ok(())
402 }
403
404 #[parameter_range(range = "euclidean_ro2:0..=126")]
410 pub fn set_euclidean_ro2(&mut self, euclidean_ro2: usize) -> Result<(), RytmError> {
411 self.euclidean_ro2 = euclidean_ro2 as u8;
412 Ok(())
413 }
414
415 #[parameter_range(range = "euclidean_tro:0..=126")]
421 pub fn set_euclidean_tro(&mut self, euclidean_tro: usize) -> Result<(), RytmError> {
422 self.euclidean_tro = euclidean_tro as u8;
423 Ok(())
424 }
425
426 pub fn set_pad_scale(&mut self, pad_scale: PadScale) {
428 self.pad_scale = pad_scale;
429 }
430
431 pub fn set_root_note(&mut self, root_note: RootNote) {
433 self.root_note = root_note;
434 }
435
436 pub fn trigs(&self) -> &[Trig] {
440 &self.trigs
441 }
442
443 pub const fn default_trig_note(&self) -> usize {
449 self.default_trig_note as usize
450 }
451
452 pub const fn default_trig_velocity(&self) -> usize {
456 self.default_trig_velocity as usize
457 }
458
459 pub const fn default_trig_note_length(&self) -> Length {
461 self.default_trig_note_length
462 }
463
464 pub const fn default_trig_flags(&self) -> TrigFlags {
466 self.default_trig_flags
467 }
468
469 pub const fn default_trig_probability(&self) -> usize {
473 self.default_trig_probability as usize
474 }
475
476 pub const fn number_of_steps(&self) -> usize {
480 self.number_of_steps as usize
481 }
482
483 pub const fn quantize_amount(&self) -> usize {
487 self.quantize_amount as usize
488 }
489
490 pub const fn sends_midi(&self) -> bool {
492 self.sends_midi
493 }
494
495 pub const fn speed(&self) -> Speed {
497 self.speed
498 }
499
500 pub const fn euclidean_mode(&self) -> bool {
502 self.euclidean_mode
503 }
504
505 pub const fn euclidean_pl1(&self) -> usize {
511 self.euclidean_pl1 as usize
512 }
513
514 pub const fn euclidean_pl2(&self) -> usize {
520 self.euclidean_pl2 as usize
521 }
522
523 pub const fn euclidean_ro1(&self) -> usize {
529 self.euclidean_ro1 as usize
530 }
531
532 pub const fn euclidean_ro2(&self) -> usize {
538 self.euclidean_ro2 as usize
539 }
540
541 pub const fn euclidean_tro(&self) -> usize {
547 self.euclidean_tro as usize
548 }
549
550 pub const fn pad_scale(&self) -> PadScale {
552 self.pad_scale
553 }
554
555 pub const fn root_note(&self) -> RootNote {
557 self.root_note
558 }
559
560 pub fn clear_all_plocks(&self) {
562 if let Some(pool) = &self.parameter_lock_pool {
563 pool.lock().clear_all_plocks_for_track(self.index as u8);
564 }
565 }
566
567 pub const fn index(&self) -> usize {
569 self.index
570 }
571
572 pub const fn owner_pattern_index(&self) -> usize {
574 self.owner_pattern_index
575 }
576}