rstmt_core/pitch/types/
pitch_class.rs1pub trait PitchClass:
7 'static + Send + Sized + Sync + core::fmt::Debug + core::fmt::Display
8{
9 private!();
10
11 fn new() -> Self;
12
13 fn index(&self) -> usize;
14}
15macro_rules! class_enum {
19 {
20 $(#[doc $($doc:tt)*])?
21 $vis:vis enum $name:ident {$($rest:tt)*}
22 } => {
23 $(#[doc $($doc)*])?
24 #[derive(
25 Clone,
26 Copy,
27 Debug,
28 Default,
29 Eq,
30 Hash,
31 Ord,
32 PartialEq,
33 PartialOrd,
34 scsys::VariantConstructors,
35 strum::AsRefStr,
36 strum::Display,
37 strum::EnumCount,
38 strum::EnumIs,
39 strum::EnumIter,
40 strum::EnumString,
41 strum::VariantArray,
42 strum::VariantNames,
43 )]
44 #[cfg_attr(
45 feature = "serde",
46 derive(serde::Deserialize, serde::Serialize),
47 serde(rename_all = "UPPERCASE")
48 )]
49 #[strum(serialize_all = "UPPERCASE")]
50 $vis enum $name {$($rest)*}
51 };
52}
53
54macro_rules! pitch_class {
55 {
56 $($(#[doc $($doc:tt)*])?
57 $vis:vis $i:ident $name:ident = $c:literal);* $(;)?
58 } => {
59 $(
60 pitch_class! {
61 @impl
62 $(#[doc $($doc)*])?
63 $vis $i $name
64 }
65 pitch_class!(@ext $name = $c);
66 )*
67 };
68 {
69 @impl
70 $(#[doc $($doc:tt)*])?
71 $vis:vis struct $name:ident
72 } => {
73 $(#[doc $($doc)*])?
74 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
75 #[cfg_attr(
76 feature = "serde",
77 derive(serde::Deserialize, serde::Serialize),
78 )]
79 $vis struct $name;
80 };
81 (@ext $name:ident = $c:literal) => {
82 impl $name {
83 pub const C_MAJOR_ID: usize = $c;
84 pub const fn new() -> Self {
86 Self
87 }
88 pub const fn value(&self) -> usize {
90 Self::C_MAJOR_ID
91 }
92 }
93
94 impl ::core::fmt::Display for $name {
95 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
96 write!(f, "{}", core::any::type_name::<Self>())
97 }
98 }
99
100 impl $crate::pitch::PitchClass for $name {
101 seal!();
102
103 fn new() -> Self {
104 Self::new()
105 }
106
107 fn index(&self) -> usize {
108 self.value()
109 }
110 }
111
112 impl PartialEq<usize> for $name {
113 fn eq(&self, other: &usize) -> bool {
114 self.value() == *other
115 }
116 }
117
118 impl PartialEq<$name> for usize {
119 fn eq(&self, other: &$name) -> bool {
120 *self == other.value()
121 }
122 }
123
124 impl PartialOrd<usize> for $name {
125 fn partial_cmp(&self, other: &usize) -> Option<core::cmp::Ordering> {
126 Some(self.value().cmp(other))
127 }
128 }
129
130 impl PartialOrd<$name> for usize {
131 fn partial_cmp(&self, other: &$name) -> Option<core::cmp::Ordering> {
132 Some(self.cmp(&other.value()))
133 }
134 }
135 };
136}
137
138class_enum! {
139 #[doc = "A representation of the natural pitch class"]
140 pub enum Natural {
141 #[default]
142 C = 0,
143 D = 2,
144 E = 4,
145 F = 5,
146 G = 7,
147 A = 9,
148 B = 11,
149 }
150}
151
152class_enum! {
153 #[doc = "A representation of the sharp pitch class"]
154 pub enum Sharp {
155 #[default]
156 C = 1,
157 D = 3,
158 F = 6,
159 G = 8,
160 A = 10,
161 }
162}
163
164class_enum! {
165 #[doc = "A representation of the flat pitch class"]
166 pub enum Flat {
167 #[default]
168 D = 1,
169 E = 3,
170 G = 6,
171 A = 8,
172 B = 10,
173 }
174}
175
176pitch_class! {
177 #[doc = "A representation of the C pitch class"]
178 pub struct C = 0;
179 #[doc = "A representation of the D pitch class"]
180 pub struct D = 2;
181 #[doc = "A representation of the E pitch class"]
182 pub struct E = 4;
183 #[doc = "A representation of the F pitch class"]
184 pub struct F = 5;
185 #[doc = "A representation of the G pitch class"]
186 pub struct G = 7;
187 #[doc = "A representation of the A pitch class"]
188 pub struct A = 9;
189 #[doc = "A representation of the B pitch class"]
190 pub struct B = 11;
191
192 pub struct CSharp = 1;
193 pub struct DSharp = 3;
194 pub struct FSharp = 6;
195 pub struct GSharp = 8;
196 pub struct ASharp = 10;
197 pub struct DFlat = 1;
198 pub struct EFlat = 3;
199 pub struct GFlat = 6;
200 pub struct AFlat = 8;
201 pub struct BFlat = 10;
202
203}