1use crate::{Key, Note, PitchClass, PitchClassCollection};
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6#[cfg(feature = "redact-composer")]
7use redact_composer_core::derive::Element;
8
9#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12#[cfg_attr(feature = "redact-composer", derive(Element))]
13#[allow(missing_docs)]
14pub enum NoteName {
15 Abb,
16 Ab,
17 A,
18 As,
19 Ass,
20 Bbb,
21 Bb,
22 B,
23 Bs,
24 Bss,
25 Cbb,
26 Cb,
27 C,
28 Cs,
29 Css,
30 Dbb,
31 Db,
32 D,
33 Ds,
34 Dss,
35 Ebb,
36 Eb,
37 E,
38 Es,
39 Ess,
40 Fbb,
41 Fb,
42 F,
43 Fs,
44 Fss,
45 Gbb,
46 Gb,
47 G,
48 Gs,
49 Gss,
50}
51
52impl NoteName {
53 pub fn in_octave(&self, octave: i8) -> Note {
59 (*self, octave).into()
60 }
61}
62
63impl From<NoteName> for u8 {
64 fn from(note: NoteName) -> Self {
65 use NoteName::*;
66 match note {
67 C | Bs | Dbb => 0,
68 Cs | Db | Bss => 1,
69 D | Css | Ebb => 2,
70 Ds | Eb | Fbb => 3,
71 E | Fb | Dss => 4,
72 F | Es | Gbb => 5,
73 Fs | Gb | Ess => 6,
74 G | Fss | Abb => 7,
75 Gs | Ab => 8,
76 A | Gss | Bbb => 9,
77 As | Bb | Cbb => 10,
78 B | Cb | Ass => 11,
79 }
80 }
81}
82
83impl PartialEq<PitchClass> for NoteName {
84 fn eq(&self, pitch_class: &PitchClass) -> bool {
89 PitchClass::from(*self) == *pitch_class
90 }
91}
92
93#[allow(dead_code)]
94impl NoteName {
95 pub(crate) fn letter(&self) -> NoteName {
97 use NoteName::*;
98 match self {
99 Abb | Ab | A | As | Ass => A,
100 Bbb | Bb | B | Bs | Bss => B,
101 Cbb | Cb | C | Cs | Css => C,
102 Dbb | Db | D | Ds | Dss => D,
103 Ebb | Eb | E | Es | Ess => E,
104 Fbb | Fb | F | Fs | Fss => F,
105 Gbb | Gb | G | Gs | Gss => G,
106 }
107 }
108
109 pub(crate) fn next_letter(&self) -> NoteName {
110 use NoteName::*;
111 match self.letter() {
112 A => B,
113 B => C,
114 C => D,
115 D => E,
116 E => F,
117 F => G,
118 G => A,
119 _ => unreachable!(),
120 }
121 }
122
123 pub(crate) fn prev_letter(&self) -> NoteName {
124 use NoteName::*;
125 match self.letter() {
126 A => G,
127 B => A,
128 C => B,
129 D => C,
130 E => D,
131 F => E,
132 G => F,
133 _ => unreachable!(),
134 }
135 }
136
137 pub(crate) fn has_sharp(&self) -> bool {
138 use NoteName::*;
139 matches!(
140 self,
141 As | Bs | Cs | Ds | Es | Fs | Gs | Ass | Bss | Css | Dss | Ess | Fss | Gss
142 )
143 }
144
145 pub(crate) fn has_flat(&self) -> bool {
146 use NoteName::*;
147 matches!(
148 self,
149 Ab | Bb | Cb | Db | Eb | Fb | Gb | Abb | Bbb | Cbb | Dbb | Ebb | Fbb | Gbb
150 )
151 }
152
153 pub(crate) fn has_double_sharp(&self) -> bool {
154 use NoteName::*;
155 matches!(self, Ass | Bss | Css | Dss | Ess | Fss | Gss)
156 }
157
158 pub(crate) fn has_double_flat(&self) -> bool {
159 use NoteName::*;
160 matches!(self, Abb | Bbb | Cbb | Dbb | Ebb | Fbb | Gbb)
161 }
162
163 pub(crate) fn complexity(&self) -> u8 {
164 use NoteName::*;
165 match self {
166 A | B | C | D | E | F | G => 0,
167 As | Bs | Cs | Ds | Es | Fs | Gs => 1,
168 Ab | Bb | Cb | Db | Eb | Fb | Gb => 1,
169 Ass | Bss | Css | Dss | Ess | Fss | Gss => 2,
170 Abb | Bbb | Cbb | Dbb | Ebb | Fbb | Gbb => 2,
171 }
172 }
173}
174
175impl PitchClass {
176 pub fn names(&self) -> Vec<NoteName> {
178 use NoteName::*;
179 match self.0 {
180 0 => vec![C, Bs, Dbb],
181 1 => vec![Cs, Db, Bss],
182 2 => vec![D, Css, Ebb],
183 3 => vec![Ds, Eb, Fbb],
184 4 => vec![E, Fb, Dss],
185 5 => vec![F, Es, Gbb],
186 6 => vec![Fs, Gb, Ess],
187 7 => vec![G, Fss, Abb],
188 8 => vec![Gs, Ab],
189 9 => vec![A, Gss, Bbb],
190 10 => vec![As, Bb, Cbb],
191 11 => vec![B, Cb, Ass],
192 _ => panic!(),
193 }
194 }
195
196 pub fn name_in_key(&self, key: &Key) -> NoteName {
200 let pitch_names = self.names();
201 let key_note_names = key.note_names();
202
203 let in_key_note = key_note_names
204 .iter()
205 .find(|n| &PitchClass::from(**n) == self);
206
207 if let Some(note) = in_key_note {
208 return *note;
209 }
210
211 let letter_matching_key_note = key_note_names
212 .iter()
213 .find(|n| &PitchClass::from(n.letter()) == self);
214
215 if let Some(key_note) = letter_matching_key_note {
216 return *key_note;
217 }
218
219 let naturalized_note = pitch_names.iter().find(|n| !n.has_sharp() && !n.has_flat());
220
221 if let Some(note) = naturalized_note {
222 return *note;
223 }
224
225 let key_sharps = key_note_names.iter().filter(|n| n.has_sharp()).count();
226 let key_flats = key_note_names.iter().filter(|n| n.has_flat()).count();
227
228 if key_sharps >= key_flats {
229 if let Some(note) = pitch_names.iter().find(|n| n.has_sharp()) {
230 *note
231 } else if let Some(note) = pitch_names.iter().find(|n| n.has_flat()) {
232 *note
233 } else {
234 pitch_names[0]
235 }
236 } else if let Some(note) = pitch_names.iter().find(|n| n.has_flat()) {
237 *note
238 } else if let Some(note) = pitch_names.iter().find(|n| n.has_sharp()) {
239 *note
240 } else {
241 pitch_names[0]
242 }
243 }
244}
245
246impl Key {
247 pub fn root_name(&self) -> NoteName {
249 match self.name_pref {
250 Some(n) => Self::simplify_root(n),
251 None => self
252 .root
253 .names()
254 .into_iter()
255 .min_by_key(NoteName::complexity)
256 .expect("Key should be nameable for any NoteName"),
257 }
258 }
259
260 pub(crate) fn simplify_root(name: NoteName) -> NoteName {
261 if name.complexity() > 1 {
262 PitchClass::from(name)
263 .names()
264 .into_iter()
265 .min_by_key(NoteName::complexity)
266 .unwrap()
267 } else {
268 name
269 }
270 }
271
272 pub fn note_names(&self) -> Vec<NoteName> {
279 let first = self.root_name();
280
281 let mut next_letter = first.next_letter();
282 let mut sharp_pref: Option<bool> = if first.has_sharp() || first.has_flat() {
283 Some(first.has_sharp())
284 } else {
285 None
286 };
287
288 let mut names = vec![first];
289 for pitch in self.pitch_classes().into_iter().skip(1) {
290 let name_options = pitch.names().into_iter().collect::<Vec<_>>();
292 let maybe_name = name_options
293 .iter()
294 .filter(|n| n.letter() == next_letter)
295 .filter(|n| {
296 if let Some(pref_sharp) = sharp_pref {
297 if pref_sharp {
298 n.has_sharp()
299 } else {
300 n.has_flat()
301 }
302 } else {
303 true
304 }
305 })
306 .min_by_key(|n| n.complexity())
307 .copied();
308
309 let name = if let Some(name) = maybe_name {
310 name
311 } else {
312 name_options
314 .iter()
315 .filter(|n| n.letter() == next_letter)
316 .min_by_key(|n| n.complexity())
317 .copied()
318 .expect("Bug: Every Key note name should have a following note name.")
319 };
320
321 names.push(name);
322
323 if sharp_pref.is_none() && (name.has_sharp() || name.has_flat()) {
324 sharp_pref = Some(name.has_sharp());
325 }
326
327 next_letter = name.next_letter();
328 }
329
330 names
331 }
332}
333
334#[cfg(test)]
335mod test {
336 mod scale_note_names {
337 use crate::{Key, NoteName::*, Scale::*};
338
339 #[test]
340 fn ab_scales() {
341 assert_eq!(
342 Key::from((Ab, Major)).note_names(),
343 [Ab, Bb, C, Db, Eb, F, G]
344 );
345 assert_eq!(
346 Key::from((Ab, NaturalMinor)).note_names(),
347 [Ab, Bb, Cb, Db, Eb, Fb, Gb]
348 );
349 assert_eq!(
350 Key::from((Ab, MelodicMinor)).note_names(),
351 [Ab, Bb, Cb, Db, Eb, F, G]
352 );
353 assert_eq!(
354 Key::from((Ab, HarmonicMinor)).note_names(),
355 [Ab, Bb, Cb, Db, Eb, Fb, G]
356 );
357 }
358
359 #[test]
360 fn a_scales() {
361 assert_eq!(Key::from((A, Major)).note_names(), [A, B, Cs, D, E, Fs, Gs]);
362 assert_eq!(
363 Key::from((A, NaturalMinor)).note_names(),
364 [A, B, C, D, E, F, G]
365 );
366 assert_eq!(
367 Key::from((A, MelodicMinor)).note_names(),
368 [A, B, C, D, E, Fs, Gs]
369 );
370 assert_eq!(
371 Key::from((A, HarmonicMinor)).note_names(),
372 [A, B, C, D, E, F, Gs]
373 );
374 }
375
376 #[test]
377 fn as_scales() {
378 assert_eq!(
379 Key::from((As, Major)).note_names(),
380 [As, Bs, Css, Ds, Es, Fss, Gss]
381 );
382 assert_eq!(
383 Key::from((As, NaturalMinor)).note_names(),
384 [As, Bs, Cs, Ds, Es, Fs, Gs]
385 );
386 assert_eq!(
387 Key::from((As, MelodicMinor)).note_names(),
388 [As, Bs, Cs, Ds, Es, Fss, Gss]
389 );
390 assert_eq!(
391 Key::from((As, HarmonicMinor)).note_names(),
392 [As, Bs, Cs, Ds, Es, Fs, Gss]
393 );
394 }
395
396 #[test]
397 fn bb_scales() {
398 assert_eq!(Key::from((Bb, Major)).note_names(), [Bb, C, D, Eb, F, G, A]);
399 assert_eq!(
400 Key::from((Bb, NaturalMinor)).note_names(),
401 [Bb, C, Db, Eb, F, Gb, Ab]
402 );
403 assert_eq!(
404 Key::from((Bb, MelodicMinor)).note_names(),
405 [Bb, C, Db, Eb, F, G, A]
406 );
407 assert_eq!(
408 Key::from((Bb, HarmonicMinor)).note_names(),
409 [Bb, C, Db, Eb, F, Gb, A]
410 );
411 }
412
413 #[test]
414 fn b_scales() {
415 assert_eq!(
416 Key::from((B, Major)).note_names(),
417 [B, Cs, Ds, E, Fs, Gs, As]
418 );
419 assert_eq!(
420 Key::from((B, NaturalMinor)).note_names(),
421 [B, Cs, D, E, Fs, G, A]
422 );
423 assert_eq!(
424 Key::from((B, MelodicMinor)).note_names(),
425 [B, Cs, D, E, Fs, Gs, As]
426 );
427 assert_eq!(
428 Key::from((B, HarmonicMinor)).note_names(),
429 [B, Cs, D, E, Fs, G, As]
430 );
431 }
432
433 #[test]
434 fn bs_scales() {
435 assert_eq!(
436 Key::from((Bs, Major)).note_names(),
437 [Bs, Css, Dss, Es, Fss, Gss, Ass]
438 );
439 assert_eq!(
440 Key::from((Bs, NaturalMinor)).note_names(),
441 [Bs, Css, Ds, Es, Fss, Gs, As]
442 );
443 assert_eq!(
444 Key::from((Bs, MelodicMinor)).note_names(),
445 [Bs, Css, Ds, Es, Fss, Gss, Ass]
446 );
447 assert_eq!(
448 Key::from((Bs, HarmonicMinor)).note_names(),
449 [Bs, Css, Ds, Es, Fss, Gs, Ass]
450 );
451 }
452
453 #[test]
454 fn cb_scales() {
455 assert_eq!(
456 Key::from((Cb, Major)).note_names(),
457 [Cb, Db, Eb, Fb, Gb, Ab, Bb]
458 );
459 assert_eq!(
460 Key::from((Cb, NaturalMinor)).note_names(),
461 [Cb, Db, Ebb, Fb, Gb, Abb, Bbb]
462 );
463 assert_eq!(
464 Key::from((Cb, MelodicMinor)).note_names(),
465 [Cb, Db, Ebb, Fb, Gb, Ab, Bb]
466 );
467 assert_eq!(
468 Key::from((Cb, HarmonicMinor)).note_names(),
469 [Cb, Db, Ebb, Fb, Gb, Abb, Bb]
470 );
471 }
472
473 #[test]
474 fn c_scales() {
475 assert_eq!(Key::from((C, Major)).note_names(), [C, D, E, F, G, A, B]);
476 assert_eq!(
477 Key::from((C, NaturalMinor)).note_names(),
478 [C, D, Eb, F, G, Ab, Bb]
479 );
480 assert_eq!(
481 Key::from((C, MelodicMinor)).note_names(),
482 [C, D, Eb, F, G, A, B]
483 );
484 assert_eq!(
485 Key::from((C, HarmonicMinor)).note_names(),
486 [C, D, Eb, F, G, Ab, B]
487 );
488 }
489
490 #[test]
491 fn cs_scales() {
492 assert_eq!(
493 Key::from((Cs, Major)).note_names(),
494 [Cs, Ds, Es, Fs, Gs, As, Bs]
495 );
496 assert_eq!(
497 Key::from((Cs, NaturalMinor)).note_names(),
498 [Cs, Ds, E, Fs, Gs, A, B]
499 );
500 assert_eq!(
501 Key::from((Cs, MelodicMinor)).note_names(),
502 [Cs, Ds, E, Fs, Gs, As, Bs]
503 );
504 assert_eq!(
505 Key::from((Cs, HarmonicMinor)).note_names(),
506 [Cs, Ds, E, Fs, Gs, A, Bs]
507 );
508 }
509
510 #[test]
511 fn db_scales() {
512 assert_eq!(
513 Key::from((Db, Major)).note_names(),
514 [Db, Eb, F, Gb, Ab, Bb, C]
515 );
516 assert_eq!(
517 Key::from((Db, NaturalMinor)).note_names(),
518 [Db, Eb, Fb, Gb, Ab, Bbb, Cb]
519 );
520 assert_eq!(
521 Key::from((Db, MelodicMinor)).note_names(),
522 [Db, Eb, Fb, Gb, Ab, Bb, C]
523 );
524 assert_eq!(
525 Key::from((Db, HarmonicMinor)).note_names(),
526 [Db, Eb, Fb, Gb, Ab, Bbb, C]
527 );
528 }
529
530 #[test]
531 fn d_scales() {
532 assert_eq!(Key::from((D, Major)).note_names(), [D, E, Fs, G, A, B, Cs]);
533 assert_eq!(
534 Key::from((D, NaturalMinor)).note_names(),
535 [D, E, F, G, A, Bb, C]
536 );
537 assert_eq!(
538 Key::from((D, MelodicMinor)).note_names(),
539 [D, E, F, G, A, B, Cs]
540 );
541 assert_eq!(
542 Key::from((D, HarmonicMinor)).note_names(),
543 [D, E, F, G, A, Bb, Cs]
544 );
545 }
546
547 #[test]
548 fn ds_scales() {
549 assert_eq!(
550 Key::from((Ds, Major)).note_names(),
551 [Ds, Es, Fss, Gs, As, Bs, Css]
552 );
553 assert_eq!(
554 Key::from((Ds, NaturalMinor)).note_names(),
555 [Ds, Es, Fs, Gs, As, B, Cs]
556 );
557 assert_eq!(
558 Key::from((Ds, MelodicMinor)).note_names(),
559 [Ds, Es, Fs, Gs, As, Bs, Css]
560 );
561 assert_eq!(
562 Key::from((Ds, HarmonicMinor)).note_names(),
563 [Ds, Es, Fs, Gs, As, B, Css]
564 );
565 }
566
567 #[test]
568 fn eb_scales() {
569 assert_eq!(
570 Key::from((Eb, Major)).note_names(),
571 [Eb, F, G, Ab, Bb, C, D]
572 );
573 assert_eq!(
574 Key::from((Eb, NaturalMinor)).note_names(),
575 [Eb, F, Gb, Ab, Bb, Cb, Db]
576 );
577 assert_eq!(
578 Key::from((Eb, MelodicMinor)).note_names(),
579 [Eb, F, Gb, Ab, Bb, C, D]
580 );
581 assert_eq!(
582 Key::from((Eb, HarmonicMinor)).note_names(),
583 [Eb, F, Gb, Ab, Bb, Cb, D]
584 );
585 }
586
587 #[test]
588 fn e_scales() {
589 assert_eq!(
590 Key::from((E, Major)).note_names(),
591 [E, Fs, Gs, A, B, Cs, Ds]
592 );
593 assert_eq!(
594 Key::from((E, NaturalMinor)).note_names(),
595 [E, Fs, G, A, B, C, D]
596 );
597 assert_eq!(
598 Key::from((E, MelodicMinor)).note_names(),
599 [E, Fs, G, A, B, Cs, Ds]
600 );
601 assert_eq!(
602 Key::from((E, HarmonicMinor)).note_names(),
603 [E, Fs, G, A, B, C, Ds]
604 );
605 }
606
607 #[test]
608 fn es_scales() {
609 assert_eq!(
610 Key::from((Es, Major)).note_names(),
611 [Es, Fss, Gss, As, Bs, Css, Dss]
612 );
613 assert_eq!(
614 Key::from((Es, NaturalMinor)).note_names(),
615 [Es, Fss, Gs, As, Bs, Cs, Ds]
616 );
617 assert_eq!(
618 Key::from((Es, MelodicMinor)).note_names(),
619 [Es, Fss, Gs, As, Bs, Css, Dss]
620 );
621 assert_eq!(
622 Key::from((Es, HarmonicMinor)).note_names(),
623 [Es, Fss, Gs, As, Bs, Cs, Dss]
624 );
625 }
626
627 #[test]
628 fn fb_scales() {
629 assert_eq!(
630 Key::from((Fb, Major)).note_names(),
631 [Fb, Gb, Ab, Bbb, Cb, Db, Eb]
632 );
633 assert_eq!(
634 Key::from((Fb, NaturalMinor)).note_names(),
635 [Fb, Gb, Abb, Bbb, Cb, Dbb, Ebb]
636 );
637 assert_eq!(
638 Key::from((Fb, MelodicMinor)).note_names(),
639 [Fb, Gb, Abb, Bbb, Cb, Db, Eb]
640 );
641 assert_eq!(
642 Key::from((Fb, HarmonicMinor)).note_names(),
643 [Fb, Gb, Abb, Bbb, Cb, Dbb, Eb]
644 );
645 }
646
647 #[test]
648 fn f_scales() {
649 assert_eq!(Key::from((F, Major)).note_names(), [F, G, A, Bb, C, D, E]);
650 assert_eq!(
651 Key::from((F, NaturalMinor)).note_names(),
652 [F, G, Ab, Bb, C, Db, Eb]
653 );
654 assert_eq!(
655 Key::from((F, MelodicMinor)).note_names(),
656 [F, G, Ab, Bb, C, D, E]
657 );
658 assert_eq!(
659 Key::from((F, HarmonicMinor)).note_names(),
660 [F, G, Ab, Bb, C, Db, E]
661 );
662 }
663
664 #[test]
665 fn fs_scales() {
666 assert_eq!(
667 Key::from((Fs, Major)).note_names(),
668 [Fs, Gs, As, B, Cs, Ds, Es]
669 );
670 assert_eq!(
671 Key::from((Fs, NaturalMinor)).note_names(),
672 [Fs, Gs, A, B, Cs, D, E]
673 );
674 assert_eq!(
675 Key::from((Fs, MelodicMinor)).note_names(),
676 [Fs, Gs, A, B, Cs, Ds, Es]
677 );
678 assert_eq!(
679 Key::from((Fs, HarmonicMinor)).note_names(),
680 [Fs, Gs, A, B, Cs, D, Es]
681 );
682 }
683
684 #[test]
685 fn gb_scales() {
686 assert_eq!(
687 Key::from((Gb, Major)).note_names(),
688 [Gb, Ab, Bb, Cb, Db, Eb, F]
689 );
690 assert_eq!(
691 Key::from((Gb, NaturalMinor)).note_names(),
692 [Gb, Ab, Bbb, Cb, Db, Ebb, Fb]
693 );
694 assert_eq!(
695 Key::from((Gb, MelodicMinor)).note_names(),
696 [Gb, Ab, Bbb, Cb, Db, Eb, F]
697 );
698 assert_eq!(
699 Key::from((Gb, HarmonicMinor)).note_names(),
700 [Gb, Ab, Bbb, Cb, Db, Ebb, F]
701 );
702 }
703
704 #[test]
705 fn g_scales() {
706 assert_eq!(Key::from((G, Major)).note_names(), [G, A, B, C, D, E, Fs]);
707 assert_eq!(
708 Key::from((G, NaturalMinor)).note_names(),
709 [G, A, Bb, C, D, Eb, F]
710 );
711 assert_eq!(
712 Key::from((G, MelodicMinor)).note_names(),
713 [G, A, Bb, C, D, E, Fs]
714 );
715 assert_eq!(
716 Key::from((G, HarmonicMinor)).note_names(),
717 [G, A, Bb, C, D, Eb, Fs]
718 );
719 }
720
721 #[test]
722 fn gs_scales() {
723 assert_eq!(
724 Key::from((Gs, Major)).note_names(),
725 [Gs, As, Bs, Cs, Ds, Es, Fss]
726 );
727 assert_eq!(
728 Key::from((Gs, NaturalMinor)).note_names(),
729 [Gs, As, B, Cs, Ds, E, Fs]
730 );
731 assert_eq!(
732 Key::from((Gs, MelodicMinor)).note_names(),
733 [Gs, As, B, Cs, Ds, Es, Fss]
734 );
735 assert_eq!(
736 Key::from((Gs, HarmonicMinor)).note_names(),
737 [Gs, As, B, Cs, Ds, E, Fss]
738 );
739 }
740 }
741}