1use crate::OtToolsIoError;
8use crate::{Defaults, HasHeaderField};
9use ot_tools_io_derive::{
10 ArrayDefaults, BoxedBigArrayDefaults, ContainerArrayMethods, IsDefaultCheck,
11};
12use serde::{Deserialize, Serialize};
13use serde_big_array::{Array, BigArray};
14use std::array::from_fn;
15use std::slice::{Iter, IterMut};
16
17const PART_HEADER: [u8; 4] = [0x50, 0x41, 0x52, 0x54];
20
21#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
22pub enum OnOrOff {
23 On = 1,
24 Off = 0,
25}
26
27#[derive(
30 Debug, Serialize, Deserialize, Clone, PartialEq, Copy, ArrayDefaults, BoxedBigArrayDefaults,
31)]
32pub struct AudioTrackVolume {
33 pub main: u8,
34 pub cue: u8,
35}
36
37impl Default for AudioTrackVolume {
39 fn default() -> Self {
40 Self {
41 main: 0x6c, cue: 0x6c, }
44 }
45}
46
47#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
50pub struct ActiveScenes {
51 pub scene_a: u8,
52 pub scene_b: u8,
53}
54
55impl Default for ActiveScenes {
56 fn default() -> Self {
57 Self {
58 scene_a: 0,
59 scene_b: 8,
60 }
61 }
62}
63
64#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
66pub struct AudioTrackMachineParamsSetupStd {
67 pub xloop: u8,
68 pub slic: u8,
69 pub len: u8,
70 pub rate: u8,
71 pub tstr: u8,
72 pub tsns: u8,
73}
74
75#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
77pub struct AudioTrackMachineParamsSetupThru {
78 pub unused_1: u8,
79 pub unused_2: u8,
80 pub unused_3: u8,
81 pub unused_4: u8,
82 pub unused_5: u8,
83 pub unused_6: u8,
84}
85
86#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
88pub struct AudioTrackMachineParamsSetupNeighbor {
89 pub unused_1: u8,
90 pub unused_2: u8,
91 pub unused_3: u8,
92 pub unused_4: u8,
93 pub unused_5: u8,
94 pub unused_6: u8,
95}
96
97#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
99pub struct AudioTrackMachineParamsSetupPickup {
100 pub unused_1: u8,
101 pub unused_2: u8,
102 pub unused_3: u8,
103 pub unused_4: u8,
104 pub tstr: u8,
105 pub tsns: u8,
106}
107
108#[derive(
112 Debug, Serialize, Deserialize, Clone, PartialEq, Copy, ArrayDefaults, BoxedBigArrayDefaults,
113)]
114pub struct AudioTrackMachinesParamsSetup {
115 pub static_machine: AudioTrackMachineParamsSetupStd,
116 pub flex_machine: AudioTrackMachineParamsSetupStd,
117 pub thru_machine: AudioTrackMachineParamsSetupThru,
118 pub neighbor_machine: AudioTrackMachineParamsSetupNeighbor,
119 pub pickup_machine: AudioTrackMachineParamsSetupPickup,
120}
121
122impl Default for AudioTrackMachinesParamsSetup {
123 fn default() -> Self {
124 Self {
125 static_machine: AudioTrackMachineParamsSetupStd {
126 xloop: 1,
127 slic: 0,
128 len: 0,
129 rate: 0,
130 tstr: 1,
131 tsns: 64,
132 },
133 flex_machine: AudioTrackMachineParamsSetupStd {
134 xloop: 1,
135 slic: 0,
136 len: 0,
137 rate: 0,
138 tstr: 1,
139 tsns: 64,
140 },
141 thru_machine: AudioTrackMachineParamsSetupThru {
142 unused_1: 0,
143 unused_2: 0,
144 unused_3: 0,
145 unused_4: 0,
146 unused_5: 0,
147 unused_6: 0,
148 },
149 neighbor_machine: AudioTrackMachineParamsSetupNeighbor {
150 unused_1: 0,
151 unused_2: 0,
152 unused_3: 0,
153 unused_4: 0,
154 unused_5: 0,
155 unused_6: 0,
156 },
157 pickup_machine: AudioTrackMachineParamsSetupPickup {
158 unused_1: 0,
159 unused_2: 0,
160 unused_3: 0,
161 unused_4: 0,
162 tstr: 1,
163 tsns: 64,
164 },
165 }
166 }
167}
168
169#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, BoxedBigArrayDefaults)]
173pub struct AudioTrackMachineSlot {
174 pub static_slot_id: u8,
175 pub flex_slot_id: u8,
176 pub unused_1: u8,
177 pub unused_2: u8,
178 pub recorder_slot_id: u8,
179}
180
181impl Default for AudioTrackMachineSlot {
182 fn default() -> Self {
183 Self {
184 static_slot_id: 0,
185 flex_slot_id: 0,
186 unused_1: 0,
187 unused_2: 0,
188 recorder_slot_id: 128,
189 }
190 }
191}
192
193impl<const N: usize> Defaults<[Self; N]> for AudioTrackMachineSlot {
195 fn defaults() -> [Self; N]
196 where
197 Self: Default,
198 {
199 from_fn(|i| Self {
200 static_slot_id: i as u8,
201 flex_slot_id: i as u8,
202 recorder_slot_id: 128 + i as u8,
203 ..Default::default()
204 })
205 }
206}
207
208#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
210pub struct AudioTrackMachineParamsValuesStd {
211 pub ptch: u8,
212 pub strt: u8,
213 pub len: u8,
214 pub rate: u8,
215 pub rtrg: u8,
216 pub rtim: u8,
217}
218
219#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
221pub struct AudioTrackMachineParamsValuesThru {
222 pub in_ab: u8,
223 pub vol_ab: u8,
224 pub unused_1: u8,
225 pub in_cd: u8,
226 pub vol_cd: u8,
227 pub unused_2: u8,
228}
229
230#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
232pub struct AudioTrackMachineParamsValuesNeighbor {
233 pub unused_1: u8,
234 pub unused_2: u8,
235 pub unused_3: u8,
236 pub unused_4: u8,
237 pub unused_5: u8,
238 pub unused_6: u8,
239}
240
241#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
243pub struct AudioTrackMachineParamsValuesPickup {
244 pub ptch: u8,
245 pub dir: u8,
246 pub len: u8,
247 pub unused_1: u8,
248 pub gain: u8,
249 pub op: u8,
250}
251
252#[derive(
256 Debug, Serialize, Deserialize, Clone, PartialEq, Copy, ArrayDefaults, BoxedBigArrayDefaults,
257)]
258pub struct AudioTrackMachinesParamsValues {
259 pub static_machine: AudioTrackMachineParamsValuesStd,
260 pub flex_machine: AudioTrackMachineParamsValuesStd,
261 pub thru_machine: AudioTrackMachineParamsValuesThru,
262 pub neighbor_machine: AudioTrackMachineParamsValuesNeighbor,
263 pub pickup_machine: AudioTrackMachineParamsValuesPickup,
264}
265
266impl Default for AudioTrackMachinesParamsValues {
267 fn default() -> Self {
268 Self {
269 static_machine: AudioTrackMachineParamsValuesStd {
270 ptch: 64,
271 strt: 0,
272 len: 0,
273 rate: 127,
274 rtrg: 0,
275 rtim: 79,
276 },
277 flex_machine: AudioTrackMachineParamsValuesStd {
278 ptch: 64,
279 strt: 0,
280 len: 0,
281 rate: 127,
282 rtrg: 0,
283 rtim: 79,
284 },
285 thru_machine: AudioTrackMachineParamsValuesThru {
286 in_ab: 0,
287 vol_ab: 64,
288 unused_1: 0,
289 in_cd: 0,
290 vol_cd: 64,
291 unused_2: 0,
292 },
293 neighbor_machine: AudioTrackMachineParamsValuesNeighbor {
294 unused_1: 0,
295 unused_2: 0,
296 unused_3: 0,
297 unused_4: 0,
298 unused_5: 0,
299 unused_6: 0,
300 },
301 pickup_machine: AudioTrackMachineParamsValuesPickup {
302 ptch: 64,
303 dir: 2,
304 len: 1,
305 unused_1: 127,
306 gain: 64,
307 op: 1,
308 },
309 }
310 }
311}
312
313#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
316pub struct LfoParamsValues {
317 pub spd1: u8,
318 pub spd2: u8,
319 pub spd3: u8,
320 pub dep1: u8,
321 pub dep2: u8,
322 pub dep3: u8,
323}
324
325#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
327pub struct AudioTrackAmpParamsValues {
328 pub atk: u8,
329 pub hold: u8,
330 pub rel: u8,
331 pub vol: u8,
332 pub bal: u8,
333 pub f: u8,
335}
336
337#[allow(clippy::derivable_impls)]
341impl Default for AudioTrackAmpParamsValues {
342 fn default() -> Self {
343 Self {
344 atk: 0,
345 hold: 127,
346 rel: 127,
347 vol: 64,
348 bal: 64,
349 f: 127,
350 }
351 }
352}
353
354#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
356pub struct AudioTrackFxParamsValues {
357 pub param_1: u8,
358 pub param_2: u8,
359 pub param_3: u8,
360 pub param_4: u8,
361 pub param_5: u8,
362 pub param_6: u8,
363}
364
365#[derive(
367 Debug, Serialize, Deserialize, Clone, PartialEq, Copy, ArrayDefaults, BoxedBigArrayDefaults,
368)]
369pub struct AudioTrackParamsValues {
370 pub lfo: LfoParamsValues,
371 pub amp: AudioTrackAmpParamsValues,
372 pub fx1: AudioTrackFxParamsValues,
373 pub fx2: AudioTrackFxParamsValues,
374}
375
376impl Default for AudioTrackParamsValues {
377 fn default() -> Self {
378 Self {
379 lfo: LfoParamsValues {
380 spd1: 32,
381 spd2: 32,
382 spd3: 32,
383 dep1: 0,
384 dep2: 0,
385 dep3: 0,
386 },
387 amp: AudioTrackAmpParamsValues::default(),
388 fx1: AudioTrackFxParamsValues {
389 param_1: 0,
390 param_2: 127,
391 param_3: 0,
392 param_4: 64,
393 param_5: 0,
394 param_6: 64,
395 },
396 fx2: AudioTrackFxParamsValues {
397 param_1: 47,
398 param_2: 0,
399 param_3: 127,
400 param_4: 0,
401 param_5: 127,
402 param_6: 0,
403 },
404 }
405 }
406}
407
408#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
410pub struct LfoParamsSetup1 {
411 pub lfo1_pmtr: u8,
412 pub lfo2_pmtr: u8,
413 pub lfo3_pmtr: u8,
414 pub lfo1_wave: u8,
415 pub lfo2_wave: u8,
416 pub lfo3_wave: u8,
417}
418
419#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
421pub struct LfoParamsSetup2 {
422 pub lfo1_mult: u8,
423 pub lfo2_mult: u8,
424 pub lfo3_mult: u8,
425 pub lfo1_trig: u8,
426 pub lfo2_trig: u8,
427 pub lfo3_trig: u8,
428}
429
430#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
432pub struct AudioTrackAmpParamsSetup {
433 pub amp: u8,
434 pub sync: u8,
435 pub atck: u8,
436 pub fx1: u8,
437 pub fx2: u8,
438 pub unused: u8,
440}
441
442#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
444pub struct AudioTrackFxParamsSetup {
445 pub setting1: u8,
446 pub setting2: u8,
447 pub setting3: u8,
448 pub setting4: u8,
449 pub setting5: u8,
450 pub setting6: u8,
451}
452
453#[derive(
455 Debug, Serialize, Deserialize, Clone, PartialEq, Copy, ArrayDefaults, BoxedBigArrayDefaults,
456)]
457pub struct AudioTrackParamsSetup {
458 pub lfo_setup_1: LfoParamsSetup1,
460 pub amp: AudioTrackAmpParamsSetup,
462 pub fx1: AudioTrackFxParamsSetup,
464 pub fx2: AudioTrackFxParamsSetup,
466 pub lfo_setup_2: LfoParamsSetup2,
468}
469
470impl Default for AudioTrackParamsSetup {
471 fn default() -> Self {
472 Self {
473 lfo_setup_1: LfoParamsSetup1 {
474 lfo1_pmtr: 0,
475 lfo2_pmtr: 0,
476 lfo3_pmtr: 0,
477 lfo1_wave: 0,
478 lfo2_wave: 0,
479 lfo3_wave: 0,
480 },
481 amp: AudioTrackAmpParamsSetup {
482 amp: 1,
483 sync: 1,
484 atck: 0,
485 fx1: 0,
486 fx2: 0,
487 unused: 0,
488 },
489 fx1: AudioTrackFxParamsSetup {
490 setting1: 0,
491 setting2: 0,
492 setting3: 1,
493 setting4: 0,
494 setting5: 3,
495 setting6: 0,
496 },
497 fx2: AudioTrackFxParamsSetup {
498 setting1: 0,
499 setting2: 1,
500 setting3: 127,
501 setting4: 1,
502 setting5: 0,
503 setting6: 0,
504 },
505 lfo_setup_2: LfoParamsSetup2 {
506 lfo1_mult: 0,
507 lfo2_mult: 0,
508 lfo3_mult: 0,
509 lfo1_trig: 0,
510 lfo2_trig: 0,
511 lfo3_trig: 0,
512 },
513 }
514 }
515}
516
517#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
519pub struct MidiTrackMidiParamsValues {
520 pub note: u8,
521 pub vel: u8,
522 pub len: u8,
523 pub not2: u8,
524 pub not3: u8,
525 pub not4: u8,
526}
527
528#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
530pub struct MidiTrackArpParamsValues {
531 pub tran: u8,
532 pub leg: u8,
533 pub mode: u8,
534 pub spd: u8,
535 pub rnge: u8,
536 pub nlen: u8,
537}
538
539#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
541pub struct MidiTrackCc1ParamsValues {
542 pub pb: u8,
543 pub at: u8,
544 pub cc1: u8,
545 pub cc2: u8,
546 pub cc3: u8,
547 pub cc4: u8,
548}
549
550#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
552pub struct MidiTrackCc2ParamsValues {
553 pub cc5: u8,
554 pub cc6: u8,
555 pub cc7: u8,
556 pub cc8: u8,
557 pub cc9: u8,
558 pub cc10: u8,
559}
560
561#[derive(
574 Debug, Serialize, Deserialize, Clone, PartialEq, Copy, ArrayDefaults, BoxedBigArrayDefaults,
575)]
576pub struct MidiTrackParamsValues {
577 pub midi: MidiTrackMidiParamsValues,
578 pub lfo: LfoParamsValues,
579 pub arp: MidiTrackArpParamsValues,
580 pub ctrl1: MidiTrackCc1ParamsValues,
581 pub ctrl2: MidiTrackCc2ParamsValues,
582 #[serde(with = "BigArray")]
583 pub unknown: [u8; 2],
584}
585
586impl Default for MidiTrackParamsValues {
587 fn default() -> Self {
588 Self {
589 midi: MidiTrackMidiParamsValues {
590 note: 48,
591 vel: 100,
592 len: 6,
593 not2: 64,
594 not3: 64,
595 not4: 64,
596 },
597 lfo: LfoParamsValues {
598 spd1: 32,
599 spd2: 32,
600 spd3: 32,
601 dep1: 0,
602 dep2: 0,
603 dep3: 0,
604 },
605 arp: MidiTrackArpParamsValues {
606 tran: 64,
607 leg: 0,
608 mode: 0,
609 spd: 5,
610 rnge: 0,
611 nlen: 6,
612 },
613 ctrl1: MidiTrackCc1ParamsValues {
614 pb: 64,
615 at: 0,
616 cc1: 127,
617 cc2: 0,
618 cc3: 0,
619 cc4: 64,
620 },
621 ctrl2: MidiTrackCc2ParamsValues {
622 cc5: 0,
623 cc6: 0,
624 cc7: 0,
625 cc8: 0,
626 cc9: 0,
627 cc10: 0,
628 },
629 unknown: [0, 0],
630 }
631 }
632}
633
634#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
636pub struct MidiTrackNoteParamsSetup {
637 pub chan: u8,
638 pub bank: u8,
639 pub prog: u8,
640 pub unused_1: u8,
641 pub sbank: u8,
642 pub unused_2: u8,
643}
644
645#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
647pub struct MidiTrackArpParamsSetup {
648 pub unused_1: u8,
649 pub unused_2: u8,
650 pub len: u8,
652 pub unused_3: u8,
653 pub unused_4: u8,
654 pub key: u8,
657}
658
659#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
661pub struct MidiTrackCc1ParamsSetup {
662 pub unused_1: u8,
663 pub unused_2: u8,
664 pub cc1: u8,
665 pub cc2: u8,
666 pub cc3: u8,
667 pub cc4: u8,
668}
669
670#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
672pub struct MidiTrackCc2ParamsSetup {
673 pub cc5: u8,
674 pub cc6: u8,
675 pub cc7: u8,
676 pub cc8: u8,
677 pub cc9: u8,
678 pub cc10: u8,
679}
680
681#[derive(
683 Debug, Serialize, Deserialize, Clone, PartialEq, Copy, ArrayDefaults, BoxedBigArrayDefaults,
684)]
685pub struct MidiTrackParamsSetup {
686 pub note: MidiTrackNoteParamsSetup,
687 pub lfo1: LfoParamsSetup1,
688 pub arp: MidiTrackArpParamsSetup,
689 pub ctrl1: MidiTrackCc1ParamsSetup,
690 pub ctrl2: MidiTrackCc2ParamsSetup,
691 pub lfo2: LfoParamsSetup2,
692}
693
694impl Default for MidiTrackParamsSetup {
695 fn default() -> Self {
696 Self {
697 note: MidiTrackNoteParamsSetup {
698 chan: 0,
699 bank: 128,
700 prog: 128,
701 unused_1: 0,
702 sbank: 128,
703 unused_2: 0,
704 },
705 lfo1: LfoParamsSetup1 {
706 lfo1_pmtr: 0,
707 lfo2_pmtr: 0,
708 lfo3_pmtr: 0,
709 lfo1_wave: 0,
710 lfo2_wave: 0,
711 lfo3_wave: 0,
712 },
713 arp: MidiTrackArpParamsSetup {
714 unused_1: 0,
715 unused_2: 0,
716 len: 7,
717 unused_3: 0,
718 unused_4: 0,
719 key: 0,
720 },
721 ctrl1: MidiTrackCc1ParamsSetup {
722 unused_1: 0,
723 unused_2: 0,
724 cc1: 7,
725 cc2: 1,
726 cc3: 2,
727 cc4: 10,
728 },
729 ctrl2: MidiTrackCc2ParamsSetup {
730 cc5: 71,
731 cc6: 72,
732 cc7: 73,
733 cc8: 74,
734 cc9: 75,
735 cc10: 76,
736 },
737 lfo2: LfoParamsSetup2 {
738 lfo1_mult: 0,
739 lfo2_mult: 0,
740 lfo3_mult: 0,
741 lfo1_trig: 0,
742 lfo2_trig: 0,
743 lfo3_trig: 0,
744 },
745 }
746 }
747}
748
749#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, ArrayDefaults, BoxedBigArrayDefaults)]
753pub struct CustomLfoDesign(pub [u8; 16]);
754
755impl Default for CustomLfoDesign {
757 fn default() -> Self {
758 Self(from_fn(|_| 0))
759 }
760}
761
762#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, ArrayDefaults, BoxedBigArrayDefaults)]
766pub struct CustomLfoInterpolationMask(pub [u8; 2]);
767
768impl Default for CustomLfoInterpolationMask {
769 fn default() -> Self {
770 Self(from_fn(|_| 0))
771 }
772}
773
774#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
776pub struct RecorderSetupSources {
777 pub in_ab: u8,
778 pub in_cd: u8,
779 pub rlen: u8,
781 pub trig: u8,
782 pub src3: u8,
784 pub xloop: u8,
785}
786
787#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
789pub struct RecorderSetupProcessing {
790 pub fin: u8,
791 pub fout: u8,
792 pub ab: u8,
793 pub qrec: u8,
794 pub qpl: u8,
795 pub cd: u8,
796}
797
798#[derive(
800 Debug, Serialize, Deserialize, Clone, PartialEq, Copy, ArrayDefaults, BoxedBigArrayDefaults,
801)]
802pub struct RecorderSetup {
803 pub src: RecorderSetupSources,
804 pub proc: RecorderSetupProcessing,
805}
806
807impl Default for RecorderSetup {
808 fn default() -> Self {
809 Self {
810 src: RecorderSetupSources {
811 in_ab: 1,
812 in_cd: 1,
813 rlen: 64,
814 trig: 0,
815 src3: 0,
816 xloop: 1,
817 },
818 proc: RecorderSetupProcessing {
819 fin: 0,
820 fout: 0,
821 ab: 0,
822 qrec: 255,
823 qpl: 255,
824 cd: 0,
825 },
826 }
827 }
828}
829
830#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
833pub struct AudioTrackSceneLockPlayback {
834 pub param1: u8,
835 pub param2: u8,
836 pub param3: u8,
837 pub param4: u8,
838 pub param5: u8,
839 pub param6: u8,
840}
841
842#[derive(
849 Debug,
850 Serialize,
851 Deserialize,
852 Clone,
853 PartialEq,
854 Copy,
855 ArrayDefaults,
856 BoxedBigArrayDefaults,
857 IsDefaultCheck,
858)]
859pub struct SceneParams {
860 pub machine: AudioTrackSceneLockPlayback,
862 pub lfo: LfoParamsValues,
864 pub amp: AudioTrackAmpParamsValues,
866 pub fx1: AudioTrackFxParamsValues,
868 pub fx2: AudioTrackFxParamsValues,
870 pub unknown_1: u8,
874 pub unknown_2: u8,
878}
879
880impl Default for SceneParams {
881 fn default() -> Self {
882 Self {
883 machine: AudioTrackSceneLockPlayback {
884 param1: 255,
885 param2: 255,
886 param3: 255,
887 param4: 255,
888 param5: 255,
889 param6: 255,
890 },
891 lfo: LfoParamsValues {
892 spd1: 255,
893 spd2: 255,
894 spd3: 255,
895 dep1: 255,
896 dep2: 255,
897 dep3: 255,
898 },
899 amp: AudioTrackAmpParamsValues {
900 atk: 255,
901 hold: 255,
902 rel: 255,
903 vol: 255,
904 bal: 255,
905 f: 255,
906 },
907 fx1: AudioTrackFxParamsValues {
908 param_1: 255,
909 param_2: 255,
910 param_3: 255,
911 param_4: 255,
912 param_5: 255,
913 param_6: 255,
914 },
915 fx2: AudioTrackFxParamsValues {
916 param_1: 255,
917 param_2: 255,
918 param_3: 255,
919 param_4: 255,
920 param_5: 255,
921 param_6: 255,
922 },
923 unknown_1: 255,
924 unknown_2: 255,
925 }
926 }
927}
928
929#[derive(
931 Debug,
932 Serialize,
933 Deserialize,
934 Clone,
935 PartialEq,
936 ArrayDefaults,
937 BoxedBigArrayDefaults,
938 IsDefaultCheck,
939 ContainerArrayMethods,
940)]
941pub struct SceneParamsArray(pub [SceneParams; 8]);
942
943#[derive(
952 Debug, Serialize, Deserialize, Clone, PartialEq, Copy, ArrayDefaults, BoxedBigArrayDefaults,
953)]
954pub struct SceneXlvAssignments {
955 #[serde(with = "BigArray")]
959 pub track_xlvs: [u8; 8],
960
961 #[serde(with = "BigArray")]
965 pub unknown: [u8; 2],
966}
967
968impl Default for SceneXlvAssignments {
969 fn default() -> Self {
970 Self {
971 track_xlvs: from_fn(|_| 255),
972 unknown: from_fn(|_| 255),
973 }
974 }
975}
976
977#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, ArrayDefaults, BoxedBigArrayDefaults)]
981pub struct MidiArpSequence(pub [u8; 16]);
982
983impl Default for MidiArpSequence {
984 fn default() -> Self {
985 Self(from_fn(|_| 0))
986 }
987}
988
989#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, BoxedBigArrayDefaults)]
991pub struct Part {
992 #[serde(with = "BigArray")]
993 pub header: [u8; 4],
994
995 #[serde(with = "BigArray")]
997 pub data_block_1: [u8; 4],
998
999 pub part_id: u8,
1001
1002 #[serde(with = "BigArray")]
1017 pub audio_track_fx1: [u8; 8],
1018
1019 #[serde(with = "BigArray")]
1038 pub audio_track_fx2: [u8; 8],
1039
1040 pub active_scenes: ActiveScenes,
1042
1043 #[serde(with = "BigArray")]
1045 pub audio_track_volumes: [AudioTrackVolume; 8],
1046
1047 #[serde(with = "BigArray")]
1050 pub audio_track_machine_types: [u8; 8],
1051
1052 #[serde(with = "BigArray")]
1055 pub audio_track_machine_params: [AudioTrackMachinesParamsValues; 8],
1056
1057 #[serde(with = "BigArray")]
1060 pub audio_track_params_values: [AudioTrackParamsValues; 8],
1061
1062 #[serde(with = "BigArray")]
1065 pub audio_track_machine_setup: [AudioTrackMachinesParamsSetup; 8],
1066
1067 #[serde(with = "BigArray")]
1069 pub audio_track_machine_slots: [AudioTrackMachineSlot; 8],
1070
1071 #[serde(with = "BigArray")]
1074 pub audio_track_params_setup: [AudioTrackParamsSetup; 8],
1075
1076 #[serde(with = "BigArray")]
1079 pub midi_track_params_values: [MidiTrackParamsValues; 8],
1080
1081 #[serde(with = "BigArray")]
1084 pub midi_track_params_setup: [MidiTrackParamsSetup; 8],
1085
1086 #[serde(with = "BigArray")]
1088 pub recorder_setup: [RecorderSetup; 8],
1089
1090 #[serde(with = "BigArray")]
1094 pub scenes: [SceneParamsArray; 16],
1095
1096 #[serde(with = "BigArray")]
1097 pub scene_xlvs: [SceneXlvAssignments; 16],
1098
1099 #[serde(with = "BigArray")]
1101 pub audio_tracks_custom_lfo_designs: [CustomLfoDesign; 8],
1102
1103 #[serde(with = "BigArray")]
1107 pub audio_tracks_custom_lfos_interpolation_masks: [CustomLfoInterpolationMask; 8],
1108
1109 #[serde(with = "BigArray")]
1111 pub midi_tracks_custom_lfos: [CustomLfoDesign; 8],
1112
1113 #[serde(with = "BigArray")]
1117 pub midi_tracks_custom_lfos_interpolation_masks: [CustomLfoInterpolationMask; 8],
1118
1119 #[serde(with = "BigArray")]
1123 pub midi_tracks_arp_mute_masks: [u8; 16],
1124
1125 pub midi_tracks_arp_seqs: [MidiArpSequence; 8],
1127}
1128
1129impl Default for Part {
1130 fn default() -> Self {
1131 Self {
1132 header: PART_HEADER,
1133 data_block_1: from_fn(|_| 0),
1134 part_id: 0,
1135 audio_track_fx1: from_fn(|_| 4),
1136 audio_track_fx2: from_fn(|_| 8),
1137 active_scenes: ActiveScenes::default(),
1138 audio_track_volumes: AudioTrackVolume::defaults(),
1139 audio_track_machine_types: from_fn(|_| 0),
1140 audio_track_machine_params: AudioTrackMachinesParamsValues::defaults(),
1141 audio_track_params_values: AudioTrackParamsValues::defaults(),
1142 audio_track_machine_setup: AudioTrackMachinesParamsSetup::defaults(),
1143 audio_track_machine_slots: AudioTrackMachineSlot::defaults(),
1144 audio_track_params_setup: AudioTrackParamsSetup::defaults(),
1145 midi_track_params_values: MidiTrackParamsValues::defaults(),
1146 midi_track_params_setup: MidiTrackParamsSetup::defaults(),
1147 recorder_setup: RecorderSetup::defaults(),
1148 scenes: SceneParamsArray::defaults(),
1149 scene_xlvs: SceneXlvAssignments::defaults(),
1150 audio_tracks_custom_lfo_designs: CustomLfoDesign::defaults(),
1151 audio_tracks_custom_lfos_interpolation_masks: CustomLfoInterpolationMask::defaults(),
1152 midi_tracks_custom_lfos: CustomLfoDesign::defaults(),
1153 midi_tracks_custom_lfos_interpolation_masks: CustomLfoInterpolationMask::defaults(),
1154 midi_tracks_arp_mute_masks: from_fn(|_| 255),
1155 midi_tracks_arp_seqs: MidiArpSequence::defaults(),
1156 }
1157 }
1158}
1159
1160impl crate::IsDefault for Part {
1161 fn is_default(&self) -> bool
1162 where
1163 Self: Default + PartialEq,
1164 {
1165 let x = Self {
1166 part_id: self.part_id,
1167 ..Default::default()
1168 };
1169 self == &x
1170 }
1171}
1172
1173impl<const N: usize> Defaults<[Self; N]> for Part {
1175 fn defaults() -> [Self; N]
1176 where
1177 Self: Default,
1178 {
1179 from_fn(|i| Self {
1180 part_id: i as u8,
1181 ..Default::default()
1182 })
1183 }
1184}
1185
1186impl HasHeaderField for Part {
1187 fn check_header(&self) -> Result<bool, OtToolsIoError> {
1188 Ok(self.header == PART_HEADER)
1189 }
1190}
1191
1192#[cfg(test)]
1193mod part_header_field {
1194 use crate::{
1195 test_utils::get_blank_proj_dirpath, BankFile, HasHeaderField, OctatrackFileIO,
1196 OtToolsIoError,
1197 };
1198 #[test]
1199 fn valid() -> Result<(), OtToolsIoError> {
1200 let path = get_blank_proj_dirpath().join("bank01.work");
1201 let parts = BankFile::from_data_file(&path)?.parts.saved.clone();
1202 let part = parts[0].clone();
1203 assert!(part.check_header()?);
1204 Ok(())
1205 }
1206
1207 #[test]
1208 fn invalid() -> Result<(), OtToolsIoError> {
1209 let path = get_blank_proj_dirpath().join("bank01.work");
1210 let parts = BankFile::from_data_file(&path)?.parts.saved.clone();
1211 let mut part = parts[0].clone();
1212
1213 part.header[0] = 255;
1214 part.header[1] = 255;
1215 part.header[2] = 255;
1216 part.header[3] = 255;
1217
1218 assert!(!part.check_header()?);
1219 Ok(())
1220 }
1221}
1222
1223#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1225pub struct Parts {
1226 pub unsaved: PartArray,
1230 pub saved: PartArray,
1234}
1235
1236#[allow(clippy::derivable_impls)]
1237impl Default for Parts {
1238 fn default() -> Self {
1239 Self {
1240 unsaved: PartArray::default(),
1241 saved: PartArray::default(),
1242 }
1243 }
1244}
1245
1246impl HasHeaderField for Parts {
1247 fn check_header(&self) -> Result<bool, OtToolsIoError> {
1248 let unsaved = self
1249 .unsaved
1250 .iter()
1251 .all(|x| x.check_header().is_ok_and(|x| x));
1252 let saved = self.saved.iter().all(|x| x.check_header().is_ok_and(|x| x));
1253
1254 Ok(saved && unsaved)
1255 }
1256}
1257
1258#[cfg(test)]
1259mod parts_header_field {
1260 use crate::{
1261 test_utils::get_blank_proj_dirpath, BankFile, HasHeaderField, OctatrackFileIO,
1262 OtToolsIoError,
1263 };
1264 #[test]
1265 fn valid() -> Result<(), OtToolsIoError> {
1266 let path = get_blank_proj_dirpath().join("bank01.work");
1267 let parts = BankFile::from_data_file(&path)?.parts;
1268 assert!(parts.check_header()?);
1269 Ok(())
1270 }
1271
1272 #[test]
1273 fn invalid() -> Result<(), OtToolsIoError> {
1274 let path = get_blank_proj_dirpath().join("bank01.work");
1275 let mut parts = BankFile::from_data_file(&path)?.parts;
1276
1277 parts.saved[0].header[0] = 255;
1278 parts.saved[0].header[1] = 255;
1279 parts.saved[0].header[2] = 255;
1280 parts.saved[0].header[3] = 255;
1281
1282 assert!(!parts.check_header()?);
1283 Ok(())
1284 }
1285}
1286
1287#[derive(PartialEq, Debug, Serialize, Deserialize, Clone, ContainerArrayMethods)]
1290pub struct PartArray(
1291 Box<Array<Part, 4>>,
1293);
1294
1295impl std::ops::Deref for PartArray {
1296 type Target = Box<Array<Part, 4>>;
1297 fn deref(&self) -> &Self::Target {
1298 &self.0
1299 }
1300}
1301
1302impl std::ops::DerefMut for PartArray {
1303 fn deref_mut(&mut self) -> &mut Self::Target {
1304 &mut self.0
1305 }
1306}