rstmt_core/pitch/
kinds.rs1use super::{PitchClass, PitchTy};
6
7pitch_class! {
8 #[default(C)]
9 pub enum Natural {
10 C = 0,
11 D = 2,
12 E = 4,
13 F = 5,
14 G = 7,
15 A = 9,
16 B = 11,
17 }
18}
19
20pitch_class! {
21 #[default(C)]
22 pub enum Sharp {
23 C = 1,
24 D = 3,
25 F = 6,
26 G = 8,
27 A = 10,
28 }
29}
30
31pitch_class! {
32 #[default(D)]
33 pub enum Flat {
34 D = 1,
35 E = 3,
36 G = 6,
37 A = 8,
38 B = 10,
39 }
40}
41
42#[derive(
43 Clone,
44 Copy,
45 Eq,
46 Hash,
47 Ord,
48 PartialEq,
49 PartialOrd,
50 smart_default::SmartDefault,
51 strum::AsRefStr,
52 strum::EnumCount,
53 strum::EnumIs,
54 strum::VariantNames,
55)]
56#[cfg_attr(
57 feature = "serde",
58 derive(serde::Deserialize, serde::Serialize),
59 serde(rename_all = "lowercase")
60)]
61#[repr(i8)]
62#[strum(serialize_all = "lowercase")]
63pub enum Pitches {
64 Flat(Flat),
65 #[default]
66 Natural(Natural),
67 Sharp(Sharp),
68}
69
70impl Pitches {
71 pub fn try_from_value(value: PitchTy) -> Result<Self, crate::Error> {
72 if let Ok(n) = Natural::try_from_value(value) {
73 Ok(n.as_class())
74 } else if let Ok(s) = Sharp::try_from_value(value) {
75 Ok(s.as_class())
76 } else if let Ok(f) = Flat::try_from_value(value) {
77 Ok(f.as_class())
78 } else {
79 Err(crate::Error::music_error("Invalid pitch value."))
80 }
81 }
82
83 pub fn value(&self) -> PitchTy {
84 match self {
85 Pitches::Flat(f) => f.pitch(),
86 Pitches::Natural(n) => n.pitch(),
87 Pitches::Sharp(s) => s.pitch(),
88 }
89 }
90}
91
92impl core::fmt::Debug for Pitches {
93 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
94 use Pitches::*;
95 match self {
96 Flat(cls) => write!(f, "{}♭", cls.as_ref()),
97 Natural(cls) => write!(f, "{}", cls.as_ref()),
98 Sharp(cls) => write!(f, "{}#", cls.as_ref()),
99 }
100 }
101}
102
103impl core::fmt::Display for Pitches {
104 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
105 use Pitches::*;
106 match self {
107 Flat(cls) => write!(f, "{}♭", cls.as_ref()),
108 Natural(cls) => write!(f, "{}", cls.as_ref()),
109 Sharp(cls) => write!(f, "{}#", cls.as_ref()),
110 }
111 }
112}
113
114impl PitchClass for Pitches {
115 seal!();
116
117 fn pitch(&self) -> PitchTy {
118 self.value()
119 }
120}
121
122impl From<Pitches> for PitchTy {
123 fn from(pitch: Pitches) -> PitchTy {
124 pitch.value()
125 }
126}
127
128impl From<PitchTy> for Pitches {
129 fn from(value: PitchTy) -> Pitches {
130 Self::try_from_value(value).unwrap_or_default()
131 }
132}