1use std::fmt::{self, Debug, Display, Formatter};
11
12use crate::bits::{bits_for, Packed};
13use crate::error::ParseError;
14use crate::fields::{ControlKind, Library, PackedOrder, Unit};
15use crate::types::RangedI8;
16
17pub type OctaveShift<const OFFSET: u8, const MIN: i8, const MAX: i8> = RangedI8<OFFSET, MIN, MAX>;
20
21pub type Transpose<const OFFSET: u8, const MIN: i8, const MAX: i8> = RangedI8<OFFSET, MIN, MAX>;
23
24#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
36pub struct LevelOf<const FULL: u8> {
37 inner: u8,
38}
39
40impl<const FULL: u8> LevelOf<FULL> {
41 const VALID: () = assert!(FULL > 0, "a level needs a nonzero full-scale value");
42
43 pub const MAX: u8 = {
44 let () = Self::VALID;
45 FULL
46 };
47
48 pub fn new(value: u8) -> Result<Self, ParseError> {
49 value.try_into()
50 }
51
52 pub fn as_u8(&self) -> u8 {
54 let () = Self::VALID;
55 self.inner
56 }
57
58 pub fn as_panel(&self) -> f32 {
63 let () = Self::VALID;
64 f32::from(self.inner) / f32::from(FULL) * 10.0
65 }
66}
67
68impl<const FULL: u8> Default for LevelOf<FULL> {
69 fn default() -> Self {
70 let () = Self::VALID;
71 Self { inner: 0 }
72 }
73}
74
75impl<const FULL: u8> TryFrom<u8> for LevelOf<FULL> {
76 type Error = ParseError;
77
78 fn try_from(value: u8) -> Result<Self, ParseError> {
79 let () = Self::VALID;
80 if value > FULL {
81 return Err(ParseError::OutOfBounds {
82 value: format!("{value}"),
83 bound: format!("0..={FULL}"),
84 });
85 }
86 Ok(LevelOf { inner: value })
87 }
88}
89
90impl<const FULL: u8> Packed for LevelOf<FULL> {
91 const MAX_BITS: u32 = {
92 let () = Self::VALID;
93 bits_for(FULL as u64)
94 };
95 const DECODE_BITS: u32 = u8::BITS;
96 const CONTROL: ControlKind = ControlKind::Knob(Unit::Panel10);
97 type Error = ParseError;
98
99 fn from_bits(bits: u64) -> Result<Self, ParseError> {
100 (bits as u8).try_into()
101 }
102
103 fn to_bits(&self) -> u64 {
104 self.inner as u64
105 }
106}
107
108impl<const FULL: u8> Display for LevelOf<FULL> {
109 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
111 write!(f, "{} ({:.1})", self.inner, self.as_panel())
112 }
113}
114
115impl<const FULL: u8> Debug for LevelOf<FULL> {
116 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
117 write!(f, "{}", self.inner)
118 }
119}
120
121impl<const FULL: u8> PartialEq<u8> for LevelOf<FULL> {
122 fn eq(&self, other: &u8) -> bool {
123 self.inner == *other
124 }
125}
126
127pub type Level = LevelOf<127>;
129
130pub type Level6 = LevelOf<63>;
132
133macro_rules! knob {
142 ($(#[$meta:meta])* $name:ident, $unit:expr) => {
143 knob!($(#[$meta])* $name, 127, 7, ControlKind::Knob($unit));
144 };
145 ($(#[$meta:meta])* $name:ident, $max:expr, $bits:expr, $control:expr) => {
146 $(#[$meta])*
147 #[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
148 pub struct $name {
149 inner: u8,
150 }
151
152 impl $name {
153 pub const MAX: u8 = $max;
154
155 pub fn new(value: u8) -> Result<Self, ParseError> {
156 value.try_into()
157 }
158
159 #[doc = concat!("The stored value, 0..=", stringify!($max), ".")]
160 pub fn as_u8(&self) -> u8 {
161 self.inner
162 }
163 }
164
165 impl TryFrom<u8> for $name {
166 type Error = ParseError;
167
168 fn try_from(value: u8) -> Result<Self, ParseError> {
169 if value > Self::MAX {
170 return Err(ParseError::OutOfBounds {
171 value: format!("{value}"),
172 bound: format!("0..={}", Self::MAX),
173 });
174 }
175 Ok($name { inner: value })
176 }
177 }
178
179 impl Packed for $name {
180 const MAX_BITS: u32 = $bits;
181 const DECODE_BITS: u32 = u8::BITS;
182 const CONTROL: ControlKind = $control;
183 type Error = ParseError;
184
185 fn from_bits(bits: u64) -> Result<Self, ParseError> {
186 (bits as u8).try_into()
187 }
188
189 fn to_bits(&self) -> u64 {
190 self.inner as u64
191 }
192 }
193
194 impl Debug for $name {
197 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
198 write!(f, "{}", self.inner)
199 }
200 }
201
202 impl Display for $name {
203 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
204 write!(f, "{}", self.inner)
205 }
206 }
207
208 impl PartialEq<u8> for $name {
209 fn eq(&self, other: &u8) -> bool {
210 self.inner == *other
211 }
212 }
213 };
214}
215
216knob!(
217 Time,
220 Unit::Milliseconds
221);
222
223knob!(
224 Frequency,
227 Unit::Hertz
228);
229
230knob!(
231 Rate,
237 Unit::Hertz
238);
239
240knob!(
241 Pan,
249 63,
250 6,
251 ControlKind::Knob(Unit::Pan)
252);
253
254knob!(
255 Interval,
262 63,
263 6,
264 ControlKind::Shift(Unit::Semitones)
265);
266
267#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
283pub struct BipolarOf<const LIMIT: i16, const UNIT: u8> {
284 inner: u8,
285}
286
287impl<const LIMIT: i16, const UNIT: u8> BipolarOf<LIMIT, UNIT> {
288 pub const MAX: u8 = 127;
289 pub const CENTER: u8 = 64;
291 pub const UNIT: Unit = Unit::expect_code(UNIT);
293
294 pub fn new(value: u8) -> Result<Self, ParseError> {
295 value.try_into()
296 }
297
298 pub fn as_u8(&self) -> u8 {
300 self.inner
301 }
302
303 pub fn reading(&self) -> f32 {
305 let from_center = f32::from(self.inner) - f32::from(Self::CENTER);
306 let span = if from_center < 0.0 {
307 f32::from(Self::CENTER)
308 } else {
309 f32::from(Self::MAX - Self::CENTER)
310 };
311 from_center / span * f32::from(LIMIT)
312 }
313}
314
315impl<const LIMIT: i16, const UNIT: u8> TryFrom<u8> for BipolarOf<LIMIT, UNIT> {
316 type Error = ParseError;
317
318 fn try_from(value: u8) -> Result<Self, ParseError> {
319 if value > Self::MAX {
320 return Err(ParseError::OutOfBounds {
321 value: format!("{value}"),
322 bound: format!("0..={}", Self::MAX),
323 });
324 }
325 Ok(BipolarOf { inner: value })
326 }
327}
328
329impl<const LIMIT: i16, const UNIT: u8> Packed for BipolarOf<LIMIT, UNIT> {
330 const MAX_BITS: u32 = 7;
331 const DECODE_BITS: u32 = u8::BITS;
332 const CONTROL: ControlKind = ControlKind::Bipolar(Unit::expect_code(UNIT));
333 type Error = ParseError;
334
335 fn from_bits(bits: u64) -> Result<Self, ParseError> {
336 (bits as u8).try_into()
337 }
338
339 fn to_bits(&self) -> u64 {
340 self.inner as u64
341 }
342}
343
344impl<const LIMIT: i16, const UNIT: u8> Debug for BipolarOf<LIMIT, UNIT> {
346 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
347 write!(f, "{}", self.inner)
348 }
349}
350
351impl<const LIMIT: i16, const UNIT: u8> Display for BipolarOf<LIMIT, UNIT> {
352 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
354 write!(f, "{} ({:+.1})", self.inner, self.reading())
355 }
356}
357
358impl<const LIMIT: i16, const UNIT: u8> PartialEq<u8> for BipolarOf<LIMIT, UNIT> {
359 fn eq(&self, other: &u8) -> bool {
360 self.inner == *other
361 }
362}
363
364pub type EqBand = BipolarOf<15, { Unit::Decibels.code() }>;
366
367pub type Bipolar<const LIMIT: i16> = BipolarOf<LIMIT, { Unit::None.code() }>;
370
371#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
389pub struct MorphOf<const BITS: u32> {
390 inner: u8,
391}
392
393impl<const BITS: u32> MorphOf<BITS> {
394 const VALID: () = assert!(BITS > 0 && BITS <= 8, "a morph must fit in a byte");
395
396 pub const NEUTRAL: u8 = {
398 let () = Self::VALID;
399 ((1u16 << BITS) / 2 - 1) as u8
400 };
401
402 pub fn as_u8(&self) -> u8 {
403 let () = Self::VALID;
404 self.inner
405 }
406
407 pub fn is_neutral(&self) -> bool {
409 self.inner == Self::NEUTRAL
410 }
411}
412
413impl<const BITS: u32> Default for MorphOf<BITS> {
414 fn default() -> Self {
415 let () = Self::VALID;
416 Self { inner: 0 }
417 }
418}
419
420impl<const BITS: u32> Packed for MorphOf<BITS> {
421 const MAX_BITS: u32 = {
422 let () = Self::VALID;
423 BITS
424 };
425 const DECODE_BITS: u32 = u8::BITS;
426 const CONTROL: ControlKind = ControlKind::Morph { of: None };
430 type Error = ::core::convert::Infallible;
431
432 fn from_bits(bits: u64) -> Result<Self, Self::Error> {
433 let () = Self::VALID;
434 Ok(MorphOf { inner: bits as u8 })
435 }
436
437 fn to_bits(&self) -> u64 {
438 self.inner as u64
439 }
440}
441
442impl<const BITS: u32> Debug for MorphOf<BITS> {
444 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
445 write!(f, "{}", self.inner)
446 }
447}
448
449impl<const BITS: u32> Display for MorphOf<BITS> {
450 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
452 if self.is_neutral() {
453 f.write_str("—")
454 } else {
455 write!(f, "{}", self.inner)
456 }
457 }
458}
459
460impl<const BITS: u32> PartialEq<u8> for MorphOf<BITS> {
461 fn eq(&self, other: &u8) -> bool {
462 self.inner == *other
463 }
464}
465
466pub type MorphTarget = MorphOf<8>;
468
469pub type DrawbarMorph = MorphOf<5>;
471
472pub type SwitchMorph = MorphOf<3>;
474
475#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
477pub struct WideSelector<const BITS: u32> {
478 inner: u16,
479}
480
481impl<const BITS: u32> WideSelector<BITS> {
482 const VALID: () = assert!(BITS > 0 && BITS <= 16, "a wide selector must fit in a u16");
483
484 pub fn raw(&self) -> u16 {
486 let () = Self::VALID;
487 self.inner
488 }
489}
490
491impl<const BITS: u32> Default for WideSelector<BITS> {
492 fn default() -> Self {
493 let () = Self::VALID;
494 Self { inner: 0 }
495 }
496}
497
498impl<const BITS: u32> Packed for WideSelector<BITS> {
499 const MAX_BITS: u32 = {
500 let () = Self::VALID;
501 BITS
502 };
503 const DECODE_BITS: u32 = u16::BITS;
504 const CONTROL: ControlKind = ControlKind::Selector;
505 type Error = ::core::convert::Infallible;
506
507 fn from_bits(bits: u64) -> Result<Self, Self::Error> {
508 let () = Self::VALID;
509 Ok(WideSelector { inner: bits as u16 })
510 }
511
512 fn to_bits(&self) -> u64 {
513 self.inner as u64
514 }
515}
516
517impl<const BITS: u32> Debug for WideSelector<BITS> {
518 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
519 write!(f, "{}", self.inner)
520 }
521}
522
523impl<const BITS: u32> Display for WideSelector<BITS> {
524 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
525 write!(f, "{}", self.inner)
526 }
527}
528
529impl<const BITS: u32> PartialEq<u16> for WideSelector<BITS> {
530 fn eq(&self, other: &u16) -> bool {
531 self.inner == *other
532 }
533}
534
535#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
551pub struct Drawbar {
552 inner: u8,
553}
554
555impl Drawbar {
556 pub const MAX: u8 = 8;
558
559 pub fn new(position: u8) -> Result<Self, ParseError> {
562 if position > Self::MAX {
563 return Err(ParseError::OutOfBounds {
564 value: format!("{position}"),
565 bound: format!("0..={}", Self::MAX),
566 });
567 }
568 Ok(Drawbar { inner: position })
569 }
570
571 pub fn raw(&self) -> u8 {
573 self.inner
574 }
575
576 pub fn position(&self) -> Option<u8> {
578 (self.inner <= Self::MAX).then_some(self.inner)
579 }
580}
581
582impl Packed for Drawbar {
583 const MAX_BITS: u32 = 4;
584 const DECODE_BITS: u32 = u8::BITS;
585 const CONTROL: ControlKind = ControlKind::Drawbar {
588 bars: 1,
589 rank: None,
590 bits_per_bar: Self::MAX_BITS as u8,
591 order: PackedOrder::HighFirst,
593 };
594 type Error = ::core::convert::Infallible;
595
596 fn from_bits(bits: u64) -> Result<Self, Self::Error> {
597 Ok(Drawbar { inner: bits as u8 })
598 }
599
600 fn to_bits(&self) -> u64 {
601 self.inner as u64
602 }
603}
604
605impl Debug for Drawbar {
606 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
607 write!(f, "{}", self.inner)
608 }
609}
610
611impl Display for Drawbar {
612 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
613 write!(f, "{}", self.inner)
614 }
615}
616
617impl PartialEq<u8> for Drawbar {
618 fn eq(&self, other: &u8) -> bool {
619 self.inner == *other
620 }
621}
622
623#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
630pub struct OctaveShiftNibble {
631 inner: i8,
633}
634
635impl OctaveShiftNibble {
636 pub fn octaves(&self) -> i8 {
638 self.inner
639 }
640}
641
642impl Packed for OctaveShiftNibble {
643 const MAX_BITS: u32 = 4;
644 const DECODE_BITS: u32 = 4;
645 const CONTROL: ControlKind = ControlKind::Shift(Unit::Octaves);
646 type Error = ::core::convert::Infallible;
647
648 fn from_bits(bits: u64) -> Result<Self, Self::Error> {
649 let nibble = (bits & 0xf) as i8;
650 Ok(OctaveShiftNibble {
651 inner: if nibble >= 8 { nibble - 16 } else { nibble },
652 })
653 }
654
655 fn to_bits(&self) -> u64 {
656 (self.inner as u8 & 0xf) as u64
657 }
658}
659
660impl Debug for OctaveShiftNibble {
661 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
662 write!(f, "{}", self.inner)
663 }
664}
665
666impl Display for OctaveShiftNibble {
667 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
668 write!(f, "{:+}", self.inner)
669 }
670}
671
672impl PartialEq<i8> for OctaveShiftNibble {
673 fn eq(&self, other: &i8) -> bool {
674 self.inner == *other
675 }
676}
677
678#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
683pub struct Selector<const BITS: u32> {
684 inner: u8,
685}
686
687impl<const BITS: u32> Selector<BITS> {
688 const VALID: () = assert!(BITS > 0 && BITS <= 8, "a selector must fit in a byte");
689
690 pub fn raw(&self) -> u8 {
692 let () = Self::VALID;
693 self.inner
694 }
695}
696
697impl<const BITS: u32> Default for Selector<BITS> {
698 fn default() -> Self {
699 let () = Self::VALID;
700 Self { inner: 0 }
701 }
702}
703
704impl<const BITS: u32> Packed for Selector<BITS> {
705 const MAX_BITS: u32 = {
706 let () = Self::VALID;
707 BITS
708 };
709 const DECODE_BITS: u32 = u8::BITS;
710 const CONTROL: ControlKind = ControlKind::Selector;
711 type Error = ::core::convert::Infallible;
712
713 fn from_bits(bits: u64) -> Result<Self, Self::Error> {
714 let () = Self::VALID;
715 Ok(Selector { inner: bits as u8 })
716 }
717
718 fn to_bits(&self) -> u64 {
719 self.inner as u64
720 }
721}
722
723impl<const BITS: u32> Debug for Selector<BITS> {
725 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
726 write!(f, "{}", self.inner)
727 }
728}
729
730impl<const BITS: u32> Display for Selector<BITS> {
731 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
732 write!(f, "{}", self.inner)
733 }
734}
735
736impl<const BITS: u32> PartialEq<u8> for Selector<BITS> {
737 fn eq(&self, other: &u8) -> bool {
738 self.inner == *other
739 }
740}
741
742pub type ClockDivision = Selector<4>;
752
753#[derive(Copy, Default, Clone, PartialEq, Eq)]
758pub struct PartMix {
759 inner: u8,
760}
761
762impl PartMix {
763 pub fn inner(&self) -> u8 {
764 self.inner
765 }
766
767 pub fn lower(&self) -> f32 {
768 let lower = 100_f32 - ((self.inner() as f32) / 127.0) * 100_f32;
769
770 if lower > 50_f32 {
771 50_f32
772 } else {
773 lower
774 }
775 }
776
777 pub fn upper(&self) -> f32 {
778 let upper = ((self.inner() as f32) / 127.0) * 100_f32;
779
780 if upper > 50_f32 {
781 50_f32
782 } else {
783 upper
784 }
785 }
786}
787
788impl Display for PartMix {
789 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
791 write!(f, "{:.1}/{:.1}", self.lower(), self.upper())
792 }
793}
794
795impl Debug for PartMix {
796 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
797 write!(f, "{self}")
798 }
799}
800
801impl Packed for PartMix {
802 const MAX_BITS: u32 = 7;
803 const DECODE_BITS: u32 = u8::BITS;
804 const CONTROL: ControlKind = ControlKind::Bipolar(Unit::None);
805 type Error = ParseError;
806
807 fn from_bits(bits: u64) -> Result<Self, ParseError> {
808 (bits as u8).try_into()
809 }
810
811 fn to_bits(&self) -> u64 {
812 self.inner() as u64
813 }
814}
815
816impl TryFrom<u8> for PartMix {
817 type Error = ParseError;
818
819 fn try_from(value: u8) -> Result<Self, Self::Error> {
820 if value > 127 {
821 return Err(ParseError::OutOfBounds {
822 value: format!("{value}"),
823 bound: "0..=127".to_string(),
824 });
825 }
826
827 Ok(PartMix { inner: value })
828 }
829}
830
831#[derive(Debug, Clone, Copy, PartialEq, Eq)]
834pub enum PercSpeed {
835 Off,
836 Soft,
837 Fast,
838 Both,
839}
840
841#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
844pub enum SplitPoint73 {
845 #[default]
846 C3,
847 F3,
848 C4,
849 F4,
850 C5,
851 F5,
852 Upper,
853 Lower,
854}
855
856impl TryFrom<u8> for SplitPoint73 {
857 type Error = ParseError;
858
859 fn try_from(value: u8) -> Result<SplitPoint73, ParseError> {
860 match value {
861 0 => Ok(SplitPoint73::C3),
862 1 => Ok(SplitPoint73::F3),
863 2 => Ok(SplitPoint73::C4),
864 3 => Ok(SplitPoint73::F4),
865 4 => Ok(SplitPoint73::C5),
866 5 => Ok(SplitPoint73::F5),
867 6 => Ok(SplitPoint73::Upper),
868 7 => Ok(SplitPoint73::Lower),
869 _ => Err(ParseError::OutOfBounds {
870 value: format!("{value}"),
871 bound: "0..=7 (SplitPoint73)".to_string(),
872 }),
873 }
874 }
875}
876
877impl Packed for SplitPoint73 {
878 const MAX_BITS: u32 = 3;
879 const DECODE_BITS: u32 = u8::BITS;
880 const CONTROL: ControlKind = ControlKind::Selector;
881 type Error = ParseError;
882
883 fn from_bits(bits: u64) -> Result<Self, ParseError> {
884 (bits as u8).try_into()
885 }
886
887 fn to_bits(&self) -> u64 {
888 *self as u64
889 }
890}
891
892#[derive(Debug, Clone, Copy, PartialEq, Eq)]
897pub enum VibChorus {
898 V1,
899 C1,
900 V2,
901 C2,
902 V3,
903 C3,
904}
905
906#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
913pub struct StageTranspose {
914 raw: u8,
915}
916
917impl StageTranspose {
918 pub fn raw(&self) -> u8 {
920 self.raw
921 }
922
923 pub fn semitones(&self) -> Option<i8> {
925 (self.raw <= 12).then(|| self.raw as i8 - 6)
926 }
927}
928
929impl Packed for StageTranspose {
930 const MAX_BITS: u32 = 4;
931 const DECODE_BITS: u32 = u8::BITS;
932 const CONTROL: ControlKind = ControlKind::Shift(Unit::Semitones);
933 type Error = ::core::convert::Infallible;
934
935 fn from_bits(bits: u64) -> Result<Self, Self::Error> {
936 Ok(StageTranspose { raw: bits as u8 })
937 }
938
939 fn to_bits(&self) -> u64 {
940 self.raw as u64
941 }
942}
943
944impl Debug for StageTranspose {
945 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
946 match self.semitones() {
947 Some(s) => write!(f, "{s}"),
948 None => write!(f, "unknown ({})", self.raw),
949 }
950 }
951}
952
953#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
957pub struct MasterTempo {
958 inner: u8,
959}
960
961impl MasterTempo {
962 pub fn as_u8(&self) -> u8 {
964 self.inner
965 }
966
967 pub fn bpm(&self) -> u16 {
969 self.inner as u16 + 30
970 }
971}
972
973impl Packed for MasterTempo {
974 const MAX_BITS: u32 = 8;
975 const DECODE_BITS: u32 = u8::BITS;
976 const CONTROL: ControlKind = ControlKind::Knob(Unit::Bpm);
977 type Error = ::core::convert::Infallible;
978
979 fn from_bits(bits: u64) -> Result<Self, Self::Error> {
980 Ok(MasterTempo { inner: bits as u8 })
981 }
982
983 fn to_bits(&self) -> u64 {
984 self.inner as u64
985 }
986}
987
988impl Debug for MasterTempo {
989 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
991 write!(f, "{}", self.bpm())
992 }
993}
994
995macro_rules! sparse_enum {
1001 (
1002 $(#[$meta:meta])*
1003 $name:ident, $bits:expr, { $($value:expr => $variant:ident, $label:expr;)+ }
1004 ) => {
1005 $(#[$meta])*
1006 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1007 pub enum $name {
1008 $($variant,)+
1009 Unknown(u8),
1011 }
1012
1013 impl ::core::fmt::Debug for $name {
1017 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
1018 match self {
1019 $($name::$variant => f.write_str(stringify!($variant)),)+
1020 $name::Unknown(raw) => write!(f, "unknown ({raw})"),
1021 }
1022 }
1023 }
1024
1025 impl $name {
1026 pub fn label(&self) -> Option<&'static str> {
1028 match self {
1029 $($name::$variant => Some($label),)+
1030 $name::Unknown(_) => None,
1031 }
1032 }
1033
1034 pub fn is_unknown(&self) -> bool {
1036 matches!(self, $name::Unknown(_))
1037 }
1038
1039 pub fn raw(&self) -> u8 {
1041 <Self as $crate::bits::Packed>::to_bits(self) as u8
1042 }
1043 }
1044
1045 impl Default for $name {
1046 fn default() -> Self {
1047 match <Self as $crate::bits::Packed>::from_bits(0) {
1048 Ok(v) => v,
1049 Err(never) => match never {},
1050 }
1051 }
1052 }
1053
1054 impl $crate::bits::Packed for $name {
1055 const MAX_BITS: u32 = $bits;
1056 const DECODE_BITS: u32 = u8::BITS;
1057 const CONTROL: $crate::fields::ControlKind = $crate::fields::ControlKind::Selector;
1058 type Error = ::core::convert::Infallible;
1059
1060 fn from_bits(bits: u64) -> Result<Self, Self::Error> {
1061 Ok(match bits as u8 {
1062 $($value => $name::$variant,)+
1063 other => $name::Unknown(other),
1064 })
1065 }
1066
1067 fn to_bits(&self) -> u64 {
1068 match self {
1069 $($name::$variant => $value as u64,)+
1070 $name::Unknown(raw) => *raw as u64,
1071 }
1072 }
1073 }
1074
1075 impl ::core::fmt::Display for $name {
1076 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
1077 match self.label() {
1078 Some(label) => f.write_str(label),
1079 None => write!(f, "unknown ({})", self.raw()),
1080 }
1081 }
1082 }
1083 };
1084}
1085
1086pub(crate) use sparse_enum;
1087
1088macro_rules! switch {
1094 (
1095 $(#[$meta:meta])*
1096 $name:ident, $clear:ident = $clear_label:expr, $set:ident = $set_label:expr
1097 ) => {
1098 $(#[$meta])*
1099 #[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1100 pub enum $name {
1101 #[default]
1103 $clear,
1104 $set,
1106 }
1107
1108 impl $name {
1109 pub fn label(&self) -> &'static str {
1111 match self {
1112 $name::$clear => $clear_label,
1113 $name::$set => $set_label,
1114 }
1115 }
1116
1117 pub fn is_set(&self) -> bool {
1119 matches!(self, $name::$set)
1120 }
1121 }
1122
1123 impl $crate::bits::Packed for $name {
1124 const MAX_BITS: u32 = 1;
1125 const DECODE_BITS: u32 = 1;
1126 const CONTROL: $crate::fields::ControlKind = $crate::fields::ControlKind::Toggle;
1127 type Error = ::core::convert::Infallible;
1128
1129 fn from_bits(bits: u64) -> Result<Self, Self::Error> {
1130 Ok(if bits != 0 { $name::$set } else { $name::$clear })
1131 }
1132
1133 fn to_bits(&self) -> u64 {
1134 self.is_set() as u64
1135 }
1136 }
1137
1138 impl ::core::fmt::Debug for $name {
1141 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
1142 match self {
1143 $name::$clear => f.write_str(stringify!($clear)),
1144 $name::$set => f.write_str(stringify!($set)),
1145 }
1146 }
1147 }
1148
1149 impl ::core::fmt::Display for $name {
1150 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
1151 f.write_str(self.label())
1152 }
1153 }
1154 };
1155}
1156
1157#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
1175pub struct ArpPattern {
1176 inner: u32,
1177}
1178
1179impl ArpPattern {
1180 pub const STEPS: usize = 16;
1182
1183 pub fn raw(&self) -> u32 {
1185 self.inner
1186 }
1187
1188 pub fn steps(&self) -> [u8; Self::STEPS] {
1190 std::array::from_fn(|n| ((self.inner >> (2 * n)) & 0b11) as u8)
1191 }
1192
1193 pub fn is_empty(&self) -> bool {
1195 self.inner == 0
1196 }
1197}
1198
1199impl Packed for ArpPattern {
1200 const MAX_BITS: u32 = 32;
1201 const DECODE_BITS: u32 = u32::BITS;
1202 const CONTROL: ControlKind = ControlKind::Pattern {
1203 steps: Self::STEPS as u8,
1204 bits_per_step: (Self::MAX_BITS / Self::STEPS as u32) as u8,
1206 order: PackedOrder::LowFirst,
1207 };
1208 type Error = ::core::convert::Infallible;
1209
1210 fn from_bits(bits: u64) -> Result<Self, Self::Error> {
1211 Ok(ArpPattern { inner: bits as u32 })
1212 }
1213
1214 fn to_bits(&self) -> u64 {
1215 self.inner as u64
1216 }
1217}
1218
1219impl Debug for ArpPattern {
1220 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1222 write!(f, "{:#010x}", self.inner)
1223 }
1224}
1225
1226impl Display for ArpPattern {
1227 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1229 for (n, step) in self.steps().into_iter().enumerate() {
1230 if n > 0 && n % 4 == 0 {
1231 f.write_str(" ")?;
1232 }
1233 match step {
1234 0 => f.write_str(".")?,
1235 s => write!(f, "{s}")?,
1236 }
1237 }
1238 Ok(())
1239 }
1240}
1241
1242impl PartialEq<u32> for ArpPattern {
1243 fn eq(&self, other: &u32) -> bool {
1244 self.inner == *other
1245 }
1246}
1247
1248#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1255pub struct LibraryRefOf<const LIBRARY: u8> {
1256 inner: u32,
1257}
1258
1259impl<const LIBRARY: u8> LibraryRefOf<LIBRARY> {
1260 pub const LIBRARY: Library = Library::expect_code(LIBRARY);
1262
1263 pub fn id(&self) -> u32 {
1265 self.inner
1266 }
1267
1268 pub fn is_none(&self) -> bool {
1269 self.inner == 0
1270 }
1271}
1272
1273impl<const LIBRARY: u8> Packed for LibraryRefOf<LIBRARY> {
1274 const MAX_BITS: u32 = 32;
1275 const DECODE_BITS: u32 = u32::BITS;
1276 const CONTROL: ControlKind = ControlKind::Reference(Library::expect_code(LIBRARY));
1277 type Error = ::core::convert::Infallible;
1278
1279 fn from_bits(bits: u64) -> Result<Self, Self::Error> {
1280 Ok(LibraryRefOf { inner: bits as u32 })
1281 }
1282
1283 fn to_bits(&self) -> u64 {
1284 self.inner as u64
1285 }
1286}
1287
1288impl<const LIBRARY: u8> Debug for LibraryRefOf<LIBRARY> {
1289 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1291 write!(f, "{:#010x}", self.inner)
1292 }
1293}
1294
1295impl<const LIBRARY: u8> Display for LibraryRefOf<LIBRARY> {
1296 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1297 if self.is_none() {
1298 f.write_str("none")
1299 } else {
1300 write!(f, "{:#010x}", self.inner)
1301 }
1302 }
1303}
1304
1305impl<const LIBRARY: u8> PartialEq<u32> for LibraryRefOf<LIBRARY> {
1306 fn eq(&self, other: &u32) -> bool {
1307 self.inner == *other
1308 }
1309}
1310
1311pub type PianoRef = LibraryRefOf<{ Library::Piano.code() }>;
1313
1314pub type SampleRef = LibraryRefOf<{ Library::Sample.code() }>;
1316
1317switch!(
1318 DelayCharacter, Normal = "normal", Analog = "analog"
1324);
1325
1326switch!(
1327 CompressorResponse, Normal = "normal", Fast = "fast"
1330);
1331
1332switch!(
1333 RotorSpeed, Slow = "slow", Fast = "fast"
1339);
1340
1341sparse_enum!(
1342 KbZone4, 4, {
1352 0 => V0, "o---";
1353 1 => V1, "-o--";
1354 2 => V2, "--o-";
1355 3 => V3, "---o";
1356 4 => V4, "oo--";
1357 5 => V5, "-oo-";
1358 6 => V6, "--oo";
1359 7 => V7, "ooo-";
1360 8 => V8, "-ooo";
1361 9 => V9, "oooo";
1362 }
1363);
1364
1365sparse_enum!(
1366 KbZone3, 3, {
1371 0 => Lo, "LO";
1372 1 => LoUp, "LO UP";
1373 2 => Up, "UP";
1374 3 => UpHi, "UP HI";
1375 4 => Hi, "HI";
1376 5 => LoUpHi, "LO UP HI";
1377 }
1378);
1379
1380sparse_enum!(
1381 SplitNote, 4, {
1386 0 => F2, "F2";
1387 1 => C3, "C3";
1388 2 => F3, "F3";
1389 3 => C4, "C4";
1390 4 => F4, "F4";
1391 5 => C5, "C5";
1392 6 => F5, "F5";
1393 7 => C6, "C6";
1394 8 => F6, "F6";
1395 9 => C7, "C7";
1396 }
1397);
1398
1399sparse_enum!(
1400 SplitWidth, 2, {
1404 0 => One, "1";
1405 1 => Six, "6";
1406 2 => Twelve, "12";
1407 }
1408);
1409
1410sparse_enum!(
1411 ProgramCategory, 8, {
1416 0x00 => Acoustic, "Acoustic";
1417 0x01 => Bass, "Bass";
1418 0x02 => Wind, "Wind";
1419 0x04 => Fantasy, "Fantasy";
1420 0x05 => Fx, "FX";
1421 0x06 => Lead, "Lead";
1422 0x07 => Organ, "Organ";
1423 0x08 => Pad, "Pad";
1424 0x0a => Pluck, "Pluck";
1425 0x0b => String, "String";
1426 0x0c => Synth, "Synth";
1427 0x0d => Vocal, "Vocal";
1428 0x0e => User, "User";
1429 0x11 => None_, "None";
1430 0x15 => Grand, "Grand";
1431 0x16 => Upright, "Upright";
1432 0x17 => EPiano1, "EPiano1";
1433 0x18 => EPiano2, "EPiano2";
1434 0x1b => Clavinet, "Clavinet";
1435 0x1c => Harpsi, "Harpsi";
1436 0x1e => Arpeggio, "Arpeggio";
1437 0xff => Undefined, "Undefined";
1438 }
1439);
1440
1441impl ProgramCategory {
1442 pub fn of(header: &crate::cbin::Header) -> Option<ProgramCategory> {
1448 let id = u8::try_from(header.category()?).ok()?;
1449 match Self::from_bits(id as u64) {
1450 Ok(category) => Some(category),
1451 Err(never) => match never {},
1452 }
1453 }
1454}
1455
1456sparse_enum!(
1457 Effect1Type, 3, {
1459 0 => APan, "A-Pan";
1460 1 => Trem, "Trem";
1461 2 => Rm, "RM";
1462 3 => WaWa, "WA-WA";
1463 4 => AWa1, "A-WA1";
1464 5 => AWa2, "A-WA2";
1465 }
1466);
1467
1468sparse_enum!(
1469 Effect2Type, 3, {
1471 0 => Phas1, "PHAS1";
1472 1 => Phas2, "PHAS2";
1473 2 => Flang, "FLANG";
1474 3 => Vibe, "VIBE";
1475 4 => Chor1, "CHOR1";
1476 5 => Chor2, "CHOR2";
1477 }
1478);
1479
1480sparse_enum!(
1481 ReverbType, 3, {
1483 0 => Room1, "Room 1";
1484 1 => Room2, "Room 2";
1485 2 => Stage1, "Stage 1";
1486 3 => Stage2, "Stage 2";
1487 4 => Hall1, "Hall 1";
1488 5 => Hall2, "Hall 2";
1489 }
1490);
1491
1492#[cfg(test)]
1493mod tests {
1494 use super::*;
1495 use crate::fields::{ControlKind, Library, PackedOrder, Unit};
1496
1497 #[test]
1500 fn a_type_says_what_kind_of_control_it_is() {
1501 assert_eq!(<Level as Packed>::CONTROL, ControlKind::Knob(Unit::Panel10));
1502 assert_eq!(
1503 <Time as Packed>::CONTROL,
1504 ControlKind::Knob(Unit::Milliseconds)
1505 );
1506 assert_eq!(
1507 <EqBand as Packed>::CONTROL,
1508 ControlKind::Bipolar(Unit::Decibels)
1509 );
1510 assert_eq!(
1515 <MorphTarget as Packed>::CONTROL,
1516 ControlKind::Morph { of: None }
1517 );
1518 assert_eq!(
1519 <Drawbar as Packed>::CONTROL,
1520 ControlKind::Drawbar {
1521 bars: 1,
1522 rank: None,
1523 bits_per_bar: 4,
1524 order: PackedOrder::HighFirst,
1525 }
1526 );
1527 assert_eq!(
1531 <ArpPattern as Packed>::CONTROL,
1532 ControlKind::Pattern {
1533 steps: 16,
1534 bits_per_step: 2,
1535 order: PackedOrder::LowFirst,
1536 }
1537 );
1538 assert_eq!(
1539 <PianoRef as Packed>::CONTROL,
1540 ControlKind::Reference(Library::Piano)
1541 );
1542 assert_eq!(
1543 <SampleRef as Packed>::CONTROL,
1544 ControlKind::Reference(Library::Sample)
1545 );
1546 assert_eq!(<KbZone4 as Packed>::CONTROL, ControlKind::Selector);
1547 assert_eq!(<bool as Packed>::CONTROL, ControlKind::Toggle);
1548 assert_eq!(
1549 <OctaveShiftNibble as Packed>::CONTROL,
1550 ControlKind::Shift(Unit::Octaves)
1551 );
1552 assert_eq!(<u8 as Packed>::CONTROL, ControlKind::Number);
1554 }
1555
1556 #[test]
1559 fn a_unit_says_whether_it_can_be_computed() {
1560 assert!(Unit::Panel10.describes_a_known_transform());
1561 assert!(Unit::Decibels.describes_a_known_transform());
1562 assert!(!Unit::Milliseconds.describes_a_known_transform());
1563 assert!(!Unit::Hertz.describes_a_known_transform());
1564 assert_eq!(Time::new(96).unwrap().to_string(), "96");
1566 assert_eq!(Level::new(96).unwrap().to_string(), "96 (7.6)");
1567 }
1568
1569 #[test]
1571 fn the_stage4_octave_shift_wraps_where_the_others_bias() {
1572 let read = |bits| OctaveShiftNibble::from_bits(bits).unwrap().octaves();
1573 assert_eq!(read(0), 0);
1574 assert_eq!(read(1), 1);
1575 assert_eq!(read(2), 2);
1576 assert_eq!(read(15), -1);
1577 assert_eq!(read(14), -2);
1578 for bits in 0..16u64 {
1580 assert_eq!(OctaveShiftNibble::from_bits(bits).unwrap().to_bits(), bits);
1581 }
1582 }
1583
1584 #[test]
1586 fn a_morph_slot_names_its_neutral_and_keeps_the_rest() {
1587 assert_eq!(MorphTarget::NEUTRAL, 127);
1588 let neutral = MorphTarget::from_bits(127).unwrap();
1589 assert!(neutral.is_neutral());
1590 assert_eq!(neutral.to_string(), "—");
1591 assert_eq!(format!("{neutral:?}"), "127");
1592
1593 let moved = MorphTarget::from_bits(254).unwrap();
1594 assert!(!moved.is_neutral());
1595 assert_eq!(moved.to_string(), "254");
1596 for bits in 0..256u64 {
1598 assert_eq!(MorphTarget::from_bits(bits).unwrap().to_bits(), bits);
1599 }
1600 }
1601
1602 #[test]
1604 fn an_arp_pattern_reads_as_steps() {
1605 let accent = ArpPattern::from_bits(0x0101_0101).unwrap();
1607 assert_eq!(
1608 accent.steps(),
1609 [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]
1610 );
1611 assert_eq!(accent.to_string(), "1... 1... 1... 1...");
1612
1613 let pan = ArpPattern::from_bits(0x55aa_5500).unwrap();
1615 assert_eq!(&pan.steps()[4..12], &[1, 1, 1, 1, 2, 2, 2, 2]);
1616
1617 assert!(ArpPattern::default().is_empty());
1618 assert_eq!(format!("{pan:?}"), "0x55aa5500");
1620 }
1621
1622 #[test]
1624 fn a_bipolar_band_reads_signed() {
1625 assert_eq!(EqBand::new(64).unwrap().reading(), 0.0);
1626 assert_eq!(EqBand::new(0).unwrap().to_string(), "0 (-15.0)");
1627 assert_eq!(EqBand::new(127).unwrap().to_string(), "127 (+15.0)");
1628 assert_eq!(format!("{:?}", EqBand::new(96).unwrap()), "96");
1630 }
1631
1632 #[test]
1635 fn a_bipolar_slot_carries_the_unit_it_was_declared_with() {
1636 assert_eq!(
1637 <EqBand as Packed>::CONTROL,
1638 ControlKind::Bipolar(Unit::Decibels)
1639 );
1640 assert_eq!(
1641 <Bipolar<10> as Packed>::CONTROL,
1642 ControlKind::Bipolar(Unit::None)
1643 );
1644 assert_eq!(Bipolar::<10>::new(127).unwrap().reading(), 10.0);
1646 }
1647
1648 #[test]
1651 fn a_unit_survives_the_code_that_carries_it() {
1652 for unit in [
1653 Unit::Panel10,
1654 Unit::Decibels,
1655 Unit::Milliseconds,
1656 Unit::Hertz,
1657 Unit::Bpm,
1658 Unit::ClockDivision,
1659 Unit::Semitones,
1660 Unit::Octaves,
1661 Unit::Pan,
1662 Unit::None,
1663 ] {
1664 assert_eq!(Unit::expect_code(unit.code()), unit, "{unit:?}");
1665 }
1666 }
1667
1668 #[test]
1671 fn a_switch_names_both_of_its_states() {
1672 let normal = DelayCharacter::from_bits(0).unwrap();
1673 let analog = DelayCharacter::from_bits(1).unwrap();
1674 assert_eq!(format!("{normal:?}"), "Normal");
1675 assert_eq!(analog.to_string(), "analog");
1676 assert_eq!(analog.to_bits(), 1);
1677 assert!(analog.is_set());
1678 assert_eq!(<DelayCharacter as Packed>::MAX_BITS, 1);
1679 }
1680
1681 #[test]
1684 fn a_drawbar_keeps_a_nibble_past_its_travel() {
1685 assert_eq!(Drawbar::from_bits(8).unwrap().position(), Some(8));
1686 assert_eq!(Drawbar::from_bits(9).unwrap().position(), None);
1687 assert_eq!(Drawbar::from_bits(9).unwrap().raw(), 9);
1688 for bits in 0..16u64 {
1689 assert_eq!(Drawbar::from_bits(bits).unwrap().to_bits(), bits);
1690 }
1691 }
1692
1693 #[test]
1694 fn a_level_carries_the_panel_transform() {
1695 assert_eq!(Level::new(0).unwrap().to_string(), "0 (0.0)");
1696 assert_eq!(Level::new(127).unwrap().to_string(), "127 (10.0)");
1697 assert_eq!(Level::new(96).unwrap().to_string(), "96 (7.6)");
1698 assert!(Level::new(128).is_err(), "128 does not fit seven bits");
1699 }
1700}