notation_core/
chord.rs

1use std::fmt::Display;
2use std::hash::Hash;
3
4use serde::{Deserialize, Serialize};
5
6use crate::interval::Interval;
7use crate::prelude::{Intervals, Semitones, Syllable};
8
9#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Debug)]
10pub struct Chord {
11    pub root: Syllable,
12    pub intervals: Intervals,
13    pub bass: Option<Interval>,
14}
15impl Display for Chord {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        let bass = match self.bass {
18            Some(base) => format!(" /{}", base),
19            None => "".to_owned(),
20        };
21        write!(f, "<Chord>({}: {}{})", self.root, self.intervals, bass)
22    }
23}
24impl Chord {
25    pub fn new(root: Syllable, intervals: Intervals, bass: Option<Interval>) -> Self {
26        Self {
27            root,
28            intervals,
29            bass,
30        }
31    }
32    pub fn calc_interval(&self, syllable: Syllable) -> Option<Interval> {
33        if Semitones::from(self.root) == Semitones::from(syllable) {
34            return Some(Interval::Unison);
35        }
36        for interval in self.intervals.get_intervals().iter() {
37            if interval.is_matched(self.root, syllable) {
38                return Some(interval.clone());
39            }
40        }
41        if let Some(base) = self.bass {
42            if base.is_matched(self.root, syllable) {
43                return Some(base);
44            }
45        }
46        None
47    }
48}
49impl Hash for Chord {
50    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
51        let string = self.to_string();
52        string.hash(state);
53    }
54}
55
56impl From<(Syllable, Intervals)> for Chord {
57    fn from(v: (Syllable, Intervals)) -> Self {
58        Self::new(v.0, v.1, None)
59    }
60}
61
62impl From<(Syllable, Vec<Interval>)> for Chord {
63    fn from(v: (Syllable, Vec<Interval>)) -> Self {
64        Self::new(v.0, v.1.into(), None)
65    }
66}
67
68impl From<(Syllable, Intervals, Interval)> for Chord {
69    fn from(v: (Syllable, Intervals, Interval)) -> Self {
70        Self::new(v.0, v.1, Some(v.2))
71    }
72}
73
74impl From<(Syllable, Vec<Interval>, Interval)> for Chord {
75    fn from(v: (Syllable, Vec<Interval>, Interval)) -> Self {
76        Self::new(v.0, v.1.into(), Some(v.2))
77    }
78}