1pub mod writer;
4
5#[derive(Clone, Debug, PartialEq)]
6pub struct TuneBook {
7 pub header: Option<FileHeader>,
8 pub tunes: Vec<Tune>,
9}
10impl TuneBook {
11 pub fn new(header: Option<FileHeader>, tunes: Vec<Tune>) -> TuneBook {
12 TuneBook { header, tunes }
13 }
14}
15
16#[derive(Clone, Debug, Eq, PartialEq)]
17pub struct FileHeader {
18 pub info: Vec<InfoField>,
19}
20impl FileHeader {
21 pub fn new(info: Vec<InfoField>) -> FileHeader {
22 FileHeader { info }
23 }
24}
25
26#[derive(Clone, Debug, PartialEq)]
27pub struct Tune {
28 pub header: TuneHeader,
29 pub body: Option<TuneBody>,
30}
31impl Tune {
32 pub fn new(header: TuneHeader, body: Option<TuneBody>) -> Tune {
33 Tune { header, body }
34 }
35}
36
37#[derive(Clone, Debug, Eq, PartialEq)]
38pub struct TuneHeader {
39 pub info: Vec<InfoField>,
40}
41impl TuneHeader {
42 pub fn new(info: Vec<InfoField>) -> TuneHeader {
43 TuneHeader { info }
44 }
45}
46
47#[derive(Clone, Debug, Eq, PartialEq)]
48pub struct InfoField(pub char, pub String);
49impl InfoField {
50 pub fn new(c: char, s: String) -> InfoField {
51 InfoField(c, s)
52 }
53}
54
55#[derive(Clone, Debug, PartialEq)]
56pub struct TuneBody {
57 pub music: Vec<MusicLine>,
58}
59impl TuneBody {
60 pub fn new(music: Vec<MusicLine>) -> TuneBody {
61 TuneBody { music }
62 }
63}
64
65#[derive(Clone, Debug, PartialEq)]
66pub struct MusicLine {
67 pub symbols: Vec<MusicSymbol>,
68}
69impl MusicLine {
70 pub fn new(symbols: Vec<MusicSymbol>) -> MusicLine {
71 MusicLine { symbols }
72 }
73}
74
75#[derive(Clone, Debug, PartialEq)]
76pub enum MusicSymbol {
77 Note {
78 decorations: Vec<Decoration>,
79 accidental: Option<Accidental>,
80 note: Note,
81 octave: i8,
82 length: f32,
83 tie: Option<Tie>,
84 },
85 Chord {
86 decorations: Vec<Decoration>,
87 notes: Vec<MusicSymbol>,
88 length: f32,
89 },
90 GraceNotes {
91 acciaccatura: Option<()>,
92 notes: Vec<MusicSymbol>,
93 },
94 Tuplet {
97 p: u32,
98 q: u32,
99 r: u32,
100 notes: Vec<MusicSymbol>,
101 },
102 Bar(String),
103 Rest(Rest),
104 Ending(u32),
105 VisualBreak,
106}
107
108#[derive(Copy, Clone, Debug, Eq, PartialEq)]
110pub enum Tie {
111 Solid,
113 Dotted,
115}
116
117static TUPLET_Q: [u32; 8] = [3, 2, 3, 0, 2, 0, 3, 0];
118impl MusicSymbol {
119 pub fn new_note(
120 decorations: Vec<Decoration>,
121 accidental: Option<Accidental>,
122 note: Note,
123 octave: i8,
124 length: f32,
125 tie: Option<Tie>,
126 ) -> MusicSymbol {
127 MusicSymbol::Note {
128 decorations,
129 accidental,
130 note,
131 octave,
132 length,
133 tie,
134 }
135 }
136
137 pub fn note(note: Note) -> MusicSymbol {
138 MusicSymbol::Note {
139 decorations: vec![],
140 accidental: None,
141 note,
142 octave: 1,
143 length: 1.0,
144 tie: None,
145 }
146 }
147
148 pub fn note_from_length(note: Note, length: f32) -> MusicSymbol {
149 MusicSymbol::Note {
150 decorations: vec![],
151 accidental: None,
152 note,
153 octave: 1,
154 length,
155 tie: None,
156 }
157 }
158
159 pub fn tuplet_with_defaults(
162 p: u32,
163 q: Option<u32>,
164 r: Option<u32>,
165 notes: Vec<MusicSymbol>,
166 ) -> Result<MusicSymbol, &'static str> {
167 assert_eq!(notes.len(), p as usize);
168
169 Self::new_tuplet(
170 p,
171 q.unwrap_or(TUPLET_Q[(p - 2) as usize]),
172 r.unwrap_or(p),
173 notes,
174 )
175 }
176
177 pub fn new_tuplet(
178 p: u32,
179 q: u32,
180 r: u32,
181 notes: Vec<MusicSymbol>,
182 ) -> Result<MusicSymbol, &'static str> {
183 if p < 2 {
184 return Err("Tuplet too small");
185 }
186 if p > 9 {
187 return Err("Tuplet too large");
188 }
189 if r == 0 {
190 return Err("R can't be 0");
191 }
192
193 Ok(MusicSymbol::Tuplet { p, q, r, notes })
194 }
195}
196
197#[derive(Copy, Clone, Debug, Eq, PartialEq)]
198pub enum Note {
199 C,
200 D,
201 E,
202 F,
203 G,
204 A,
205 B,
206}
207
208impl From<Note> for char {
209 fn from(note: Note) -> Self {
210 match note {
211 Note::C => 'C',
212 Note::D => 'D',
213 Note::E => 'E',
214 Note::F => 'F',
215 Note::G => 'G',
216 Note::A => 'A',
217 Note::B => 'B',
218 }
219 }
220}
221
222#[derive(Clone, Debug, Eq, PartialEq)]
223pub enum Decoration {
224 Staccato,
225 Roll,
226 Fermata,
227 Accent,
228 LowerMordent,
229 Coda,
230 UpperMordent,
231 Segno,
232 Trill,
233 UpBow,
234 DownBow,
235 Unresolved(String),
236}
237
238#[derive(Copy, Clone, Debug, Eq, PartialEq)]
239pub enum Accidental {
240 Natural,
241 Sharp,
242 Flat,
243 DoubleSharp,
244 DoubleFlat,
245}
246
247#[derive(Copy, Clone, Debug, Eq, PartialEq)]
248pub enum Rest {
249 Note(u32),
250 Measure(u32),
251 NoteHidden(u32),
252 MeasureHidden(u32),
253}