notation_core/
syllable.rs

1use serde::{Deserialize, Serialize};
2use std::fmt::Display;
3
4use crate::prelude::{PitchName, PitchSign, Semitones};
5
6// https://en.wikipedia.org/wiki/Solf%C3%A8ge
7#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Debug)]
8pub enum Syllable {
9    //Natural
10    Do,
11    Di, //Sharp
12    Ra, //Flat
13    Re,
14    Ri, //Sharp
15    Me, //Flat
16    Mi,
17    Fa,
18    Fi, //Sharp
19    Se, //Flat
20    So,
21    Si, //Sharp
22    Le, //Flat
23    La,
24    Li, //Sharp
25    Te, //Flat
26    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            //Natural
45            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            //Sharp
53            Syllable::Di => "1#",
54            Syllable::Ri => "2#",
55            Syllable::Fi => "4#",
56            Syllable::Si => "5#",
57            Syllable::Li => "6#",
58            //Flat
59            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            //Natural
70            "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            //Sharp
78            "1#" => Syllable::Di,
79            "2#" => Syllable::Ri,
80            "4#" => Syllable::Fi,
81            "5#" => Syllable::Si,
82            "6#" => Syllable::Li,
83            //Flat
84            "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            //Natural
101            "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            //Sharp
109            "Di" => Syllable::Di,
110            "Ri" => Syllable::Ri,
111            "Fi" => Syllable::Fi,
112            "Si" => Syllable::Si,
113            "Li" => Syllable::Li,
114            //Flat
115            "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            //Natural
129            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            //Sharp
137            Syllable::Di => 1,
138            Syllable::Ri => 3,
139            Syllable::Fi => 6,
140            Syllable::Si => 8,
141            Syllable::Li => 10,
142            //Flat
143            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}