1use serde::{Deserialize, Serialize};
2use std::fmt::Display;
3
4use crate::prelude::{PitchName, PitchSign, Semitones};
5
6#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Debug)]
8pub enum Syllable {
9 Do,
11 Di, Ra, Re,
14 Ri, Me, Mi,
17 Fa,
18 Fi, Se, So,
21 Si, Le, La,
24 Li, Te, Ti,
27}
28
29impl Display for Syllable {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 write!(f, "{}", self.to_text())
32 }
33}
34
35impl Default for Syllable {
36 fn default() -> Self {
37 Self::Do
38 }
39}
40
41impl Syllable {
42 pub fn to_text(&self) -> String {
43 match self {
44 Syllable::Do => "1",
46 Syllable::Re => "2",
47 Syllable::Mi => "3",
48 Syllable::Fa => "4",
49 Syllable::So => "5",
50 Syllable::La => "6",
51 Syllable::Ti => "7",
52 Syllable::Di => "1#",
54 Syllable::Ri => "2#",
55 Syllable::Fi => "4#",
56 Syllable::Si => "5#",
57 Syllable::Li => "6#",
58 Syllable::Ra => "2b",
60 Syllable::Me => "3b",
61 Syllable::Se => "5b",
62 Syllable::Le => "6b",
63 Syllable::Te => "7b",
64 }
65 .to_owned()
66 }
67 pub fn from_text(text: &str) -> Self {
68 match text {
69 "1" => Syllable::Do,
71 "2" => Syllable::Re,
72 "3" => Syllable::Mi,
73 "4" => Syllable::Fa,
74 "5" => Syllable::So,
75 "6" => Syllable::La,
76 "7" => Syllable::Ti,
77 "1#" => Syllable::Di,
79 "2#" => Syllable::Ri,
80 "4#" => Syllable::Fi,
81 "5#" => Syllable::Si,
82 "6#" => Syllable::Li,
83 "2b" => Syllable::Ra,
85 "3b" => Syllable::Me,
86 "5b" => Syllable::Se,
87 "6b" => Syllable::Le,
88 "7b" => Syllable::Te,
89 _ => Syllable::Do,
90 }
91 }
92}
93
94impl Syllable {
95 pub fn to_ident(&self) -> String {
96 format!("{:?}", self)
97 }
98 pub fn from_ident(ident: &str) -> Self {
99 match ident {
100 "Do" => Syllable::Do,
102 "Re" => Syllable::Re,
103 "Mi" => Syllable::Mi,
104 "Fa" => Syllable::Fa,
105 "So" => Syllable::So,
106 "La" => Syllable::La,
107 "Ti" => Syllable::Ti,
108 "Di" => Syllable::Di,
110 "Ri" => Syllable::Ri,
111 "Fi" => Syllable::Fi,
112 "Si" => Syllable::Si,
113 "Li" => Syllable::Li,
114 "Ra" => Syllable::Ra,
116 "Me" => Syllable::Me,
117 "Se" => Syllable::Se,
118 "Le" => Syllable::Le,
119 "Te" => Syllable::Te,
120 _ => Syllable::Do,
121 }
122 }
123}
124
125impl From<Syllable> for Semitones {
126 fn from(v: Syllable) -> Self {
127 match v {
128 Syllable::Do => 0,
130 Syllable::Re => 2,
131 Syllable::Mi => 4,
132 Syllable::Fa => 5,
133 Syllable::So => 7,
134 Syllable::La => 9,
135 Syllable::Ti => 11,
136 Syllable::Di => 1,
138 Syllable::Ri => 3,
139 Syllable::Fi => 6,
140 Syllable::Si => 8,
141 Syllable::Li => 10,
142 Syllable::Ra => 1,
144 Syllable::Me => 3,
145 Syllable::Se => 6,
146 Syllable::Le => 8,
147 Syllable::Te => 10,
148 }
149 .into()
150 }
151}
152
153impl From<Semitones> for Syllable {
154 fn from(v: Semitones) -> Self {
155 let pos_val = if v.0 >= 0 { v.0 % 12 } else { v.0 % 12 + 12 };
156 match pos_val {
157 0 => Syllable::Do,
158 1 => Syllable::Di,
159 2 => Syllable::Re,
160 3 => Syllable::Ri,
161 4 => Syllable::Mi,
162 5 => Syllable::Fa,
163 6 => Syllable::Fi,
164 7 => Syllable::So,
165 8 => Syllable::Si,
166 9 => Syllable::La,
167 10 => Syllable::Li,
168 11 => Syllable::Ti,
169 _ => Syllable::Do,
170 }
171 }
172}
173
174impl From<(PitchSign, PitchName)> for Syllable {
175 fn from(v: (PitchSign, PitchName)) -> Self {
176 match v.0 {
177 PitchSign::DoubleFlat => match v.1 {
178 PitchName::C => Self::Te,
179 PitchName::D => Self::Do,
180 PitchName::E => Self::Re,
181 PitchName::F => Self::Me,
182 PitchName::G => Self::Fa,
183 PitchName::A => Self::So,
184 PitchName::B => Self::La,
185 },
186 PitchSign::Flat => match v.1 {
187 PitchName::C => Self::Ti,
188 PitchName::D => Self::Ra,
189 PitchName::E => Self::Me,
190 PitchName::F => Self::Mi,
191 PitchName::G => Self::Se,
192 PitchName::A => Self::Le,
193 PitchName::B => Self::Te,
194 },
195 PitchSign::Natural => match v.1 {
196 PitchName::C => Self::Do,
197 PitchName::D => Self::Re,
198 PitchName::E => Self::Mi,
199 PitchName::F => Self::Fa,
200 PitchName::G => Self::So,
201 PitchName::A => Self::La,
202 PitchName::B => Self::Ti,
203 },
204 PitchSign::Sharp => match v.1 {
205 PitchName::C => Self::Di,
206 PitchName::D => Self::Ri,
207 PitchName::E => Self::Fa,
208 PitchName::F => Self::Fi,
209 PitchName::G => Self::Si,
210 PitchName::A => Self::Li,
211 PitchName::B => Self::Do,
212 },
213 PitchSign::DoubleSharp => match v.1 {
214 PitchName::C => Self::Re,
215 PitchName::D => Self::Mi,
216 PitchName::E => Self::Fi,
217 PitchName::F => Self::So,
218 PitchName::G => Self::La,
219 PitchName::A => Self::Ti,
220 PitchName::B => Self::Di,
221 },
222 }
223 }
224}