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}