ot_tools_io/
banks.rs

1/*
2SPDX-License-Identifier: GPL-3.0-or-later
3Copyright © 2024 Mike Robeson [dijksterhuis]
4*/
5
6//! Types for `bank??.*` binary data files.
7pub mod parts;
8pub mod patterns;
9
10use crate::{
11    banks::{parts::Parts, patterns::Pattern},
12    CalculateChecksum, CheckChecksum, CheckHeader, CheckIntegrity, DefaultsArrayBoxed, Encode,
13    IsDefault, RBoxErr,
14};
15use ot_tools_io_derive::{Decodeable, DefaultsAsBoxedBigArray};
16use serde::{Deserialize, Serialize};
17use serde_big_array::{Array, BigArray};
18use std::array::from_fn;
19
20/// Bank header data.
21/// ```text
22/// FORM....DPS1BANK.....
23/// 46 4f 52 4d 00 00 00 00 44 50 53 31 42 41 4e 4b 00 00 00 00 00
24/// [70 79 82 77 0 0 0 0 68 80 83 49 66 65 78 75 0 0 0 0 0]
25/// ```
26pub const BANK_HEADER: [u8; 21] = [
27    70, 79, 82, 77, 0, 0, 0, 0, 68, 80, 83, 49, 66, 65, 78, 75, 0, 0, 0, 0, 0,
28];
29
30/// Current/supported version of bank files.
31pub const BANK_FILE_VERSION: u8 = 23;
32
33/// An Octatrack Bank. Contains data related to Parts and Patterns.
34#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, DefaultsAsBoxedBigArray, Decodeable)]
35pub struct BankFile {
36    /// Misc header data for Banks.
37    /// Always follows the same format.
38    #[serde(with = "BigArray")]
39    pub header: [u8; 21],
40
41    pub datatype_version: u8,
42
43    /// Pattern data for a Bank.
44    // note -- stack overflow if tring to use #[serde(with = "BigArray")]
45    pub patterns: Box<Array<Pattern, 16>>,
46
47    /// All part data for this bank, includes currently unsaved and previously saved state
48    pub parts: Parts,
49
50    /// Unknown what these bytes refer to.
51    #[serde(with = "BigArray")]
52    pub unknown: [u8; 5],
53
54    /// Names for each Part within the Bank.
55    /// Maximum 7 character length.
56    #[serde(with = "BigArray")]
57    pub part_names: [[u8; 7]; 4],
58
59    /// checksum bytes
60    pub checksum: u16,
61}
62
63/// Default Part names (ONE, TWO, THREE, FOUR) converted to u8 for ease of use.
64const DEFAULT_PART_NAMES: [[u8; 7]; 4] = [
65    [0x4f, 0x4e, 0x45, 0x00, 0x00, 0x00, 0x00], // "ONE"
66    [0x54, 0x57, 0x4f, 0x00, 0x00, 0x00, 0x00], // "TWO"
67    [0x54, 0x48, 0x52, 0x45, 0x45, 0x00, 0x00], // "THREE"
68    [0x46, 0x4f, 0x55, 0x52, 0x00, 0x00, 0x00], // "FOUR"
69];
70
71impl Encode for BankFile {
72    fn encode(&self) -> RBoxErr<Vec<u8>> {
73        let mut chkd = self.clone();
74        chkd.checksum = self.calculate_checksum()?;
75        let bytes = bincode::serialize(&chkd)?;
76        Ok(bytes)
77    }
78}
79
80impl Default for BankFile {
81    fn default() -> Self {
82        Self {
83            header: BANK_HEADER,
84            datatype_version: BANK_FILE_VERSION,
85            patterns: Pattern::defaults(),
86            parts: Parts::default(),
87            unknown: from_fn(|_| 0),
88            part_names: DEFAULT_PART_NAMES,
89            // WARN: mutated during encode! do not calculate checksum in this
90            // method until i've refactored `get_checksum` to not use Bank::default()
91            // (end up with a never ending recursive loop of calling default)
92            // TODO: Hardcoded
93            checksum: 48022,
94        }
95    }
96}
97
98impl IsDefault for BankFile {
99    fn is_default(&self) -> bool {
100        &BankFile::default() == self
101    }
102}
103
104impl CalculateChecksum for BankFile {
105    fn calculate_checksum(&self) -> RBoxErr<u16> {
106        let bytes = bincode::serialize(&self)?;
107        let bytes_no_header_no_chk = &bytes[16..bytes.len() - 2];
108        let default_bytes = &bincode::serialize(&BankFile::default())?;
109        let def_important_bytes = &default_bytes[16..bytes.len() - 2];
110        let default_checksum: i32 = 48022;
111        let mut byte_diffs: i32 = 0;
112        for (byte, def_byte) in bytes_no_header_no_chk.iter().zip(def_important_bytes) {
113            let byte_diff = (*byte as i32) - (*def_byte as i32);
114            if byte_diff != 0 {
115                byte_diffs += byte_diff;
116            }
117        }
118        let check = byte_diffs * 256 + default_checksum;
119        let modded = check.rem_euclid(65535);
120        Ok(modded as u16)
121    }
122}
123
124impl CheckHeader for BankFile {
125    fn check_header(&self) -> bool {
126        self.header == BANK_HEADER
127    }
128}
129
130impl CheckChecksum for BankFile {
131    fn check_checksum(&self) -> RBoxErr<bool> {
132        Ok(self.checksum == self.calculate_checksum()?)
133    }
134}
135
136impl CheckIntegrity for BankFile {}
137
138#[cfg(test)]
139mod checksum {
140    use crate::banks::BankFile;
141    use crate::test_utils::{get_bank_dirpath, get_blank_proj_dirpath};
142    use crate::{read_type_from_bin_file, CalculateChecksum, Encode};
143    use std::path::Path;
144
145    fn helper_test_chksum(fp: &Path) {
146        let valid = read_type_from_bin_file::<BankFile>(fp).unwrap();
147        let mut test = valid.clone();
148        test.checksum = 0;
149        let encoded = test.encode().unwrap();
150        let def_encoded = BankFile::default().encode().unwrap();
151
152        let r = test.calculate_checksum();
153
154        //let bytes = bincode::serialize(&test).unwrap();
155        //let r = get_checksum(&bytes);
156        assert!(r.is_ok());
157        let res = r.unwrap();
158
159        let s_attr_chk: u32 = encoded[16..encoded.len() - 2]
160            .iter()
161            .map(|x| *x as u32)
162            .sum::<u32>()
163            .rem_euclid(u16::MAX as u32 + 1);
164
165        let non_zero_bytes = encoded.iter().filter(|b| b > &&0).count();
166        let non_zero_sum = encoded
167            .iter()
168            .cloned()
169            .filter(|b| b > &0)
170            .map(|x| x as u32)
171            .sum::<u32>();
172
173        let default_byte_sum = def_encoded
174            .iter()
175            .cloned()
176            .filter(|b| b > &0)
177            .map(|x| x as u32)
178            .sum::<u32>();
179
180        println!(
181            "l: {} r: {} non_zero_bytes {} sum total: {} def sum: {}, s-attr {} diff {} (or {})",
182            res,
183            valid.checksum,
184            non_zero_bytes,
185            non_zero_sum,
186            default_byte_sum,
187            s_attr_chk,
188            res.wrapping_sub(valid.checksum),
189            valid.checksum.wrapping_sub(res)
190        );
191
192        assert_eq!(res, valid.checksum);
193    }
194
195    #[test]
196    fn default_bank1() {
197        helper_test_chksum(&get_blank_proj_dirpath().join("bank01.work"));
198    }
199
200    #[test]
201    fn default_bank2() {
202        helper_test_chksum(&get_blank_proj_dirpath().join("bank02.work"));
203    }
204
205    #[test]
206    fn one_scene_zero_val() {
207        // start value incremented by 127 (max) and len incremented by 127 (max) on the machine
208        helper_test_chksum(
209            &get_bank_dirpath()
210                .join("checksum")
211                .join("scene1-atrack1-lfo-dep1-zero.work"),
212        );
213    }
214
215    #[test]
216    fn one_scene_127_val() {
217        // start value incremented by 127 (max) and len incremented by 127 (max) on the machine
218        helper_test_chksum(
219            &get_bank_dirpath()
220                .join("checksum")
221                .join("scene1-atrack1-lfo-dep1-127.work"),
222        );
223    }
224
225    #[test]
226    fn scene_params_decr_lots() {
227        // all scenes have assignments on the LFO parameters for track 1 - sets everything tp 0
228        helper_test_chksum(
229            &get_bank_dirpath()
230                .join("checksum")
231                .join("all-scenes-lfo-params-zeroed.work"),
232        );
233    }
234
235    mod static_strt_only {
236        use crate::banks::checksum::helper_test_chksum;
237        use crate::test_utils::get_bank_dirpath;
238
239        #[test]
240        fn static_strt_1() {
241            // start value incremented by one on the machine
242            helper_test_chksum(
243                &get_bank_dirpath()
244                    .join("checksum")
245                    .join("static-strt-1.work"),
246            );
247        }
248
249        #[test]
250        fn static_strt_2() {
251            // start value incremented by two on the machine
252            helper_test_chksum(
253                &get_bank_dirpath()
254                    .join("checksum")
255                    .join("static-strt-2.work"),
256            );
257        }
258
259        #[test]
260        fn static_strt_10() {
261            // start value incremented by ten on the machine
262            helper_test_chksum(
263                &get_bank_dirpath()
264                    .join("checksum")
265                    .join("static-strt-10.work"),
266            );
267        }
268
269        // off by one?!
270        #[test]
271        fn static_strt_127() {
272            // start value incremented by 127 (max) on the machine
273            helper_test_chksum(
274                &get_bank_dirpath()
275                    .join("checksum")
276                    .join("static-strt-127.work"),
277            );
278        }
279
280        #[test]
281        fn static_strt_126() {
282            helper_test_chksum(
283                &get_bank_dirpath()
284                    .join("checksum")
285                    .join("static-strt-126.work"),
286            );
287        }
288
289        #[test]
290        fn static_strt_125() {
291            helper_test_chksum(
292                &get_bank_dirpath()
293                    .join("checksum")
294                    .join("static-strt-125.work"),
295            );
296        }
297
298        #[test]
299        fn static_strt_124() {
300            helper_test_chksum(
301                &get_bank_dirpath()
302                    .join("checksum")
303                    .join("static-strt-124.work"),
304            );
305        }
306
307        #[test]
308        fn static_strt_123() {
309            helper_test_chksum(
310                &get_bank_dirpath()
311                    .join("checksum")
312                    .join("static-strt-123.work"),
313            );
314        }
315
316        #[test]
317        fn static_strt_122() {
318            helper_test_chksum(
319                &get_bank_dirpath()
320                    .join("checksum")
321                    .join("static-strt-122.work"),
322            );
323        }
324
325        #[test]
326        fn static_strt_121() {
327            helper_test_chksum(
328                &get_bank_dirpath()
329                    .join("checksum")
330                    .join("static-strt-121.work"),
331            );
332        }
333
334        #[test]
335        fn static_strt_120() {
336            helper_test_chksum(
337                &get_bank_dirpath()
338                    .join("checksum")
339                    .join("static-strt-120.work"),
340            );
341        }
342
343        #[test]
344        fn static_strt_119() {
345            helper_test_chksum(
346                &get_bank_dirpath()
347                    .join("checksum")
348                    .join("static-strt-119.work"),
349            );
350        }
351
352        #[test]
353        fn static_strt_118() {
354            helper_test_chksum(
355                &get_bank_dirpath()
356                    .join("checksum")
357                    .join("static-strt-118.work"),
358            );
359        }
360
361        #[test]
362        fn static_strt_117() {
363            helper_test_chksum(
364                &get_bank_dirpath()
365                    .join("checksum")
366                    .join("static-strt-117.work"),
367            );
368        }
369
370        #[test]
371        fn static_strt_116() {
372            helper_test_chksum(
373                &get_bank_dirpath()
374                    .join("checksum")
375                    .join("static-strt-116.work"),
376            );
377        }
378
379        #[test]
380        fn static_strt_115() {
381            helper_test_chksum(
382                &get_bank_dirpath()
383                    .join("checksum")
384                    .join("static-strt-115.work"),
385            );
386        }
387
388        #[test]
389        fn static_strt_114() {
390            helper_test_chksum(
391                &get_bank_dirpath()
392                    .join("checksum")
393                    .join("static-strt-114.work"),
394            );
395        }
396
397        #[test]
398        fn static_strt_113() {
399            helper_test_chksum(
400                &get_bank_dirpath()
401                    .join("checksum")
402                    .join("static-strt-113.work"),
403            );
404        }
405
406        #[test]
407        fn static_strt_112() {
408            helper_test_chksum(
409                &get_bank_dirpath()
410                    .join("checksum")
411                    .join("static-strt-112.work"),
412            );
413        }
414
415        #[test]
416        fn static_strt_111() {
417            helper_test_chksum(
418                &get_bank_dirpath()
419                    .join("checksum")
420                    .join("static-strt-111.work"),
421            );
422        }
423
424        #[test]
425        fn static_strt_71() {
426            helper_test_chksum(
427                &get_bank_dirpath()
428                    .join("checksum")
429                    .join("static-strt-71.work"),
430            );
431        }
432
433        #[test]
434        fn static_strt_70() {
435            helper_test_chksum(
436                &get_bank_dirpath()
437                    .join("checksum")
438                    .join("static-strt-70.work"),
439            );
440        }
441
442        #[test]
443        fn static_strt_69() {
444            helper_test_chksum(
445                &get_bank_dirpath()
446                    .join("checksum")
447                    .join("static-strt-69.work"),
448            );
449        }
450
451        #[test]
452        fn static_strt_68() {
453            helper_test_chksum(
454                &get_bank_dirpath()
455                    .join("checksum")
456                    .join("static-strt-68.work"),
457            );
458        }
459
460        #[test]
461        fn static_strt_67() {
462            helper_test_chksum(
463                &get_bank_dirpath()
464                    .join("checksum")
465                    .join("static-strt-67.work"),
466            );
467        }
468
469        #[test]
470        fn static_strt_66() {
471            helper_test_chksum(
472                &get_bank_dirpath()
473                    .join("checksum")
474                    .join("static-strt-66.work"),
475            );
476        }
477
478        #[test]
479        fn static_strt_65() {
480            helper_test_chksum(
481                &get_bank_dirpath()
482                    .join("checksum")
483                    .join("static-strt-65.work"),
484            );
485        }
486
487        #[test]
488        fn static_strt_64() {
489            helper_test_chksum(
490                &get_bank_dirpath()
491                    .join("checksum")
492                    .join("static-strt-64.work"),
493            );
494        }
495
496        #[test]
497        fn static_strt_63() {
498            helper_test_chksum(
499                &get_bank_dirpath()
500                    .join("checksum")
501                    .join("static-strt-63.work"),
502            );
503        }
504
505        #[test]
506        fn static_strt_62() {
507            helper_test_chksum(
508                &get_bank_dirpath()
509                    .join("checksum")
510                    .join("static-strt-62.work"),
511            );
512        }
513
514        #[test]
515        fn static_strt_61() {
516            helper_test_chksum(
517                &get_bank_dirpath()
518                    .join("checksum")
519                    .join("static-strt-61.work"),
520            );
521        }
522
523        #[test]
524        fn static_strt_60() {
525            helper_test_chksum(
526                &get_bank_dirpath()
527                    .join("checksum")
528                    .join("static-strt-60.work"),
529            );
530        }
531
532        #[test]
533        fn static_strt_59() {
534            helper_test_chksum(
535                &get_bank_dirpath()
536                    .join("checksum")
537                    .join("static-strt-59.work"),
538            );
539        }
540
541        #[test]
542        fn static_strt_58() {
543            helper_test_chksum(
544                &get_bank_dirpath()
545                    .join("checksum")
546                    .join("static-strt-58.work"),
547            );
548        }
549
550        #[test]
551        fn static_strt_57() {
552            helper_test_chksum(
553                &get_bank_dirpath()
554                    .join("checksum")
555                    .join("static-strt-57.work"),
556            );
557        }
558
559        #[test]
560        fn static_strt_56() {
561            helper_test_chksum(
562                &get_bank_dirpath()
563                    .join("checksum")
564                    .join("static-strt-56.work"),
565            );
566        }
567    }
568
569    mod static_strt_mult {
570        use crate::banks::checksum::helper_test_chksum;
571        use crate::test_utils::get_bank_dirpath;
572
573        #[test]
574        fn static_strt_127_len_128() {
575            // start value incremented by 127 (max) and len incremented by 127 (max) on the machine
576            helper_test_chksum(
577                &get_bank_dirpath()
578                    .join("checksum")
579                    .join("static-strt-127-len-128.work"),
580            );
581        }
582
583        #[test]
584        fn static_strt_67_len_67() {
585            helper_test_chksum(
586                &get_bank_dirpath()
587                    .join("checksum")
588                    .join("static-strt-67-len-67.work"),
589            );
590        }
591
592        #[test]
593        fn static_strt_67_len_68() {
594            helper_test_chksum(
595                &get_bank_dirpath()
596                    .join("checksum")
597                    .join("static-strt-67-len-68.work"),
598            );
599        }
600
601        #[test]
602        fn static_strt_68_len_68() {
603            helper_test_chksum(
604                &get_bank_dirpath()
605                    .join("checksum")
606                    .join("static-strt-68-len-68.work"),
607            );
608        }
609
610        #[test]
611        fn static_strt_67_len_66() {
612            helper_test_chksum(
613                &get_bank_dirpath()
614                    .join("checksum")
615                    .join("static-strt-67-len-66.work"),
616            );
617        }
618
619        #[test]
620        fn static_strt_66_len_66() {
621            helper_test_chksum(
622                &get_bank_dirpath()
623                    .join("checksum")
624                    .join("static-strt-66-len-66.work"),
625            );
626        }
627
628        #[test]
629        fn static_strt_32_len_32() {
630            helper_test_chksum(
631                &get_bank_dirpath()
632                    .join("checksum")
633                    .join("static-strt-32-len-32.work"),
634            );
635        }
636
637        #[test]
638        fn static_strt_32_len_33() {
639            helper_test_chksum(
640                &get_bank_dirpath()
641                    .join("checksum")
642                    .join("static-strt-32-len-33.work"),
643            );
644        }
645
646        #[test]
647        fn static_strt_33_len_33() {
648            helper_test_chksum(
649                &get_bank_dirpath()
650                    .join("checksum")
651                    .join("static-strt-33-len-33.work"),
652            );
653        }
654
655        #[test]
656        fn static_strt_32_len_31() {
657            helper_test_chksum(
658                &get_bank_dirpath()
659                    .join("checksum")
660                    .join("static-strt-32-len-31.work"),
661            );
662        }
663
664        #[test]
665        fn static_strt_31_len_31() {
666            helper_test_chksum(
667                &get_bank_dirpath()
668                    .join("checksum")
669                    .join("static-strt-31-len-31.work"),
670            );
671        }
672
673        #[test]
674        fn static_strt_67_len_67_rtrg_68() {
675            helper_test_chksum(
676                &get_bank_dirpath()
677                    .join("checksum")
678                    .join("static-strt-67-len-67-rtrg-68.work"),
679            );
680        }
681
682        #[test]
683        fn static_strt_67_len_68_rtrg_68() {
684            helper_test_chksum(
685                &get_bank_dirpath()
686                    .join("checksum")
687                    .join("static-strt-67-len-68-rtrg-68.work"),
688            );
689        }
690
691        #[test]
692        fn static_strt_67_len_69_rtrg_68() {
693            helper_test_chksum(
694                &get_bank_dirpath()
695                    .join("checksum")
696                    .join("static-strt-67-len-69-rtrg-68.work"),
697            );
698        }
699
700        #[test]
701        fn static_strt_67_len_69_rtrg_69() {
702            helper_test_chksum(
703                &get_bank_dirpath()
704                    .join("checksum")
705                    .join("static-strt-67-len-69-rtrg-69.work"),
706            );
707        }
708
709        #[test]
710        fn static_strt_67_len_69_rtrg_67() {
711            helper_test_chksum(
712                &get_bank_dirpath()
713                    .join("checksum")
714                    .join("static-strt-67-len-69-rtrg-67.work"),
715            );
716        }
717
718        #[test]
719        fn static_strt_67_len_67_rtrg_67() {
720            helper_test_chksum(
721                &get_bank_dirpath()
722                    .join("checksum")
723                    .join("static-strt-67-len-67-rtrg-67.work"),
724            );
725        }
726    }
727
728    mod flex_strt {
729        use crate::banks::checksum::helper_test_chksum;
730        use crate::test_utils::get_bank_dirpath;
731
732        #[test]
733        fn flex_strt_126() {
734            helper_test_chksum(
735                &get_bank_dirpath()
736                    .join("checksum")
737                    .join("flex-strt-126.work"),
738            );
739        }
740
741        #[test]
742        fn flex_strt_125() {
743            helper_test_chksum(
744                &get_bank_dirpath()
745                    .join("checksum")
746                    .join("flex-strt-125.work"),
747            );
748        }
749
750        #[test]
751        fn flex_strt_124() {
752            helper_test_chksum(
753                &get_bank_dirpath()
754                    .join("checksum")
755                    .join("flex-strt-124.work"),
756            );
757        }
758
759        #[test]
760        fn flex_strt_123() {
761            helper_test_chksum(
762                &get_bank_dirpath()
763                    .join("checksum")
764                    .join("flex-strt-123.work"),
765            );
766        }
767
768        #[test]
769        fn flex_strt_122() {
770            helper_test_chksum(
771                &get_bank_dirpath()
772                    .join("checksum")
773                    .join("flex-strt-122.work"),
774            );
775        }
776
777        #[test]
778        fn flex_strt_121() {
779            helper_test_chksum(
780                &get_bank_dirpath()
781                    .join("checksum")
782                    .join("flex-strt-121.work"),
783            );
784        }
785
786        #[test]
787        fn flex_strt_120() {
788            helper_test_chksum(
789                &get_bank_dirpath()
790                    .join("checksum")
791                    .join("flex-strt-120.work"),
792            );
793        }
794
795        #[test]
796        fn flex_strt_119() {
797            helper_test_chksum(
798                &get_bank_dirpath()
799                    .join("checksum")
800                    .join("flex-strt-119.work"),
801            );
802        }
803
804        #[test]
805        fn flex_strt_118() {
806            helper_test_chksum(
807                &get_bank_dirpath()
808                    .join("checksum")
809                    .join("flex-strt-118.work"),
810            );
811        }
812
813        #[test]
814        fn flex_strt_117() {
815            helper_test_chksum(
816                &get_bank_dirpath()
817                    .join("checksum")
818                    .join("flex-strt-117.work"),
819            );
820        }
821
822        #[test]
823        fn flex_strt_116() {
824            helper_test_chksum(
825                &get_bank_dirpath()
826                    .join("checksum")
827                    .join("flex-strt-116.work"),
828            );
829        }
830
831        #[test]
832        fn flex_strt_115() {
833            helper_test_chksum(
834                &get_bank_dirpath()
835                    .join("checksum")
836                    .join("flex-strt-115.work"),
837            );
838        }
839
840        #[test]
841        fn flex_strt_114() {
842            helper_test_chksum(
843                &get_bank_dirpath()
844                    .join("checksum")
845                    .join("flex-strt-114.work"),
846            );
847        }
848
849        #[test]
850        fn flex_strt_113() {
851            helper_test_chksum(
852                &get_bank_dirpath()
853                    .join("checksum")
854                    .join("flex-strt-113.work"),
855            );
856        }
857
858        #[test]
859        fn flex_strt_112() {
860            helper_test_chksum(
861                &get_bank_dirpath()
862                    .join("checksum")
863                    .join("flex-strt-112.work"),
864            );
865        }
866
867        #[test]
868        fn flex_strt_111() {
869            helper_test_chksum(
870                &get_bank_dirpath()
871                    .join("checksum")
872                    .join("flex-strt-111.work"),
873            );
874        }
875    }
876
877    mod track_parameters {
878        use crate::banks::checksum::helper_test_chksum;
879        use crate::test_utils::get_bank_dirpath;
880
881        #[test]
882        fn track_params_attack_127() {
883            helper_test_chksum(
884                &get_bank_dirpath()
885                    .join("checksum")
886                    .join("tparams-attack-127.work"),
887            );
888        }
889
890        #[test]
891        fn track_params_hold_0() {
892            helper_test_chksum(
893                &get_bank_dirpath()
894                    .join("checksum")
895                    .join("tparams-hold-0.work"),
896            );
897        }
898
899        #[test]
900        fn track_params_release_0() {
901            helper_test_chksum(
902                &get_bank_dirpath()
903                    .join("checksum")
904                    .join("tparams-rel-0.work"),
905            );
906        }
907        #[test]
908        fn track_params_vol_neg64() {
909            helper_test_chksum(
910                &get_bank_dirpath()
911                    .join("checksum")
912                    .join("tparams-vol-neg64.work"),
913            );
914        }
915
916        #[test]
917        fn track_params_vol_pos63() {
918            helper_test_chksum(
919                &get_bank_dirpath()
920                    .join("checksum")
921                    .join("tparams-vol-pos63.work"),
922            );
923        }
924
925        #[test]
926        fn track_params_balance_neg64() {
927            helper_test_chksum(
928                &get_bank_dirpath()
929                    .join("checksum")
930                    .join("tparams-bal-neg64.work"),
931            );
932        }
933
934        #[test]
935        fn track_params_balance_pos63() {
936            helper_test_chksum(
937                &get_bank_dirpath()
938                    .join("checksum")
939                    .join("tparams-bal-pos63.work"),
940            );
941        }
942
943        #[test]
944        fn track_params_lfo1_spd_0() {
945            helper_test_chksum(
946                &get_bank_dirpath()
947                    .join("checksum")
948                    .join("tparams-lfo1-spd-0.work"),
949            );
950        }
951
952        #[test]
953        fn track_params_lfo1_spd_127() {
954            helper_test_chksum(
955                &get_bank_dirpath()
956                    .join("checksum")
957                    .join("tparams-lfo1-spd-127.work"),
958            );
959        }
960
961        #[test]
962        fn track_params_lfo1_amt_64() {
963            helper_test_chksum(
964                &get_bank_dirpath()
965                    .join("checksum")
966                    .join("tparams-lfo1-amt-64.work"),
967            );
968        }
969
970        #[test]
971        fn track_params_lfo1_amt_127() {
972            helper_test_chksum(
973                &get_bank_dirpath()
974                    .join("checksum")
975                    .join("tparams-lfo1-amt-127.work"),
976            );
977        }
978
979        #[test]
980        fn track_params_fx1_filter_base_127() {
981            helper_test_chksum(
982                &get_bank_dirpath()
983                    .join("checksum")
984                    .join("tparams-fx1-filt-base-127.work"),
985            );
986        }
987
988        #[test]
989        fn track_params_fx1_filter_width_0() {
990            helper_test_chksum(
991                &get_bank_dirpath()
992                    .join("checksum")
993                    .join("tparams-fx1-filt-wid-0.work"),
994            );
995        }
996
997        #[test]
998        fn track_params_fx1_filter_q_127() {
999            helper_test_chksum(
1000                &get_bank_dirpath()
1001                    .join("checksum")
1002                    .join("tparams-fx1-filt-q-127.work"),
1003            );
1004        }
1005
1006        #[test]
1007        fn track_params_fx1_filter_depth_neg64() {
1008            helper_test_chksum(
1009                &get_bank_dirpath()
1010                    .join("checksum")
1011                    .join("tparams-fx1-filt-dep-neg64.work"),
1012            );
1013        }
1014
1015        #[test]
1016        fn track_params_fx1_filter_depth_pos63() {
1017            helper_test_chksum(
1018                &get_bank_dirpath()
1019                    .join("checksum")
1020                    .join("tparams-fx1-filt-dep-pos63.work"),
1021            );
1022        }
1023
1024        #[test]
1025        fn track_params_fx2_delay_snd_127() {
1026            // start value incremented by 127 (max) and len incremented by 127 (max) on the machine
1027            helper_test_chksum(
1028                &get_bank_dirpath()
1029                    .join("checksum")
1030                    .join("atrack1-delay-snd-127.work"),
1031            );
1032        }
1033    }
1034
1035    mod lfo_designer {
1036        use crate::banks::checksum::helper_test_chksum;
1037        use crate::test_utils::get_bank_dirpath;
1038
1039        #[test]
1040        fn lfo_design_atr1_step1_pos64() {
1041            helper_test_chksum(
1042                &get_bank_dirpath()
1043                    .join("checksum")
1044                    .join("lfo-design-step1-64.work"),
1045            );
1046        }
1047
1048        #[test]
1049        fn lfo_design_atr1_step1_pos127() {
1050            helper_test_chksum(
1051                &get_bank_dirpath()
1052                    .join("checksum")
1053                    .join("lfo-design-step1-127.work"),
1054            );
1055        }
1056
1057        #[test]
1058        fn lfo_design_atr1_step1_neg64() {
1059            helper_test_chksum(
1060                &get_bank_dirpath()
1061                    .join("checksum")
1062                    .join("lfo-design-step1-neg64.work"),
1063            );
1064        }
1065
1066        #[test]
1067        fn lfo_design_atr1_step1_neg128() {
1068            helper_test_chksum(
1069                &get_bank_dirpath()
1070                    .join("checksum")
1071                    .join("lfo-design-step1-neg128.work"),
1072            );
1073        }
1074
1075        #[test]
1076        fn lfo_design_atr1_randomised() {
1077            helper_test_chksum(
1078                &get_bank_dirpath()
1079                    .join("checksum")
1080                    .join("lfo-design-randomised.work"),
1081            );
1082        }
1083    }
1084}
1085
1086/// Raw bytes of bank data files. Only really useful for lazy debugging and / or reverse engineering purposes.
1087#[derive(Debug, Serialize, Deserialize, Decodeable)]
1088pub struct BankRawBytes {
1089    pub data: Box<Array<u8, 636113>>,
1090}