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