redact_composer_musical/scale/
mod.rs

1use crate::{Interval, IntervalStepSequence};
2
3mod mode;
4pub use mode::*;
5
6mod degree;
7pub use degree::*;
8
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11
12#[cfg(feature = "redact-composer")]
13use redact_composer_core::derive::Element;
14
15/// Sequence of intervals spanning 12 semitones or one octave.
16#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
17#[cfg_attr(feature = "redact-composer", derive(Element))]
18#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
19pub enum Scale {
20    /// ```
21    /// # use redact_composer_musical::Scale;
22    /// # use redact_composer_musical::{Interval, IntervalStepSequence};
23    /// let (w, h) = (Interval(2), Interval(1)); // w = Whole-step, h = Half-step
24    /// assert_eq!(Scale::Major.interval_steps(), vec![w, w, h, w, w, w, h]);
25    /// assert_eq!(Scale::Major.interval_steps().into_iter().sum::<Interval>(), Interval::Octave);
26    /// ```
27    Major,
28    /// ```
29    /// # use redact_composer_musical::Scale;
30    /// # use redact_composer_musical::{Interval, IntervalStepSequence};
31    /// let (w, h) = (Interval(2), Interval(1)); // w = Whole-step, h = Half-step
32    /// assert_eq!(Scale::NaturalMinor.interval_steps(), vec![w, h, w, w, h, w, w]);
33    /// assert_eq!(Scale::NaturalMinor.interval_steps().into_iter().sum::<Interval>(), Interval::Octave);
34    /// ```
35    NaturalMinor,
36    /// ```
37    /// # use redact_composer_musical::Scale;
38    /// # use redact_composer_musical::{Interval, IntervalStepSequence};
39    /// let (w, h) = (Interval(2), Interval(1)); // w = Whole-step, h = Half-step
40    /// assert_eq!(Scale::MelodicMinor.interval_steps(), vec![w, h, w, w, w, w, h]);
41    /// assert_eq!(Scale::MelodicMinor.interval_steps().into_iter().sum::<Interval>(), Interval::Octave);
42    /// ```
43    MelodicMinor,
44    /// ```
45    /// # use redact_composer_musical::Scale;
46    /// # use redact_composer_musical::{Interval, IntervalStepSequence};
47    /// let (w, h) = (Interval(2), Interval(1)); // w = Whole-step, h = Half-step
48    /// assert_eq!(Scale::HarmonicMinor.interval_steps(), vec![w, h, w, w, h, w + h, h]);
49    /// assert_eq!(Scale::HarmonicMinor.interval_steps().into_iter().sum::<Interval>(), Interval::Octave);
50    /// ```
51    HarmonicMinor,
52}
53
54impl IntervalStepSequence for Scale {
55    fn interval_steps(&self) -> Vec<Interval> {
56        let (w, h) = (Interval(2), Interval(1)); // w = Whole-step, h = Half-step
57
58        match self {
59            Scale::Major => vec![w, w, h, w, w, w, h],
60            Scale::NaturalMinor => vec![w, h, w, w, h, w, w],
61            Scale::MelodicMinor => vec![w, h, w, w, w, w, h],
62            Scale::HarmonicMinor => vec![w, h, w, w, h, w + h, h],
63        }
64    }
65}
66
67impl Scale {
68    /// Returns a [Vec]<[Scale]> of all types.
69    pub fn values() -> Vec<Scale> {
70        vec![
71            Self::Major,
72            Self::NaturalMinor,
73            Self::MelodicMinor,
74            Self::HarmonicMinor,
75        ]
76    }
77}