nord_format/formats/ne5/program/
piano.rs1use crate::components::{sparse_enum, PianoRef};
4use crate::types::RangedU8;
5use nord_bits_derive::bitbody;
6
7#[bitbody(8)]
12#[derive(Default)]
13pub struct PianoPanel {
14 #[bits(0..=2)]
15 pub category: PianoCategory,
16 #[bits(5..=9)]
19 pub piano_model: RangedU8<31>,
20 #[bits(15..=16)]
21 pub clav_model: RangedU8<3>,
22 #[bits(17..=18)]
23 pub acoustics: RangedU8<3>,
24 #[bits(19..=20)]
25 pub touch: RangedU8<3>,
26 #[bits(21..=21)]
27 pub mono: bool,
28 #[bits(22..=53)]
38 pub id: PianoRef,
39}
40sparse_enum!(
41 PianoCategory, 3, {
43 0 => Grand, "grand";
44 1 => Upright, "upright";
45 2 => EPiano1, "epiano1";
46 3 => EPiano2, "epiano2";
47 4 => Clavinet, "clavinet";
48 5 => Harpsichord, "harps";
49 }
50);
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use crate::bits::Packed;
56 use std::array;
57
58 #[test]
61 fn unnamed_bits_survive_a_re_encode() {
62 const GAPS: [u8; 8] = [0b0001_1000, 0b0011_1110, 0, 0, 0, 0, 0, 0];
64 fn gap_bits(raw: [u8; 8]) -> [u8; 8] {
65 array::from_fn(|i| raw[i] & GAPS[i])
66 }
67
68 let mut panel = PianoPanel::try_from(GAPS).unwrap();
69 panel.category = PianoCategory::EPiano1;
70 panel.id = PianoRef::from_bits(0xdead_beef).expect("a 32-bit id decodes totally");
71 let out = <[u8; 8]>::from(&panel);
72 assert_eq!(gap_bits(out), GAPS, "a re-encode cleared a gap bit");
73
74 let mut panel = PianoPanel::try_from([0; 8]).unwrap();
75 panel.category = PianoCategory::Unknown(7);
76 panel.piano_model = 31u8.try_into().unwrap();
77 let out = <[u8; 8]>::from(&panel);
78 assert_eq!(gap_bits(out), [0; 8], "a re-encode set a gap bit");
79 }
80}