1use std::{cmp::Ordering, collections::HashSet, fmt::Display};
4
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8use pest::Parser;
9
10use crate::core::{
11 base::{HasDescription, HasName, HasPreciseName, HasStaticName, Parsable, Res},
12 interval::Interval,
13 known_chord::{HasRelativeChord, HasRelativeScale, HasScaleCandidates, IntervalCandidate, IntervalCollectionKind, KnownChord, ScaleCandidate},
14 modifier::{known_modifier_sets, likely_extension_sets, one_off_modifier_sets, Degree, Extension, HasIsDominant, Modifier},
15 named_pitch::HasNamedPitch,
16 note::{CZero, Note, NoteRecreator},
17 octave::{HasOctave, Octave},
18 parser::{note_str_to_note, octave_str_to_octave, ChordParser, Rule},
19 pitch::{HasFrequency, Pitch},
20};
21
22pub trait HasRoot {
26 fn root(&self) -> Note;
28}
29
30pub trait HasSlash {
32 fn slash(&self) -> Note;
34}
35
36pub trait HasModifiers {
38 fn modifiers(&self) -> &HashSet<Modifier>;
40}
41
42pub trait HasExtensions {
44 fn extensions(&self) -> &HashSet<Extension>;
46}
47
48pub trait HasInversion {
50 fn inversion(&self) -> u8;
52}
53
54pub trait HasIsCrunchy {
56 fn is_crunchy(&self) -> bool;
58}
59
60pub trait HasKnownChord {
62 fn known_chord(&self) -> KnownChord;
64}
65
66pub trait HasScale {
68 fn scale(&self) -> Vec<Note>;
70}
71
72pub trait HasChord {
74 fn chord(&self) -> Vec<Note>;
76}
77
78pub trait Chordable {
84 fn with_modifier(self, modifier: Modifier) -> Chord;
86 fn with_modifiers(self, modifiers: &[Modifier]) -> Chord;
88 fn with_extension(self, extension: Extension) -> Chord;
90 fn with_extensions(self, extensions: &[Extension]) -> Chord;
92 fn with_inversion(self, inversion: u8) -> Chord;
94 fn with_slash(self, slash: Note) -> Chord;
96 fn with_octave(self, octave: Octave) -> Chord;
98 fn with_crunchy(self, is_crunchy: bool) -> Chord;
100
101 fn minor(self) -> Chord;
105
106 fn flat5(self) -> Chord;
108 fn flat_five(self) -> Chord;
110
111 fn augmented(self) -> Chord;
113 fn aug(self) -> Chord;
115
116 fn major7(self) -> Chord;
118 fn major_seven(self) -> Chord;
120 fn maj7(self) -> Chord;
122
123 fn dominant7(self) -> Chord;
125 fn seven(self) -> Chord;
127 fn dominant9(self) -> Chord;
129 fn nine(self) -> Chord;
131 fn dominant11(self) -> Chord;
133 fn eleven(self) -> Chord;
135 fn dominant13(self) -> Chord;
137 fn thirteen(self) -> Chord;
139 fn dominant(self, dominant: Degree) -> Chord;
141
142 fn flat9(self) -> Chord;
144 fn flat_nine(self) -> Chord;
146
147 fn sharp9(self) -> Chord;
149 fn sharp_nine(self) -> Chord;
151
152 fn sharp11(self) -> Chord;
154 fn sharp_eleven(self) -> Chord;
156
157 fn flat13(self) -> Chord;
159 fn flat_thirteen(self) -> Chord;
161
162 fn diminished(self) -> Chord;
166 fn dim(self) -> Chord;
168
169 fn half_diminished(self) -> Chord;
171 fn half_dim(self) -> Chord;
173
174 fn sus2(self) -> Chord;
178 fn sus_two(self) -> Chord;
180
181 fn sus4(self) -> Chord;
183 fn sus_four(self) -> Chord;
185 fn sustain(self) -> Chord;
187 fn sus(self) -> Chord;
189
190 fn flat11(self) -> Chord;
192 fn flat_eleven(self) -> Chord;
194
195 fn sharp13(self) -> Chord;
197 fn sharp_thirteen(self) -> Chord;
199
200 fn add2(self) -> Chord;
202 fn add_two(self) -> Chord;
204
205 fn add4(self) -> Chord;
207 fn add_four(self) -> Chord;
209
210 fn add6(self) -> Chord;
212 fn add_six(self) -> Chord;
214
215 fn add9(self) -> Chord;
217 fn add_nine(self) -> Chord;
219
220 fn add11(self) -> Chord;
222 fn add_eleven(self) -> Chord;
224
225 fn add13(self) -> Chord;
227 fn add_thirteen(self) -> Chord;
229}
230
231pub trait HasDomninantDegree {
233 fn dominant_degree(&self) -> Option<Degree>;
235}
236
237#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
241#[derive(PartialEq, Eq, Clone, Debug)]
242pub struct Chord {
243 root: Note,
245 slash: Option<Note>,
247 modifiers: HashSet<Modifier>,
249 extensions: HashSet<Extension>,
251 inversion: u8,
253 is_crunchy: bool,
257}
258
259impl Ord for Chord {
262 fn cmp(&self, other: &Self) -> Ordering {
263 let a_inversion = self.inversion;
264 let b_inversion = other.inversion;
265 let cmp_inversion = a_inversion.cmp(&b_inversion);
266
267 let a_slashes = self.slash.is_some() as u8;
268 let b_slashes = other.slash.is_some() as u8;
269 let cmp_slashes = a_slashes.cmp(&b_slashes);
270
271 let a_crunchy = self.is_crunchy as u8;
272 let b_crunchy = other.is_crunchy as u8;
273 let cmp_crunchy = a_crunchy.cmp(&b_crunchy);
274
275 let a_extensions_len = self.extensions.len() as u8;
276 let b_extensions_len = other.extensions.len() as u8;
277 let cmp_extensions = {
278 let result = a_extensions_len.cmp(&b_extensions_len);
279
280 if result.is_eq() {
281 let a_extensions = Vec::from_iter(&self.extensions);
282 let b_extensions = Vec::from_iter(&other.extensions);
283
284 a_extensions.cmp(&b_extensions)
285 } else {
286 result
287 }
288 };
289
290 let a_modifiers_len = self.modifiers.len() as u8;
291 let b_modifiers_len = other.modifiers.len() as u8;
292 let cmp_modifiers = {
293 let result = a_modifiers_len.cmp(&b_modifiers_len);
294
295 if result.is_eq() {
296 let a_modifiers = Vec::from_iter(&self.modifiers);
297 let b_modifiers = Vec::from_iter(&other.modifiers);
298
299 a_modifiers.cmp(&b_modifiers)
300 } else {
301 result
302 }
303 };
304
305 let a_inversion_exists = u8::from(a_inversion != 0);
307 let b_inversion_exists = u8::from(b_inversion != 0);
308
309 let a_all_changes_len = a_extensions_len + a_modifiers_len + 2 * a_slashes + 2 * a_inversion_exists;
310 let b_all_changes_len = b_extensions_len + b_modifiers_len + 2 * b_slashes + 2 * b_inversion_exists;
311
312 let cmp_all_changes = a_all_changes_len.cmp(&b_all_changes_len);
313
314 let a_root = self.root;
315 let b_root = other.root;
316 let cmp_root = a_root.cmp(&b_root);
317
318 cmp_all_changes
319 .then(cmp_inversion)
320 .then(cmp_slashes)
321 .then(cmp_extensions)
322 .then(cmp_modifiers)
323 .then(cmp_root)
324 .then(cmp_crunchy)
325 }
326}
327
328impl PartialOrd for Chord {
329 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
330 Some(self.cmp(other))
331 }
332}
333
334impl Chord {
335 pub fn new(root: Note) -> Self {
337 Self {
338 root,
339 slash: None,
340 modifiers: HashSet::new(),
341 extensions: HashSet::new(),
342 inversion: 0,
343 is_crunchy: false,
344 }
345 }
346}
347
348impl Chord {
349 pub fn try_from_pitches(all_pitches: &[Pitch]) -> Res<Vec<Self>> {
353 use crate::core::named_pitch::NamedPitch;
354 use crate::core::octave::Octave;
355
356 if all_pitches.is_empty() {
357 return Err(anyhow::Error::msg("Must have at least one pitch to guess a chord."));
358 }
359
360 let mut all_note_combinations = Vec::new();
361
362 let mut base_notes: Vec<Note> = all_pitches.iter().map(|&p| Note::new(NamedPitch::from(p), Octave::Four)).collect();
364 base_notes.sort();
365
366 for rotation in 0..base_notes.len() {
368 let mut rotated = base_notes.clone();
369
370 for i in 0..rotation {
372 rotated[i] = rotated[i].with_octave(Octave::Five);
373 }
374
375 rotated.sort();
377
378 all_note_combinations.push(rotated);
380 }
381
382 let mut all_candidates = Vec::new();
384 for notes in all_note_combinations {
385 if notes.len() >= 3 {
386 if let Ok(candidates) = Self::try_from_notes(¬es) {
387 all_candidates.extend(candidates);
388 }
389 }
390 }
391
392 all_candidates.sort();
394 all_candidates.dedup_by_key(|c| c.to_string());
395
396 if all_candidates.is_empty() {
397 return Err(anyhow::Error::msg("Could not determine chord from pitches."));
398 }
399
400 Ok(all_candidates)
401 }
402
403 pub fn try_from_notes(notes: &[Note]) -> Res<Vec<Self>> {
405 if notes.len() < 3 {
406 return Err(anyhow::Error::msg("Must have at least three notes to guess a chord."));
407 }
408
409 let mut notes = notes.to_vec();
410 notes.sort();
411
412 let mut result = Vec::new();
413
414 for inversion in 0..3 {
416 let proper_root = if inversion == 0 {
417 notes[0]
418 } else {
419 let note = notes[notes.len() - inversion];
420
421 note.with_octave(note.octave() - 1)
422 };
423
424 let proper_root_slash = if inversion == 0 {
425 notes[1]
426 } else {
427 let note = notes[notes.len() - inversion];
428
429 note.with_octave(note.octave() - 1)
430 };
431
432 for mod_set in known_modifier_sets() {
433 for mod_set2 in one_off_modifier_sets() {
434 for ext_set in likely_extension_sets() {
435 for is_crunchy in [false, true] {
436 let candidate_chord_root = Chord::new(proper_root)
438 .with_modifiers(mod_set)
439 .with_modifiers(mod_set2)
440 .with_extensions(ext_set)
441 .with_inversion(inversion as u8)
442 .with_crunchy(is_crunchy);
443 let candidate_chord_root_notes = candidate_chord_root.chord();
444
445 if notes.len() == candidate_chord_root_notes.len() && notes.iter().zip(&candidate_chord_root.chord()).all(|(a, b)| a.frequency() == b.frequency()) {
446 result.push(candidate_chord_root);
447 }
448
449 let candidate_chord_slash = Chord::new(proper_root_slash)
451 .with_slash(notes[0])
452 .with_modifiers(mod_set)
453 .with_modifiers(mod_set2)
454 .with_extensions(ext_set)
455 .with_inversion(inversion as u8)
456 .with_crunchy(is_crunchy);
457 let candidate_chord_slash_notes = candidate_chord_slash.chord();
458
459 if notes.len() == candidate_chord_slash_notes.len() && notes.iter().zip(&candidate_chord_slash.chord()).all(|(a, b)| a.frequency() == b.frequency()) {
460 result.push(candidate_chord_slash);
461 }
462 }
463 }
464 }
465 }
466 }
467
468 for c in &mut result {
470 let dominant_degree = c.dominant_degree();
471
472 if let Some(degree) = dominant_degree {
473 match degree {
474 Degree::Nine => {
475 c.extensions.remove(&Extension::Add9);
476 }
477 Degree::Eleven => {
478 c.extensions.remove(&Extension::Add9);
479 c.extensions.remove(&Extension::Add11);
480 }
481 Degree::Thirteen => {
482 c.extensions.remove(&Extension::Add9);
483 c.extensions.remove(&Extension::Add11);
484 c.extensions.remove(&Extension::Add13);
485 }
486 Degree::Seven => {}
487 }
488 }
489
490 if c.modifiers.contains(&Modifier::Diminished) {
491 c.modifiers.remove(&Modifier::Minor);
492 c.modifiers.remove(&Modifier::Flat5);
493 c.modifiers.remove(&Modifier::Augmented5);
494 }
495 }
496
497 result.sort();
499
500 result.dedup_by(|a, b| a.modifiers == b.modifiers && a.extensions == b.extensions && a.slash == b.slash && a.inversion == b.inversion);
502
503 Ok(result)
504 }
505}
506
507impl HasName for Chord {
508 fn name(&self) -> String {
509 let known_name = self.known_chord().name();
510 let known_name = known_name.as_str();
511 let mut name = String::new();
512
513 name.push_str(self.root.static_name());
514
515 name.push_str(known_name);
516
517 if self.modifiers.contains(&Modifier::Flat5) && !known_name.contains("(♭5)") {
520 name.push_str("(♭5)");
521 }
522
523 if self.modifiers.contains(&Modifier::Augmented5) && !known_name.contains('+') && !known_name.contains("(♯5)") {
524 name.push_str("(♯5)");
525 }
526
527 if self.modifiers.contains(&Modifier::Flat9) && !known_name.contains("(♭9)") {
528 name.push_str("(♭9)");
529 }
530
531 if self.modifiers.contains(&Modifier::Sharp9) && !known_name.contains("(♯9)") {
532 name.push_str("(♯9)");
533 }
534
535 if self.modifiers.contains(&Modifier::Sharp11) && !known_name.contains("(♯11)") {
536 name.push_str("(♯11)");
537 }
538
539 if self.modifiers.contains(&Modifier::Flat13) && !known_name.contains("(♭13)") {
540 name.push_str("(♭13)");
541 }
542
543 if !self.extensions.is_empty() {
545 for e in &self.extensions {
546 name.push_str(&format!("({})", e.static_name()));
547 }
548 }
549
550 if let Some(slash) = self.slash {
552 name.push_str(&format!("/{}", slash.static_name()));
553 }
554
555 name
558 }
559}
560
561impl HasPreciseName for Chord {
562 fn precise_name(&self) -> String {
563 let mut name = String::new();
564
565 name.push_str(&self.name());
566
567 if self.root.octave() != Octave::Four {
569 name.push_str(&format!("@{}", self.root.octave().static_name()));
570 }
571
572 if self.inversion != 0 {
574 name.push_str(&format!("^{}", self.inversion));
575 }
576
577 if self.is_crunchy {
579 name.push('!');
580 }
581
582 name
583 }
584}
585
586impl HasRoot for Chord {
587 fn root(&self) -> Note {
588 self.root
589 }
590}
591
592impl HasSlash for Chord {
593 fn slash(&self) -> Note {
594 self.slash.unwrap_or(self.root)
595 }
596}
597
598impl HasModifiers for Chord {
599 fn modifiers(&self) -> &HashSet<Modifier> {
600 &self.modifiers
601 }
602}
603
604impl HasExtensions for Chord {
605 fn extensions(&self) -> &HashSet<Extension> {
606 &self.extensions
607 }
608}
609
610impl HasInversion for Chord {
611 fn inversion(&self) -> u8 {
612 self.inversion
613 }
614}
615
616impl HasIsCrunchy for Chord {
617 fn is_crunchy(&self) -> bool {
618 self.is_crunchy
619 }
620}
621
622impl Display for Chord {
623 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
624 let scale = self.scale().iter().map(HasStaticName::static_name).collect::<Vec<_>>().join(", ");
625 let chord = self.chord().iter().map(HasStaticName::static_name).collect::<Vec<_>>().join(", ");
626
627 writeln!(f, "{}", self.precise_name())?;
628 writeln!(f, " {}", self.description())?;
629 writeln!(f, " {}", scale)?;
630 write!(f, " {}", chord)?;
631
632 Ok(())
633 }
634}
635
636impl Chordable for Chord {
637 fn with_modifier(mut self, modifier: Modifier) -> Chord {
638 if modifier == Modifier::Augmented5 {
640 self.modifiers.remove(&Modifier::Flat5);
641 self.modifiers.remove(&Modifier::Diminished);
642 }
643
644 if (modifier == Modifier::Diminished || modifier == Modifier::Flat5) && self.modifiers.contains(&Modifier::Augmented5) {
645 return self;
646 }
647
648 self.modifiers.insert(modifier);
649
650 self
651 }
652
653 fn with_modifiers(self, modifiers: &[Modifier]) -> Chord {
654 let mut chord = self;
655
656 for m in modifiers {
657 chord = chord.with_modifier(*m);
658 }
659
660 chord
661 }
662
663 fn with_extension(mut self, extension: Extension) -> Chord {
664 self.extensions.insert(extension);
665
666 self
667 }
668
669 fn with_extensions(self, extensions: &[Extension]) -> Chord {
670 let mut chord = self;
671
672 for e in extensions {
673 chord = chord.with_extension(*e);
674 }
675
676 chord
677 }
678
679 fn with_inversion(mut self, inversion: u8) -> Chord {
680 self.inversion = inversion;
681
682 self
683 }
684
685 fn with_slash(mut self, slash: Note) -> Chord {
686 self.slash = Some(slash);
687
688 self
689 }
690
691 fn with_octave(self, octave: Octave) -> Self {
692 let root = Note::new(self.root.named_pitch(), octave);
693
694 Chord { root, ..self }
695 }
696
697 fn with_crunchy(self, is_crunchy: bool) -> Chord {
698 Chord { is_crunchy, ..self }
699 }
700
701 fn minor(self) -> Chord {
704 self.with_modifier(Modifier::Minor)
705 }
706
707 fn flat5(self) -> Chord {
708 self.with_modifier(Modifier::Flat5)
709 }
710
711 fn flat_five(self) -> Chord {
712 self.flat5()
713 }
714
715 fn augmented(self) -> Chord {
716 self.with_modifier(Modifier::Augmented5)
717 }
718
719 fn aug(self) -> Chord {
720 self.augmented()
721 }
722
723 fn major7(self) -> Chord {
724 self.with_modifier(Modifier::Major7)
725 }
726
727 fn major_seven(self) -> Chord {
728 self.major7()
729 }
730
731 fn maj7(self) -> Chord {
732 self.major7()
733 }
734
735 fn dominant7(self) -> Chord {
736 self.with_modifier(Modifier::Dominant(Degree::Seven))
737 }
738
739 fn seven(self) -> Chord {
740 self.dominant7()
741 }
742
743 fn dominant9(self) -> Chord {
744 self.with_modifier(Modifier::Dominant(Degree::Nine))
745 }
746
747 fn nine(self) -> Chord {
748 self.dominant9()
749 }
750
751 fn dominant11(self) -> Chord {
752 self.with_modifier(Modifier::Dominant(Degree::Eleven))
753 }
754
755 fn eleven(self) -> Chord {
756 self.dominant11()
757 }
758
759 fn dominant13(self) -> Chord {
760 self.with_modifier(Modifier::Dominant(Degree::Thirteen))
761 }
762
763 fn thirteen(self) -> Chord {
764 self.dominant13()
765 }
766
767 fn dominant(self, dominant: Degree) -> Chord {
768 self.with_modifier(Modifier::Dominant(dominant))
769 }
770
771 fn flat9(self) -> Chord {
772 self.with_modifier(Modifier::Flat9)
773 }
774
775 fn flat_nine(self) -> Chord {
776 self.flat9()
777 }
778
779 fn sharp9(self) -> Chord {
780 self.with_modifier(Modifier::Sharp9)
781 }
782
783 fn sharp_nine(self) -> Chord {
784 self.sharp9()
785 }
786
787 fn sharp11(self) -> Chord {
788 self.with_modifier(Modifier::Sharp11)
789 }
790
791 fn sharp_eleven(self) -> Chord {
792 self.sharp11()
793 }
794
795 fn diminished(self) -> Chord {
798 self.with_modifier(Modifier::Diminished)
799 }
800
801 fn dim(self) -> Chord {
802 self.diminished()
803 }
804
805 fn half_diminished(self) -> Chord {
806 self.minor().seven().flat5()
807 }
808
809 fn half_dim(self) -> Chord {
810 self.half_diminished()
811 }
812
813 fn sus2(self) -> Chord {
816 self.with_extension(Extension::Sus2)
817 }
818
819 fn sus_two(self) -> Chord {
820 self.sus2()
821 }
822
823 fn sus4(self) -> Chord {
824 self.with_extension(Extension::Sus4)
825 }
826
827 fn sus_four(self) -> Chord {
828 self.sus4()
829 }
830
831 fn sustain(self) -> Chord {
832 self.sus4()
833 }
834
835 fn sus(self) -> Chord {
836 self.sustain()
837 }
838
839 fn flat11(self) -> Chord {
840 self.with_extension(Extension::Flat11)
841 }
842
843 fn flat_eleven(self) -> Chord {
844 self.flat11()
845 }
846
847 fn flat13(self) -> Chord {
848 self.with_modifier(Modifier::Flat13)
849 }
850
851 fn flat_thirteen(self) -> Chord {
852 self.flat13()
853 }
854
855 fn sharp13(self) -> Chord {
856 self.with_extension(Extension::Sharp13)
857 }
858
859 fn sharp_thirteen(self) -> Chord {
860 self.sharp13()
861 }
862
863 fn add2(self) -> Chord {
864 self.with_extension(Extension::Add2)
865 }
866
867 fn add_two(self) -> Chord {
868 self.add2()
869 }
870
871 fn add4(self) -> Chord {
872 self.with_extension(Extension::Add4)
873 }
874
875 fn add_four(self) -> Chord {
876 self.add4()
877 }
878
879 fn add6(self) -> Chord {
880 self.with_extension(Extension::Add6)
881 }
882
883 fn add_six(self) -> Chord {
884 self.add6()
885 }
886
887 fn add9(self) -> Chord {
888 self.with_extension(Extension::Add9)
889 }
890
891 fn add_nine(self) -> Chord {
892 self.add9()
893 }
894
895 fn add11(self) -> Chord {
896 self.with_extension(Extension::Add11)
897 }
898
899 fn add_eleven(self) -> Chord {
900 self.add11()
901 }
902
903 fn add13(self) -> Chord {
904 self.with_extension(Extension::Add13)
905 }
906
907 fn add_thirteen(self) -> Chord {
908 self.add13()
909 }
910}
911
912impl HasKnownChord for Chord {
913 fn known_chord(&self) -> KnownChord {
914 let modifiers = &self.modifiers;
915 let degree = self.dominant_degree();
916
917 let contains_dominant = degree.is_some();
918 let degree = degree.unwrap_or(Degree::Seven);
919
920 if modifiers.contains(&Modifier::Diminished) {
921 KnownChord::Diminished
922 } else if modifiers.contains(&Modifier::Minor) {
923 if modifiers.contains(&Modifier::Major7) {
924 return KnownChord::MinorMajor7;
925 }
926
927 if contains_dominant {
928 if modifiers.contains(&Modifier::Flat5) {
929 return KnownChord::HalfDiminished(degree);
930 }
931
932 if modifiers.contains(&Modifier::Flat13) {
933 if modifiers.contains(&Modifier::Flat9) {
934 return KnownChord::MinorDominantFlat9Flat13(degree);
935 }
936
937 return KnownChord::MinorDominantFlat13(degree);
938 }
939
940 return KnownChord::MinorDominant(degree);
941 }
942
943 KnownChord::Minor
944 } else {
945 if modifiers.contains(&Modifier::Augmented5) {
946 if modifiers.contains(&Modifier::Major7) {
947 return KnownChord::AugmentedMajor7;
948 }
949
950 if contains_dominant {
951 if modifiers.contains(&Modifier::Flat9) {
952 return KnownChord::AugmentedDominantFlat9(degree);
953 }
954
955 return KnownChord::AugmentedDominant(degree);
956 }
957
958 return KnownChord::Augmented;
959 }
960
961 if self.modifiers.contains(&Modifier::Major7) {
962 return KnownChord::Major7;
963 }
964
965 if contains_dominant {
966 if modifiers.contains(&Modifier::Flat9) {
967 return KnownChord::DominantFlat9(degree);
968 }
969
970 if modifiers.contains(&Modifier::Sharp9) {
971 return KnownChord::DominantSharp9(degree);
972 }
973
974 if modifiers.contains(&Modifier::Sharp11) {
975 return KnownChord::DominantSharp11(degree);
976 }
977
978 return KnownChord::Dominant(degree);
979 }
980
981 if self.modifiers.contains(&Modifier::Sharp11) && modifiers.len() == 1 {
983 return KnownChord::Sharp11;
984 }
985
986 KnownChord::Major
987 }
988 }
989}
990
991impl HasDescription for Chord {
992 fn description(&self) -> &'static str {
993 self.known_chord().description()
994 }
995}
996
997impl Chord {
998 pub fn scale_interval_candidates(&self) -> &'static [IntervalCandidate] {
1000 self.known_chord().scale_interval_candidates()
1001 }
1002}
1003
1004use crate::core::interval::HasIntervals;
1005
1006impl HasIntervals for Chord {
1007 fn intervals(&self) -> &'static [Interval] {
1008 self.known_chord().intervals()
1009 }
1010}
1011
1012impl HasScaleCandidates for Chord {
1013 fn scale_candidates(&self) -> Vec<ScaleCandidate> {
1014 self.scale_interval_candidates().iter().map(IntervalCandidate::to_scale_candidate).collect()
1015 }
1016}
1017
1018impl HasRelativeScale for Chord {
1019 fn relative_scale(&self) -> Vec<Interval> {
1020 self.known_chord().relative_scale()
1021 }
1022}
1023
1024impl HasRelativeChord for Chord {
1025 fn relative_chord(&self) -> Vec<Interval> {
1026 let mut result = self.known_chord().relative_chord();
1027 let modifiers = &self.modifiers;
1028 let extensions = &self.extensions;
1029
1030 if modifiers.contains(&Modifier::Dominant(Degree::Nine)) {
1033 result.push(Interval::MajorNinth);
1034 } else if modifiers.contains(&Modifier::Dominant(Degree::Eleven)) {
1035 result.push(Interval::MajorNinth);
1036 result.push(Interval::PerfectEleventh);
1037 } else if modifiers.contains(&Modifier::Dominant(Degree::Thirteen)) {
1038 result.push(Interval::MajorNinth);
1039 result.push(Interval::PerfectEleventh);
1040 result.push(Interval::MajorThirteenth);
1041 }
1042
1043 if modifiers.contains(&Modifier::Flat5) {
1046 result.remove(2);
1047 result.push(Interval::DiminishedFifth);
1048 }
1049
1050 if modifiers.contains(&Modifier::Augmented5) {
1051 result.remove(2);
1052 result.push(Interval::AugmentedFifth);
1053 }
1054
1055 if modifiers.contains(&Modifier::Flat9) {
1056 result.push(Interval::MinorNinth);
1057 }
1058
1059 if modifiers.contains(&Modifier::Sharp9) {
1060 result.push(Interval::AugmentedNinth);
1061 }
1062
1063 if modifiers.contains(&Modifier::Sharp11) {
1064 result.push(Interval::AugmentedEleventh);
1065 }
1066
1067 if modifiers.contains(&Modifier::Flat13) {
1068 result.push(Interval::MinorThirteenth);
1069 }
1070
1071 if extensions.contains(&Extension::Sus2) {
1074 result.remove(1);
1075 result.push(Interval::MajorSecond);
1076 }
1077
1078 if extensions.contains(&Extension::Sus4) {
1079 result.remove(1);
1080 result.push(Interval::PerfectFourth);
1081 }
1082
1083 if extensions.contains(&Extension::Flat11) {
1084 result.push(Interval::DiminishedEleventh);
1085 }
1086
1087 if extensions.contains(&Extension::Sharp13) {
1088 result.push(Interval::AugmentedThirteenth);
1089 }
1090
1091 if extensions.contains(&Extension::Add2) {
1092 result.push(Interval::MajorSecond);
1093 }
1094
1095 if extensions.contains(&Extension::Add4) {
1096 result.push(Interval::PerfectFourth);
1097 }
1098
1099 if extensions.contains(&Extension::Add6) {
1100 result.push(Interval::MajorSixth);
1101 }
1102
1103 if extensions.contains(&Extension::Add9) {
1104 result.push(Interval::MajorNinth);
1105 }
1106
1107 if extensions.contains(&Extension::Add11) {
1108 result.push(Interval::PerfectEleventh);
1109 }
1110
1111 if extensions.contains(&Extension::Add13) {
1112 result.push(Interval::MajorThirteenth);
1113 }
1114
1115 result.sort();
1117 result.dedup();
1118
1119 result
1120 }
1121}
1122
1123impl HasScale for Chord {
1124 fn scale(&self) -> Vec<Note> {
1125 let candidates = self.scale_interval_candidates();
1127 if let Some(candidate) = candidates.first() {
1128 match candidate.kind {
1129 IntervalCollectionKind::Mode(kind) => crate::core::mode::Mode::new(self.root, kind).notes(),
1130 IntervalCollectionKind::Scale(kind) => crate::core::scale::Scale::new(self.root, kind).notes(),
1131 }
1132 } else {
1133 self.relative_scale().into_iter().map(|i| self.root + i).collect()
1135 }
1136 }
1137}
1138
1139impl HasChord for Chord {
1140 fn chord(&self) -> Vec<Note> {
1141 let mut result: Vec<_> = self.relative_chord().into_iter().map(|i| self.root + i).collect();
1142
1143 for _ in 0..self.inversion {
1145 let mut note = result.remove(0);
1146
1147 while note < *result.last().unwrap_or(&CZero) {
1148 note += Interval::PerfectOctave;
1149 }
1150
1151 result.push(note);
1152 }
1153
1154 if self.is_crunchy {
1156 let bottom = *result.first().unwrap_or(&CZero);
1157 let top = bottom.with_octave(bottom.octave() + 1);
1158
1159 for note in &mut result {
1160 while *note > top {
1161 *note = note.with_octave(note.octave() - 1);
1162 }
1163 }
1164 }
1165
1166 if let Some(mut slash) = self.slash {
1168 let bottom = *result.first().unwrap_or(&CZero);
1170 let floor = Note::new(bottom.named_pitch(), bottom.octave() - 1);
1171
1172 slash = slash.with_octave(Octave::Zero);
1173 while slash < floor {
1174 slash += Interval::PerfectOctave;
1175 }
1176
1177 result.insert(0, slash);
1178 }
1179
1180 result.sort();
1182 result.dedup();
1183
1184 result
1185 }
1186}
1187
1188impl HasDomninantDegree for Chord {
1189 fn dominant_degree(&self) -> Option<Degree> {
1190 let modifiers = &self.modifiers;
1191 if !modifiers.contains(&Modifier::Dominant(Degree::Seven))
1192 && !modifiers.contains(&Modifier::Dominant(Degree::Nine))
1193 && !modifiers.contains(&Modifier::Dominant(Degree::Eleven))
1194 && !modifiers.contains(&Modifier::Dominant(Degree::Thirteen))
1195 {
1196 return None;
1197 }
1198
1199 Some(match modifiers.iter().find(|m| m.is_dominant()) {
1200 Some(Modifier::Dominant(d)) => *d,
1201 _ => Degree::Seven,
1202 })
1203 }
1204}
1205
1206impl Parsable for Chord {
1207 fn parse(input: &str) -> Res<Self>
1208 where
1209 Self: Sized,
1210 {
1211 let root = ChordParser::parse(Rule::chord, input)?.next().unwrap();
1212
1213 assert_eq!(Rule::chord, root.as_rule());
1214
1215 let mut components = root.into_inner();
1216
1217 let note = components.next().unwrap();
1218
1219 assert_eq!(Rule::note, note.as_rule());
1220
1221 let mut result = Chord::new(note_str_to_note(note.into_inner().as_str())?);
1222
1223 while let Some(component) = components.next() {
1224 match component.as_rule() {
1225 Rule::maj7_modifier => {
1226 result = result.major7();
1227 }
1228 Rule::minor => {
1229 result = result.minor();
1230 }
1231 Rule::augmented => {
1232 result = result.augmented();
1233 }
1234 Rule::diminished => {
1235 result = result.diminished();
1236 }
1237 Rule::half_diminished => {
1238 result = result.half_diminished();
1239 }
1240 Rule::dominant_modifier => match component.as_str() {
1241 "7" => {
1242 result = result.seven();
1243 }
1244 "9" => {
1245 result = result.nine();
1246 }
1247 "11" => {
1248 result = result.eleven();
1249 }
1250 "13" => {
1251 result = result.thirteen();
1252 }
1253 _ => {
1254 return Err(anyhow::Error::msg(format!("Unknown dominant modifier: {}", component.as_str())));
1255 }
1256 },
1257 Rule::modifier => match component.as_str() {
1258 "sus2" => {
1259 result = result.sus2();
1260 }
1261 "sus4" => {
1262 result = result.sus4();
1263 }
1264 "add2" => {
1265 result = result.add2();
1266 }
1267 "add4" => {
1268 result = result.add4();
1269 }
1270 "add6" | "6" => {
1271 result = result.add6();
1272 }
1273 "b5" | "♭5" => {
1274 result = result.flat5();
1275 }
1276 "#5" | "♯5" => {
1277 result = result.augmented();
1278 }
1279 "add9" => {
1280 result = result.add9();
1281 }
1282 "b9" | "♭9" => {
1283 result = result.flat9();
1284 }
1285 "#9" | "♯9" => {
1286 result = result.sharp9();
1287 }
1288 "add11" => {
1289 result = result.add11();
1290 }
1291 "b11" | "♭11" => {
1292 result = result.flat11();
1293 }
1294 "#11" | "♯11" => {
1295 result = result.sharp11();
1296 }
1297 "add13" => {
1298 result = result.add13();
1299 }
1300 "b13" | "♭13" => {
1301 result = result.flat13();
1302 }
1303 "#13" | "♯13" => {
1304 result = result.sharp13();
1305 }
1306 _ => {
1307 return Err(anyhow::Error::msg(format!("Unknown modifier: {}", component.as_str())));
1308 }
1309 },
1310 Rule::slash => {
1311 let note = note_str_to_note(components.next().unwrap().as_str())?;
1312
1313 result = result.with_slash(note);
1314 }
1315 Rule::at => {
1316 let octave = octave_str_to_octave(components.next().unwrap().as_str())?;
1317
1318 result = result.with_octave(octave);
1319 }
1320 Rule::hat => {
1321 let inversion = components.next().unwrap().as_str().parse::<u8>()?;
1322
1323 result = result.with_inversion(inversion);
1324 }
1325 Rule::bang => {
1326 result = result.with_crunchy(true);
1327 }
1328 Rule::EOI => {}
1329 _ => {
1330 return Err(anyhow::Error::msg(format!("Unknown rule in chord parser: {:?}", component.as_rule())));
1331 }
1332 }
1333 }
1334
1335 Ok(result)
1336 }
1337}
1338
1339#[cfg(feature = "audio")]
1340use super::base::{Playable, PlaybackHandle};
1341
1342#[cfg(feature = "audio")]
1343impl Playable for Chord {
1344 #[coverage(off)]
1345 fn play(&self, delay: std::time::Duration, length: std::time::Duration, fade_in: std::time::Duration) -> Res<PlaybackHandle> {
1346 use rodio::{source::SineWave, OutputStreamBuilder, Sink, Source};
1347
1348 let chord_tones = self.chord();
1349
1350 if length.as_secs_f32() <= chord_tones.len() as f32 * delay.as_secs_f32() {
1351 return Err(anyhow::Error::msg(
1352 "The delay is too long for the length of play (i.e., the number of chord tones times the delay is longer than the length).",
1353 ));
1354 }
1355
1356 let stream = OutputStreamBuilder::open_default_stream()?;
1357
1358 let mut sinks = vec![];
1359
1360 for (k, n) in chord_tones.into_iter().enumerate() {
1361 let sink = Sink::connect_new(stream.mixer());
1362
1363 let d = delay * k as u32;
1364
1365 let source = SineWave::new(n.frequency()).take_duration(length - d).buffered().delay(d).fade_in(fade_in).amplify(0.20);
1366
1367 sink.append(source);
1368
1369 sinks.push(sink);
1370 }
1371
1372 Ok(PlaybackHandle::new(stream, sinks))
1373 }
1374}
1375
1376impl Default for Chord {
1377 fn default() -> Self {
1378 Chord::new(super::note::C)
1379 }
1380}
1381
1382impl Chord {
1383 pub fn format_with_scale_candidates(&self) -> String {
1392 use std::fmt::Write;
1393
1394 let mut result = String::new();
1395
1396 let scale = self.scale().iter().map(HasStaticName::static_name).collect::<Vec<_>>().join(", ");
1397 let chord = self.chord().iter().map(HasStaticName::static_name).collect::<Vec<_>>().join(", ");
1398
1399 writeln!(&mut result, "{}", self.precise_name()).unwrap();
1400 writeln!(&mut result, " {}", self.description()).unwrap();
1401 writeln!(&mut result, " {}", scale).unwrap();
1402 writeln!(&mut result, " {}", chord).unwrap();
1403
1404 let candidates = self.scale_candidates();
1406 if !candidates.is_empty() {
1407 writeln!(&mut result).unwrap();
1408 writeln!(&mut result, " Recommended scales/modes:").unwrap();
1409 for candidate in candidates {
1410 let notes = candidate.notes(self.root());
1411 let notes_str = notes.iter().map(HasStaticName::static_name).collect::<Vec<_>>().join(", ");
1412 writeln!(&mut result, " {}. {} - {} ({})", candidate.rank(), candidate.name(), candidate.reason(), notes_str).unwrap();
1413 writeln!(&mut result, " {}", candidate.description()).unwrap();
1414 }
1415 }
1416
1417 result
1418 }
1419}
1420
1421#[cfg(test)]
1424mod tests {
1425 use super::*;
1426 use crate::core::{note::*, octave::HasOctave};
1427 use pretty_assertions::assert_eq;
1428
1429 #[test]
1430 fn test_text() {
1431 assert_eq!(Chord::new(C).flat9().sharp9().sharp11().add13().with_slash(E).name(), "C(♭9)(♯9)(♯11)(add13)/E");
1432 assert_eq!(Chord::new(C).flat5().name(), "C(♭5)");
1433 assert_eq!(Chord::new(C).minor().augmented().name(), "Cm(♯5)");
1434 assert_eq!(Chord::new(C).with_octave(Octave::Six).precise_name(), "C@6");
1435
1436 let display_output = format!("{}", Chord::new(C).minor().seven().flat_five());
1438 assert!(display_output.contains("Cm7(♭5)"));
1439 assert!(display_output.contains("half diminished"));
1440 assert!(display_output.contains("C, D♭, E♭, F, G♭, A♭, B♭"));
1441 assert!(display_output.contains("C, E♭, G♭, B♭"));
1442 assert!(!display_output.contains("Recommended scales/modes:"));
1443
1444 let verbose_output = Chord::new(C).minor().seven().flat_five().format_with_scale_candidates();
1446 assert!(verbose_output.contains("Recommended scales/modes:"));
1447 assert!(verbose_output.contains("locrian"));
1448 }
1449
1450 #[test]
1451 fn test_display_format() {
1452 let chord = Chord::new(C);
1454 let output = format!("{}", chord);
1455 let expected = "C\n major\n C, D, E, F, G, A, B\n C, E, G";
1456 assert_eq!(output, expected);
1457
1458 let verbose_output = chord.format_with_scale_candidates();
1460 assert!(verbose_output.contains("Recommended scales/modes:"));
1461 assert!(verbose_output.contains("ionian"));
1462 assert!(verbose_output.contains("major pentatonic"));
1463 }
1464
1465 #[test]
1466 fn test_properties() {
1467 assert_eq!(Chord::new(C).seven().flat9().root(), C);
1468 assert_eq!(Chord::new(C).with_slash(E).slash(), E);
1469 assert_eq!(Chord::new(C).slash(), C);
1470 assert_eq!(Chord::new(C).flat9().add13().with_slash(E).modifiers(), &vec![Modifier::Flat9].into_iter().collect::<HashSet<_>>());
1471 assert_eq!(Chord::new(C).flat9().add13().with_slash(E).extensions(), &vec![Extension::Add13].into_iter().collect::<HashSet<_>>());
1472 assert_eq!(Chord::new(C).flat9().add13().with_slash(E).seven().dominant_degree(), Some(Degree::Seven));
1473 assert_eq!(Chord::new(C).flat9().add13().with_slash(E).nine().dominant_degree(), Some(Degree::Nine));
1474 assert_eq!(Chord::new(C).flat9().with_inversion(1).inversion(), 1);
1475 assert_eq!(Chord::new(C).flat9().with_octave(Octave::Three).root().octave(), Octave::Three);
1476 }
1477
1478 #[test]
1479 fn test_known_chords() {
1480 assert_eq!(Chord::new(C).known_chord(), KnownChord::Major);
1481 assert_eq!(Chord::new(C).minor().known_chord(), KnownChord::Minor);
1482 assert_eq!(Chord::new(C).major7().known_chord(), KnownChord::Major7);
1483 assert_eq!(Chord::new(C).minor().major7().known_chord(), KnownChord::MinorMajor7);
1484 assert_eq!(Chord::new(C).minor().dominant(Degree::Seven).known_chord(), KnownChord::MinorDominant(Degree::Seven));
1485 assert_eq!(Chord::new(C).minor().eleven().known_chord(), KnownChord::MinorDominant(Degree::Eleven));
1486 assert_eq!(Chord::new(C).seven().known_chord(), KnownChord::Dominant(Degree::Seven));
1487 assert_eq!(Chord::new(C).eleven().known_chord(), KnownChord::Dominant(Degree::Eleven));
1488 assert_eq!(Chord::new(C).thirteen().known_chord(), KnownChord::Dominant(Degree::Thirteen));
1489 assert_eq!(Chord::new(C).diminished().known_chord(), KnownChord::Diminished);
1490 assert_eq!(Chord::new(C).dim().known_chord(), KnownChord::Diminished);
1491 assert_eq!(Chord::new(C).minor().seven().flat5().known_chord(), KnownChord::HalfDiminished(Degree::Seven));
1492 assert_eq!(Chord::new(C).augmented().known_chord(), KnownChord::Augmented);
1493 assert_eq!(Chord::new(C).aug().major7().known_chord(), KnownChord::AugmentedMajor7);
1494 assert_eq!(Chord::new(C).augmented().seven().known_chord(), KnownChord::AugmentedDominant(Degree::Seven));
1495 assert_eq!(Chord::new(C).seven().sharp11().known_chord(), KnownChord::DominantSharp11(Degree::Seven));
1496 assert_eq!(Chord::new(C).seven().flat9().known_chord(), KnownChord::DominantFlat9(Degree::Seven));
1497 assert_eq!(Chord::new(C).seven().sharp9().known_chord(), KnownChord::DominantSharp9(Degree::Seven));
1498 assert_eq!(Chord::new(C).seven().flat9().augmented().known_chord(), KnownChord::AugmentedDominantFlat9(Degree::Seven));
1499
1500 assert_eq!(Chord::new(C).sus2().known_chord(), KnownChord::Major);
1501 assert_eq!(Chord::new(C).sus4().known_chord(), KnownChord::Major);
1502 assert_eq!(Chord::new(C).sustain().known_chord(), KnownChord::Major);
1503 assert_eq!(Chord::new(C).seven().sus().known_chord(), KnownChord::Dominant(Degree::Seven));
1504 }
1505
1506 #[test]
1507 fn test_scales() {
1508 assert_eq!(Chord::new(C).scale(), vec![C, D, E, F, G, A, B]);
1511 assert_eq!(Chord::new(C).minor().scale(), vec![C, D, EFlat, F, G, AFlat, BFlat]);
1512 assert_eq!(Chord::new(C).major_seven().scale(), vec![C, D, E, F, G, A, B]);
1513 assert_eq!(Chord::new(C).minor().maj7().scale(), vec![C, D, EFlat, F, G, A, B]);
1514 assert_eq!(Chord::new(C).minor().seven().scale(), vec![C, D, EFlat, F, G, A, BFlat]);
1515 assert_eq!(Chord::new(C).minor().eleven().scale(), vec![C, D, EFlat, F, G, A, BFlat]);
1516 assert_eq!(Chord::new(C).seven().scale(), vec![C, D, E, F, G, A, BFlat]);
1517 assert_eq!(Chord::new(C).eleven().scale(), vec![C, D, E, F, G, A, BFlat]);
1518 assert_eq!(Chord::new(C).thirteen().scale(), vec![C, D, E, F, G, A, BFlat]);
1519 assert_eq!(Chord::new(C).diminished().scale(), vec![C, D, EFlat, F, GFlat, AFlat, BDoubleFlat, B]);
1520 assert_eq!(Chord::new(C).dim().scale(), vec![C, D, EFlat, F, GFlat, AFlat, BDoubleFlat, B]);
1521 assert_eq!(Chord::new(C).minor().seven().flat5().scale(), vec![C, DFlat, EFlat, F, GFlat, AFlat, BFlat]);
1522 assert_eq!(Chord::new(C).augmented().scale(), vec![C, D, E, F, GSharp, A, B]);
1523 assert_eq!(Chord::new(C).augmented().major7().scale(), vec![C, D, E, FSharp, GSharp, A, B]);
1524 assert_eq!(Chord::new(C).augmented().seven().scale(), vec![C, D, E, FSharp, GSharp, ASharp]);
1525 assert_eq!(Chord::new(C).seven().sharp_eleven().scale(), vec![C, D, E, FSharp, G, A, BFlat]);
1526 assert_eq!(Chord::new(C).seven().flat_nine().scale(), vec![C, DFlat, EFlat, E, FSharp, G, A, BFlat]);
1527 assert_eq!(Chord::new(C).seven().sharp_nine().scale(), vec![C, DFlat, EFlat, FFlat, GFlat, AFlat, BFlat]);
1528
1529 assert_eq!(Chord::new(DFlat).scale(), vec![DFlat, EFlat, F, GFlat, AFlat, BFlat, CFive]);
1532 assert_eq!(Chord::new(DFlat).seven().scale(), vec![DFlat, EFlat, F, GFlat, AFlat, BFlat, CFlatFive]);
1533 assert_eq!(Chord::new(DFlat).dim().scale(), vec![DFlat, EFlat, FFlat, GFlat, ADoubleFlat, BDoubleFlat, CDoubleFlatFive, CFive]);
1534 }
1535
1536 #[test]
1537 fn test_chords() {
1538 assert_eq!(Chord::new(C).chord(), vec![C, E, G]);
1541 assert_eq!(Chord::new(C).minor().chord(), vec![C, EFlat, G]);
1542 assert_eq!(Chord::new(C).major7().chord(), vec![C, E, G, B]);
1543 assert_eq!(Chord::new(C).minor().major7().chord(), vec![C, EFlat, G, B]);
1544 assert_eq!(Chord::new(C).minor().seven().chord(), vec![C, EFlat, G, BFlat]);
1545 assert_eq!(Chord::new(C).minor().eleven().chord(), vec![C, EFlat, G, BFlat, DFive, FFive]);
1546 assert_eq!(Chord::new(C).seven().chord(), vec![C, E, G, BFlat]);
1547 assert_eq!(Chord::new(C).eleven().chord(), vec![C, E, G, BFlat, DFive, FFive]);
1548 assert_eq!(Chord::new(C).thirteen().chord(), vec![C, E, G, BFlat, DFive, FFive, AFive]);
1549 assert_eq!(Chord::new(C).diminished().chord(), vec![C, EFlat, GFlat, BDoubleFlat]);
1550 assert_eq!(Chord::new(C).dim().chord(), vec![C, EFlat, GFlat, BDoubleFlat]);
1551 assert_eq!(Chord::new(C).minor().seven().flat5().chord(), vec![C, EFlat, GFlat, BFlat]);
1552 assert_eq!(Chord::new(C).half_diminished().chord(), vec![C, EFlat, GFlat, BFlat]);
1553 assert_eq!(Chord::new(C).half_dim().chord(), vec![C, EFlat, GFlat, BFlat]);
1554 assert_eq!(Chord::new(C).augmented().chord(), vec![C, E, GSharp]);
1555 assert_eq!(Chord::new(C).augmented().major7().chord(), vec![C, E, GSharp, B]);
1556 assert_eq!(Chord::new(C).augmented().seven().chord(), vec![C, E, GSharp, BFlat]);
1557 assert_eq!(Chord::new(C).seven().sharp11().chord(), vec![C, E, G, BFlat, FSharpFive]);
1558 assert_eq!(Chord::new(C).seven().flat_nine().chord(), vec![C, E, G, BFlat, DFlatFive]);
1559 assert_eq!(Chord::new(C).seven().sharp_nine().chord(), vec![C, E, G, BFlat, DSharpFive]);
1560
1561 assert_eq!(Chord::new(C).nine().sus2().chord(), vec![C, D, G, BFlat, DFive]);
1564 assert_eq!(Chord::new(C).nine().sus_two().chord(), vec![C, D, G, BFlat, DFive]);
1565 assert_eq!(Chord::new(C).nine().sus4().chord(), vec![C, F, G, BFlat, DFive]);
1566 assert_eq!(Chord::new(C).nine().sus_four().chord(), vec![C, F, G, BFlat, DFive]);
1567 assert_eq!(Chord::new(C).nine().sustain().chord(), vec![C, F, G, BFlat, DFive]);
1568 assert_eq!(Chord::new(C).seven().sus().chord(), vec![C, F, G, BFlat]);
1569 assert_eq!(Chord::new(C).seven().add2().chord(), vec![C, D, E, G, BFlat]);
1570 assert_eq!(Chord::new(C).seven().add_two().chord(), vec![C, D, E, G, BFlat]);
1571 assert_eq!(Chord::new(C).seven().add4().chord(), vec![C, E, F, G, BFlat]);
1572 assert_eq!(Chord::new(C).seven().add_four().chord(), vec![C, E, F, G, BFlat]);
1573 assert_eq!(Chord::new(C).add6().chord(), vec![C, E, G, A]);
1574 assert_eq!(Chord::new(C).seven().add9().chord(), vec![C, E, G, BFlat, DFive]);
1575 assert_eq!(Chord::new(C).seven().add_nine().chord(), vec![C, E, G, BFlat, DFive]);
1576 assert_eq!(Chord::new(C).seven().add11().chord(), vec![C, E, G, BFlat, FFive]);
1577 assert_eq!(Chord::new(C).seven().add_eleven().chord(), vec![C, E, G, BFlat, FFive]);
1578 assert_eq!(Chord::new(C).seven().add13().chord(), vec![C, E, G, BFlat, AFive]);
1579 assert_eq!(Chord::new(C).seven().add_thirteen().chord(), vec![C, E, G, BFlat, AFive]);
1580 assert_eq!(Chord::new(C).seven().add2().add4().chord(), vec![C, D, E, F, G, BFlat]);
1581 assert_eq!(Chord::new(C).seven().add6().chord(), vec![C, E, G, A, BFlat]);
1582 assert_eq!(Chord::new(C).seven().add_six().chord(), vec![C, E, G, A, BFlat]);
1583 assert_eq!(Chord::new(C).seven().flat11().chord(), vec![C, E, G, BFlat, FFlatFive]);
1584 assert_eq!(Chord::new(C).seven().flat_eleven().chord(), vec![C, E, G, BFlat, FFlatFive]);
1585 assert_eq!(Chord::new(C).seven().flat13().chord(), vec![C, E, G, BFlat, AFlatFive]);
1586 assert_eq!(Chord::new(C).seven().flat_thirteen().chord(), vec![C, E, G, BFlat, AFlatFive]);
1587 assert_eq!(Chord::new(C).seven().sharp13().chord(), vec![C, E, G, BFlat, ASharpFive]);
1588 assert_eq!(Chord::new(C).seven().sharp_thirteen().chord(), vec![C, E, G, BFlat, ASharpFive]);
1589
1590 assert_eq!(Chord::new(C).seven().sharp9().with_crunchy(true).chord(), vec![C, DSharp, E, G, BFlat]);
1593
1594 assert_eq!(Chord::new(C).with_slash(D).chord(), vec![DThree, C, E, G]);
1597 assert_eq!(Chord::new(CFive).with_slash(D).chord(), vec![DFour, CFive, EFive, GFive]);
1598
1599 assert_eq!(C.into_chord().with_inversion(1).chord(), vec![E, G, CFive]);
1602 assert_eq!(C.into_chord().with_inversion(2).chord(), vec![G, CFive, EFive]);
1603 assert_eq!(C.into_chord().maj7().with_inversion(3).chord(), vec![B, CFive, EFive, GFive]);
1604 assert_eq!(BFlatThree.into_chord().seven().flat9().with_inversion(1).chord(), vec![D, F, AFlat, CFlatFive, BFlatFive]);
1605
1606 assert_eq!(C.into_chord().flat5().aug().chord(), vec![C, E, GSharp]);
1608 }
1609
1610 #[test]
1611 fn test_parse() {
1612 assert_eq!(Chord::parse("C").unwrap().chord(), vec![C, E, G]);
1613 assert_eq!(Chord::parse("Cm").unwrap().chord(), vec![C, EFlat, G]);
1614 assert_eq!(Chord::parse("Cm7").unwrap().chord(), vec![C, EFlat, G, BFlat]);
1615 assert_eq!(Chord::parse("Cm7b5").unwrap().chord(), vec![C, EFlat, GFlat, BFlat]);
1616 assert_eq!(Chord::parse("C7").unwrap().chord(), vec![C, E, G, BFlat]);
1617 assert_eq!(Chord::parse("C7b9").unwrap().chord(), vec![C, E, G, BFlat, DFlatFive]);
1618 assert_eq!(Chord::parse("C7b9#11").unwrap().chord(), vec![C, E, G, BFlat, DFlatFive, FSharpFive]);
1619 assert_eq!(Chord::parse("C(add6)").unwrap().chord(), vec![C, E, G, A]);
1620 assert_eq!(Chord::parse("Em(#5)").unwrap().chord(), vec![E, G, BSharp]);
1621 assert_eq!(Chord::parse("D+11").unwrap().chord(), vec![D, FSharp, ASharp, CFive, EFive, GFive]);
1622 assert_eq!(Chord::parse("Dm13b5").unwrap().chord(), vec![D, F, AFlat, CFive, EFive, GFive, BFive]);
1623 assert_eq!(Chord::parse("Dsus2").unwrap().chord(), vec![D, E, A]);
1624 assert_eq!(Chord::parse("Dsus4").unwrap().chord(), vec![D, G, A]);
1625 assert_eq!(Chord::parse("Dadd2").unwrap().chord(), vec![D, E, FSharp, A]);
1626 assert_eq!(Chord::parse("Dadd4").unwrap().chord(), vec![D, FSharp, G, A]);
1627 assert_eq!(Chord::parse("Dadd9").unwrap().chord(), vec![D, FSharp, A, EFive]);
1628 assert_eq!(Chord::parse("Dadd11").unwrap().chord(), vec![D, FSharp, A, GFive]);
1629 assert_eq!(Chord::parse("Dadd13").unwrap().chord(), vec![D, FSharp, A, BFive]);
1630 assert_eq!(Chord::parse("Dm#9").unwrap().chord(), vec![D, F, A, ESharpFive]);
1631 assert_eq!(Chord::parse("Dmb11").unwrap().chord(), vec![D, F, A, GFlatFive]);
1632 assert_eq!(Chord::parse("D(b13)").unwrap().chord(), vec![D, FSharp, A, BFlatFive]);
1633 assert_eq!(Chord::parse("D(#13)").unwrap().chord(), vec![D, FSharp, A, BSharpFive]);
1634 }
1635
1636 #[test]
1637 fn test_guess() {
1638 assert_eq!(
1639 Chord::try_from_notes(&[EThree, C, EFlat, FSharp, ASharp, DFive]).unwrap().first().unwrap().chord(),
1640 Chord::parse("Cm9b5/E").unwrap().chord()
1641 );
1642 assert_eq!(Chord::try_from_notes(&[C, E, G]).unwrap().first().unwrap().chord(), Chord::parse("C").unwrap().chord());
1643 assert_eq!(
1644 Chord::try_from_notes(&[C, E, G, BFlat, DFive, FFive]).unwrap().first().unwrap().chord(),
1645 Chord::parse("C11").unwrap().chord()
1646 );
1647 assert_eq!(
1648 Chord::try_from_notes(&[C, E, G, BFlat, DFive, FFive, AFive]).unwrap().first().unwrap().chord(),
1649 Chord::parse("C13").unwrap().chord()
1650 );
1651 assert_eq!(Chord::try_from_notes(&[C, EFlat, GFlat, A]).unwrap().first().unwrap().chord(), Chord::parse("Cdim").unwrap().chord());
1652 }
1653
1654 #[test]
1655 #[should_panic(expected = "Must have at least three notes to guess a chord.")]
1656 fn test_chord_from_notes_failure() {
1657 Chord::try_from_notes(&[C, E]).unwrap();
1658 }
1659}