music_theory/theory/
scale.rs

1use super::{
2    traits::{
3        Wrapper, VecWrapper, ModeTrait, AsScaleTry, AsSteps, AddInterval, ToPC, AsPCs,
4        AsRelativeIntervals, AsEnharmonicNotes, AsEnharmonicNotesWithStart, Cyclic,
5        ToEnharmonicNote, ToNote, ModeIteratorSpawner, AsChord, AsRootedChord, ScaleIteratorSpawner
6    },
7    Note, _Note, Interval, PCs, Intervals, EnharmonicNote, Chord, RootedChord
8};
9
10/// A mode is an index into all possible modes.
11///
12/// Example:
13/// ```
14/// use music_theory::theory::*;
15/// let W = Interval::WHOLE;
16/// let S = Interval::SEMI;
17/// assert_eq!(
18///     Steps::wrap(
19///         vec![W, W, S, W, W, W, S] // Ionian mode
20///     ).unwrap().mode(2 /* this is the mode type (usize) */),
21///     Steps::wrap(
22///         vec![S, W, W, W, S, W, W] // Phrygian mode
23///     ).unwrap()
24/// );
25/// ```
26pub type Mode = usize;
27/// Type defined for convenience.
28pub type Notes = Vec<Note>;
29
30/// A scale is a list of notes.
31/// For example, the C2 Major scale contains the notes [C2, D2, E2, F2, G2, A3, B3].
32///
33/// Example:
34/// ```
35/// use music_theory::theory::*;
36/// let scale = Scale::wrap(
37///     vec![Note::C1, Note::D1, Note::E1, Note::F1, Note::G1, Note::A2, Note::B2]
38/// ).unwrap();
39/// assert!(scale.contains_all(&[Note::E1, Note::A2]));
40/// ```
41#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
42pub struct Scale(pub(crate) Notes);
43
44/// A Steps object is a list of intervals.
45/// In this case, the list of notes is represented by the intervals between the notes.
46/// The scale formulas build from half steps and whole steps such as \[W,W,H,W,W,W,H\] for the C
47/// Major scale are an example of Steps.
48/// Steps can also contain negative intervals, and as big leaps as the
49/// [Interval][crate::theory::interval::Interval] type allows.
50///
51/// Example:
52/// ```
53/// use music_theory::theory::*;
54/// let W = Interval::WHOLE;
55/// let S = Interval::SEMI;
56/// let steps = Steps::wrap(vec![W, W, S, W, W, W, S]).unwrap(); /* wraps into Option<Steps> so
57/// when you unwrap again you have Steps. */
58/// assert_eq!(
59///     steps.to_scale_try(Note::C1),
60///     Scale::wrap(
61///         vec![Note::C1, Note::D1, Note::E1, Note::F1, Note::G1, Note::A2, Note::B2]
62///     )
63/// );
64/// ```
65#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
66pub struct Steps(pub(crate) Intervals);
67
68impl Scale{
69    /// Will try to convert the scale to steps that define an octave scale.
70    /// This means it needs to fit into one octave.
71    /// It will add a last step so the steps wrap back onto the first note.
72    ///
73    /// Example:
74    /// ```
75    /// use music_theory::theory::*;
76    /// let W = Interval::WHOLE;
77    /// let H = Interval::SEMI;
78    /// assert_eq!( // C Major
79    ///     Scale::wrap(vec![Note::C1, Note::D1, Note::E1, Note::F1, Note::G1, Note::A2, Note::B2])
80    ///         .unwrap().as_octave_steps(),
81    ///     Steps::wrap(vec![W, W, H, W, W, W, H])
82    /// );
83    /// ```
84    pub fn as_octave_steps(&self) -> Option<Steps>{
85        if self.is_empty(){ return None; }
86        let mut res = Vec::new();
87        let mut last = self[0];
88        let mut sum = Interval::ROOT;
89        for note in self.iter().skip(1){
90            let diff = *note - last;
91            if diff.0 < 0 { return None; }
92            if diff.0 == 0 { continue; }
93            res.push(diff);
94            last = *note;
95            sum += diff;
96        }
97        if sum > Interval::OCTAVE { return None; }
98        if sum == Interval::OCTAVE {
99            return Some(Steps(res));
100        }
101        res.push(Interval::OCTAVE - sum);
102        Some(Steps(res))
103    }
104}
105
106impl Steps{
107    /// Will try to return an index and a copy of the mode.
108    /// For example, calling `mode_nr_of_this` on a Ionian mode with a Dorian mode should return
109    /// the index of `1`.
110    /// The index is zero based so giving itself as in input return an index of `0`.
111    ///
112    /// Example:
113    /// ```
114    /// use music_theory::theory::*;
115    /// let W = Interval::WHOLE;
116    /// let H = Interval::SEMI;
117    /// let major = Steps::wrap(vec![W, W, H, W, W, W, H]).unwrap();
118    /// let minor = major.clone().mode(5);
119    /// assert_eq!(
120    ///     major.mode_nr_of_this(&minor),
121    ///     Some((5, Steps::wrap(vec![ W, H, W, W, H, W, W]).unwrap()))
122    /// );
123    /// ```
124    pub fn mode_nr_of_this(&self, mode: &Steps) -> Option<(usize, Steps)>{
125        if mode.len() != self.len() {
126            return None;
127        }
128        let len = self.len();
129        let mut copy = self.clone();
130        for i in 0..=len{
131            if copy.0 == mode.0{
132                return Some((i, copy));
133            }
134            copy.next_mode_mut();
135        }
136        None
137    }
138}
139
140ImplVecWrapper!(Scale, Note);
141ImplVecWrapper!(Steps, Interval);
142
143impl Wrapper for Scale{
144    type Inner = Notes;
145
146    fn wrap(scale: Self::Inner) -> Option<Self>{
147        if scale.is_empty(){
148            None
149        } else {
150            Some(Self(scale))
151        }
152    }
153
154    fn unwrap(self) -> Self::Inner{
155        self.0
156    }
157}
158
159impl Wrapper for Steps{
160    type Inner = Intervals;
161
162    fn wrap(steps: Self::Inner) -> Option<Self>{
163        if steps.is_empty(){
164            None
165        } else {
166            Some(Self(steps))
167        }
168    }
169
170    fn unwrap(self) -> Self::Inner{
171        self.0
172    }
173}
174
175impl ModeTrait for Scale{
176    fn next_mode_mut(&mut self){
177        self.0.rotate_left(1);
178    }
179
180    fn next_mode(mut self) -> Self{
181        self.next_mode_mut();
182        self
183    }
184
185    fn mode(mut self, mode: Mode) -> Self{
186        let len = self.len();
187        self.0.rotate_left(mode % len);
188        Scale(self.0)
189    }
190}
191
192impl ModeTrait for Steps{
193    fn next_mode_mut(&mut self){
194        self.0.rotate_left(1);
195    }
196
197    fn next_mode(mut self) -> Self{
198        self.next_mode_mut();
199        self
200    }
201
202    fn mode(mut self, mode: Mode) -> Self{
203        let len = self.len();
204        self.0.rotate_left(mode % len);
205        Steps(self.0)
206    }
207}
208
209impl AsSteps for Scale{
210    fn as_steps(&self, complete_octave_cycle: bool) -> Steps{
211        if self.0.is_empty() { return Steps::default(); }
212        let mut last = self[0];
213        let mut intervals = Vec::new();
214        for note in self.iter().skip(1){
215            let diff = *note - last;
216            intervals.push(diff);
217            last = *note;
218        }
219        if complete_octave_cycle {
220            intervals.push(self[0] - last + Interval::OCTAVE);
221        }
222        Steps(intervals)
223    }
224}
225
226impl AsPCs for Scale{
227    fn as_pcs(&self) -> PCs{
228        let mut res = Vec::new();
229        for n in &self.0{
230            res.push(n.to_pc());
231        }
232        res
233    }
234}
235
236impl AsChord for Scale{
237    fn as_chord(&self) -> Chord{
238        if self.is_empty() { return Chord(Vec::new()); }
239        let root = self[0];
240        let mut intervals = vec![];
241        for note in self.iter().skip(1){
242            let mut diff = note.0 as i32 - root.0 as i32;
243            if diff == 0 { continue; }
244            if diff < 0 {
245                diff = (diff % 12) + 12;
246            }
247            intervals.push(Note(diff as _Note));
248        }
249        intervals.sort();
250        Chord(intervals)
251    }
252}
253
254// Could be used for hexatonics etc?
255// fn _into_enharmonic_notes_with_start_subheptatonic(scale: Scale, start: Option<EnharmonicNote>) -> Vec<EnharmonicNote>{
256//     let mut set = vec![0, 0, 0, 0, 0, 0, 0];
257//     let mut res = Vec::new();
258//     let skip = if let Some(en) = start{
259//         set[en.letter as usize] = 1;
260//         res.push(en);
261//         1
262//     } else {
263//         0
264//     };
265//     for (i, note) in scale.0.into_iter().enumerate().skip(skip){
266//         if i >= 7 { return Vec::new(); } // Impossible: no more letters.
267//         let en = note.to_enharmonic_note().unwrap();
268//         let en = if set[en.letter as usize] == 1{
269//             let mut nen = en;
270//             loop {
271//                 nen = nen.next();
272//                 if set[nen.letter as usize] == 0 { break nen; }
273//             }
274//         } else {
275//             en
276//         };
277//         set[en.letter as usize] = 1;
278//         res.push(en);
279//     }
280//     res
281// }
282
283fn as_enharmonic_notes_with_start_heptatonic(scale: &Scale, start: Option<EnharmonicNote>)
284    -> Vec<EnharmonicNote>
285{
286    let mut res = Vec::new();
287    if scale.is_empty() { return res; }
288    let (skip, mut target_letter) = if let Some(en) = start{
289        if en.to_note() != scale[0] { return res; }
290        res.push(en);
291        (1, en.next().letter)
292    } else {
293        (0, scale[0].to_enharmonic_note().letter)
294    };
295    for note in scale.iter().skip(skip){
296        let en = note.to_enharmonic_note();
297        let new_en = if en.letter == target_letter {
298            en
299        } else {
300            en.spelled_as(target_letter)
301        };
302        res.push(new_en);
303        target_letter = target_letter.next();
304    }
305    res
306}
307
308impl AsEnharmonicNotes for Scale{
309    fn as_enharmonic_notes(&self) -> Vec<EnharmonicNote>{
310        as_enharmonic_notes_with_start_heptatonic(self, None)
311    }
312}
313
314impl AsEnharmonicNotesWithStart for Scale{
315    fn as_enharmonic_notes_with_start(&self, start: Option<EnharmonicNote>) -> Vec<EnharmonicNote>{
316        as_enharmonic_notes_with_start_heptatonic(self, start)
317    }
318}
319
320impl AsRootedChord for Scale{
321    fn as_rooted_chord(&self) -> RootedChord{
322        if self.is_empty() { RootedChord{ root: Note::ZERO, chord: Chord(vec![]) } }
323        else if self.len() == 1 { RootedChord{ root: self[0], chord: Chord(vec![]) } }
324        else { RootedChord::from_chord(self[0], self.as_chord()) }
325    }
326}
327
328impl AsScaleTry for Steps{
329    fn as_scale_try(&self, mut note: Note) -> Option<Scale>{
330        let mut vec = vec![note];
331        if self.is_empty(){
332            return Some(Scale(vec));
333        }
334        for step in self.iter().take(self.len() - 1){
335            note = note.add_interval(*step)?;
336            vec.push(note);
337        }
338        Some(Scale(vec))
339    }
340}
341
342impl AsRelativeIntervals for Steps{
343    fn as_relative_intervals(&self, reference: &Self) -> Option<Intervals>{
344        if self.0.len() != reference.0.len() { return None; }
345        if self.0.is_empty() { return None; }
346        let mut acc_a = Interval(0);
347        let mut acc_b = Interval(0);
348        let mut res = Vec::new();
349        for i in 0..self.0.len(){
350            let diff = acc_a - acc_b;
351            res.push(diff);
352            acc_a += self[i];
353            acc_b += reference[i];
354        }
355        Some(res)
356    }
357}
358
359impl AsChord for Steps{
360    fn as_chord(&self) -> Chord{
361        if self.is_empty() { return Chord(Vec::new()); }
362        let mut intervals = vec![];
363        let mut acc = 0;
364        for step in self.iter(){
365            acc += step.0;
366            if acc == 0 { continue; }
367            intervals.push(Note((((acc % 12) + 12) % 12) as _Note));
368        }
369        let chord = Chord(intervals);
370        chord.normalized()
371    }
372}
373
374/// Scale iterator iterates over a scale and yields notes.
375/// You can take a `ScaleIterator` from [Steps][crate::theory::scale::Steps] and let it
376/// generate notes from the steps.
377///
378/// Example:
379/// ```
380/// use music_theory::theory::*;
381/// let major = music_theory::libr::ionian::steps();
382/// let mut iter = major.scale_iter(Note::C1);
383/// assert_eq!(
384///     iter.take(7).collect::<Vec<_>>(),
385///     vec![Note::C1, Note::D1, Note::E1, Note::F1, Note::G1, Note::A2, Note::B2]
386/// );
387/// ```
388pub struct ScaleIterator<'a>{
389    scale: &'a [Interval],
390    current: usize,
391    len: usize,
392    root: Note,
393}
394
395impl<'a> Iterator for ScaleIterator<'a>{
396    type Item = Note;
397
398    fn next(&mut self) -> Option<Note>{
399        if self.current >= self.len{
400            self.current = 0;
401        }
402        let res = self.root;
403        self.root = self.root.add_interval(self.scale[self.current])?;
404        self.current += 1;
405        Some(res)
406    }
407}
408
409impl ScaleIteratorSpawner for Steps{
410    fn scale_iter(&self, root: Note) -> ScaleIterator{
411        ScaleIterator{
412            scale: &self.0,
413            current: 0,
414            len: self.len(),
415            root,
416        }
417    }
418}
419
420/// The `ModeIterator` iterates over modes.
421/// Anything that is [Clone][std::clone::Clone] +
422/// [ModeTrait][crate::theory::traits::ModeTrait] +
423/// [VecWrapper][crate::theory::traits::VecWrapper] can spawn a `ModeIterator`.
424///
425/// Example:
426/// ```
427/// use music_theory::theory::*;
428/// let W = Interval::WHOLE;
429/// let H = Interval::SEMI;
430/// let mut iter = music_theory::libr::ionian::steps().mode_iter();
431/// assert_eq!(
432///     iter.next().unwrap().unwrap(),
433///     vec![W, W, H, W, W, W, H]
434/// );
435/// ```
436pub struct ModeIterator<T: ModeTrait + VecWrapper>{
437    wrapper: T,
438    current: usize,
439    len: usize,
440}
441
442// TODO: return references?
443impl<T: Clone + ModeTrait + VecWrapper> Iterator for ModeIterator<T>{
444    type Item = T;
445
446    fn next(&mut self) -> Option<T>{
447        if self.current >= self.len{
448            return Option::None;
449        }
450        let res = self.wrapper.clone();
451        self.wrapper.next_mode_mut();
452        self.current += 1;
453        Option::Some(res)
454    }
455}
456
457impl<T: ModeTrait + VecWrapper> ModeIteratorSpawner<T> for T{
458    fn mode_iter(self) -> ModeIterator<T>{
459        let len = self.len();
460        ModeIterator{
461            wrapper: self,
462            current: 0,
463            len,
464        }
465    }
466}
467
468#[cfg(test)]
469mod tests{
470    use super::super::*;
471
472    #[test]
473    fn scale_wrap(){
474        assert_eq!(Scale::wrap(vec![]), None);
475        assert_eq!(Scale::wrap(vec![Note(0), Note(1)]), Some(Scale(vec![Note(0), Note(1)])));
476    }
477
478    #[test]
479    fn scale_unwrap(){
480        assert_eq!(Scale(vec![Note(0), Note(1)]).unwrap(), vec![Note(0), Note(1)]);
481    }
482
483    #[test]
484    fn steps_wrap(){
485        assert_eq!(Steps::wrap(vec![]), None);
486        assert_eq!(
487            Steps::wrap(vec![Interval(0), Interval(1)]), Some(Steps(vec![Interval(0), Interval(1)]))
488        );
489    }
490
491    #[test]
492    fn steps_unwrap(){
493        assert_eq!(Steps(vec![Interval(2), Interval(1)]).unwrap(), vec![Interval(2), Interval(1)]);
494    }
495
496    #[test]
497    fn scale_len(){
498        assert_eq!(Scale(vec![Note(0), Note(1)]).len(), 2);
499    }
500
501    #[test]
502    fn scale_is_empty(){
503        assert!(!Scale(vec![Note(0)]).is_empty());
504    }
505
506    #[test]
507    fn test_scale_iter(){
508        let scale = Scale(vec![Note(0), Note(1), Note(2)]);
509        let mut iter = scale.iter();
510        assert_eq!(iter.next(), Some(&Note(0)));
511        assert_eq!(iter.next(), Some(&Note(1)));
512        assert_eq!(iter.next(), Some(&Note(2)));
513        assert_eq!(iter.next(), None);
514    }
515
516    #[test]
517    fn scale_contains(){
518        let scale = Scale(vec![Note(0), Note(1), Note(2)]);
519        assert!(scale.contains(&Note(0)));
520        assert!(scale.contains(&Note(1)));
521        assert!(scale.contains(&Note(2)));
522        assert!(!scale.contains(&Note(3)));
523    }
524
525    #[test]
526    fn scale_contains_all(){
527        let scale = Scale(vec![Note(0), Note(1), Note(2)]);
528        assert!(scale.contains_all(&[Note(0)]));
529        assert!(scale.contains_all(&[Note(0), Note(1)]));
530        assert!(scale.contains_all(&[Note(0), Note(1), Note(2)]));
531        assert!(!scale.contains_all(&[Note(0), Note(1), Note(2), Note(3)]));
532    }
533
534    #[test]
535    fn scale_contains_any(){
536        let scale = Scale(vec![Note(0), Note(1), Note(2)]);
537        assert!(scale.contains_any(&[Note(0)]));
538        assert!(scale.contains_any(&[Note(1)]));
539        assert!(scale.contains_any(&[Note(2)]));
540        assert!(scale.contains_any(&[Note(3245), Note(2)]));
541        assert!(!scale.contains_any(&[Note(3)]));
542    }
543
544    #[test]
545    fn scale_as_subs(){
546        let (c, d, e) = (Note::C1, Note::D1, Note::E1);
547        let scale = Scale(vec![c, d, e]);
548        assert_eq!(
549            scale.as_subs(None),
550            vec![
551                Scale(vec![]),
552                Scale(vec![c]),
553                Scale(vec![d]),
554                Scale(vec![e]),
555                Scale(vec![c, d]),
556                Scale(vec![d, c]),
557                Scale(vec![c, e]),
558                Scale(vec![e, c]),
559                Scale(vec![d, e]),
560                Scale(vec![e, d]),
561                Scale(vec![c, d, e]),
562                Scale(vec![c, e, d]),
563                Scale(vec![d, c, e]),
564                Scale(vec![d, e, c]),
565                Scale(vec![e, c, d]),
566                Scale(vec![e, d, c]),
567            ]
568        );
569    }
570
571    #[test]
572    fn scale_indexing(){
573        let (c, d, e) = (Note::C1, Note::D1, Note::E1);
574        let mut scale = Scale(vec![c, d, e]);
575        assert_eq!(scale[0], c);
576        assert_eq!(scale[1], d);
577        assert_eq!(scale[2], e);
578        scale[0] = d;
579        assert_eq!(scale[0], d);
580    }
581
582    #[test]
583    fn steps_len(){
584        assert_eq!(Steps(vec![Interval(1), Interval(2)]).len(), 2);
585    }
586
587    #[test]
588    fn steps_is_empty(){
589        assert!(!Steps(vec![Interval(1)]).is_empty());
590    }
591
592    #[test]
593    fn steps_iter(){
594        let steps = Steps(vec![Interval(1), Interval(2), Interval(3)]);
595        let mut iter = steps.iter();
596        assert_eq!(iter.next(), Some(&Interval(1)));
597        assert_eq!(iter.next(), Some(&Interval(2)));
598        assert_eq!(iter.next(), Some(&Interval(3)));
599        assert_eq!(iter.next(), None);
600    }
601
602    #[test]
603    fn scale_next_mode_mut(){
604        let mut scale = Scale(vec![Note(0), Note(1), Note(2)]);
605        scale.next_mode_mut();
606        assert_eq!(scale, Scale(vec![Note(1), Note(2), Note(0)]));
607        scale.next_mode_mut();
608        assert_eq!(scale, Scale(vec![Note(2), Note(0), Note(1)]));
609        scale.next_mode_mut();
610        assert_eq!(scale, Scale(vec![Note(0), Note(1), Note(2)]));
611        let clone = scale.clone();
612        scale.next_mode_mut();
613        assert_eq!(scale, clone.next_mode());
614    }
615
616    #[test]
617    fn scale_next_mode(){
618        let mut scale = Scale(vec![Note(0), Note(1), Note(2)]);
619        scale = scale.next_mode();
620        assert_eq!(scale, Scale(vec![Note(1), Note(2), Note(0)]));
621        scale = scale.next_mode();
622        assert_eq!(scale, Scale(vec![Note(2), Note(0), Note(1)]));
623        scale = scale.next_mode();
624        assert_eq!(scale, Scale(vec![Note(0), Note(1), Note(2)]));
625        let mut clone = scale.clone();
626        clone.next_mode_mut();
627        assert_eq!(scale.next_mode(), clone);
628    }
629
630    #[test]
631    fn scale_mode(){
632        let scale = Scale(vec![Note(0), Note(1), Note(2)]);
633        assert_eq!(scale.clone().mode(0), scale);
634        assert_eq!(scale.clone().mode(1), Scale(vec![Note(1), Note(2), Note(0)]));
635        assert_eq!(scale.clone().mode(2), Scale(vec![Note(2), Note(0), Note(1)]));
636        assert_eq!(scale.clone().mode(3), scale);
637        assert_eq!(scale.clone().mode(1), scale.next_mode());
638    }
639
640    #[test]
641    fn steps_next_mode_mut(){
642        let mut steps = Steps(vec![Interval(1), Interval(2), Interval(3)]);
643        steps.next_mode_mut();
644        assert_eq!(steps, Steps(vec![Interval(2), Interval(3), Interval(1)]));
645        steps.next_mode_mut();
646        assert_eq!(steps, Steps(vec![Interval(3), Interval(1), Interval(2)]));
647        steps.next_mode_mut();
648        assert_eq!(steps, Steps(vec![Interval(1), Interval(2), Interval(3)]));
649        let clone = steps.clone();
650        steps.next_mode_mut();
651        assert_eq!(steps, clone.next_mode());
652    }
653
654    #[test]
655    fn steps_next_mode(){
656        let mut steps = Steps(vec![Interval(1), Interval(2), Interval(3)]);
657        steps = steps.next_mode();
658        assert_eq!(steps, Steps(vec![Interval(2), Interval(3), Interval(1)]));
659        steps = steps.next_mode();
660        assert_eq!(steps, Steps(vec![Interval(3), Interval(1), Interval(2)]));
661        steps = steps.next_mode();
662        assert_eq!(steps, Steps(vec![Interval(1), Interval(2), Interval(3)]));
663        let mut clone = steps.clone();
664        clone.next_mode_mut();
665        assert_eq!(steps.next_mode(), clone);
666    }
667
668    #[test]
669    fn steps_mode(){
670        let steps = Steps(vec![Interval(1), Interval(2), Interval(3)]);
671        assert_eq!(steps.clone().mode(0), steps);
672        assert_eq!(steps.clone().mode(1), Steps(vec![Interval(2), Interval(3), Interval(1)]));
673        assert_eq!(steps.clone().mode(2), Steps(vec![Interval(3), Interval(1), Interval(2)]));
674        assert_eq!(steps.clone().mode(3), steps);
675        assert_eq!(steps.clone().mode(1), steps.next_mode());
676    }
677
678    #[test]
679    fn steps_as_scale(){
680        assert_eq!(
681            Steps(vec![]).as_scale_try(Note(123)),
682            Some(Scale(vec![Note(123)]))
683        );
684        assert_eq!( // C Major
685            Steps(vec![Interval(2), Interval(2), Interval(1), Interval(2),
686                        Interval(2), Interval(2), Interval(1)])
687                .as_scale_try(PC::C.to_note()).unwrap().iter().map(|n| n.to_pc()).collect::<Vec<_>>(),
688            vec![PC::C, PC::D, PC::E, PC::F, PC::G, PC::A, PC::B]
689        );
690        assert_eq!( // A Minor
691            Steps(vec![Interval(2), Interval(2), Interval(1), Interval(2),
692                        Interval(2), Interval(2), Interval(1)]).mode(5)
693                .to_scale_try(PC::A.to_note()).unwrap().iter().map(|n| n.to_pc()).collect::<Vec<_>>(),
694            vec![PC::A, PC::B, PC::C, PC::D, PC::E, PC::F, PC::G]
695        );
696    }
697
698    #[test]
699    fn scale_as_steps(){
700        assert_eq!( // C Major
701            Scale(vec![Note::C1, Note::D1, Note::E1, Note::F1, Note::G1, Note::A2, Note::B2])
702                .as_steps(true),
703            Steps(vec![Interval(2), Interval(2), Interval(1), Interval(2),
704                        Interval(2), Interval(2), Interval(1)])
705        );
706        assert_eq!(
707            Scale(vec![Note::A1, Note::B1, Note::C1, Note::D1, Note::E1, Note::F1, Note::G1])
708                .as_steps(true),
709            Steps(vec![Interval(2), Interval(2), Interval(1), Interval(2),
710                        Interval(2), Interval(2), Interval(1)]).mode(5)
711        );
712        assert_eq!(
713            Scale(vec![Note::A1, Note::B1, Note::A1, Note::B1]).to_steps(true),
714            Steps(vec![Interval(2), Interval(-2), Interval(2), Interval(10)])
715        );
716        assert_eq!(
717            Scale(vec![Note::A1, Note::B1, Note::A1, Note::B1]).to_steps(false),
718            Steps(vec![Interval(2), Interval(-2), Interval(2)])
719        );
720    }
721
722    #[test]
723    fn scale_as_pcs(){
724        assert_eq!(
725            Scale(vec![Note::C1, Note::E1, Note::G1, Note::C2]).as_pcs(),
726            vec![PC::C, PC::E, PC::G, PC::C]
727        );
728        assert_eq!(
729            Scale(vec![Note::A1, Note::C1, Note::D1, Note::F1, Note::A2]).to_pcs(),
730            vec![PC::A, PC::C, PC::D, PC::F, PC::A]
731        );
732    }
733
734    #[test]
735    fn scale_as_chord(){
736        assert_eq!(Scale(vec![]).to_chord(), Chord(vec![]));
737        assert_eq!(
738            Scale(vec![Note::C1, Note::E1, Note::G1]).as_chord(),
739            Chord::new(MAJOR)
740        );
741        assert_eq!(
742            Scale(vec![Note::C1, Note::B1, Note::E1, Note::G1]).as_chord(),
743            Chord::new(MAJOR_SEVENTH_CHORD)
744        );
745        assert_eq!(
746            Scale(vec![Note::C1, Note::E1, Note::G1, Note::B2]).as_chord(),
747            Chord::new(MAJOR_SEVENTH_CHORD)
748        );
749    }
750
751    #[test]
752    fn mode_nr_of_this(){
753        let major = Steps(vec![Interval(2), Interval(2), Interval(1), Interval(2),
754            Interval(2), Interval(2), Interval(1)]);
755        let minor = major.clone().mode(5);
756        assert_eq!(
757            major.mode_nr_of_this(&minor),
758            Some((5, Steps(vec![
759                Interval(2), Interval(1), Interval(2), Interval(2),
760                Interval(1), Interval(2), Interval(2)
761            ])))
762        );
763        assert_eq!(
764            Steps(vec![Interval(1), Interval(1)]).mode_nr_of_this(&Steps(vec![Interval(1)])),
765            None
766        );
767        assert_eq!(
768            Steps(vec![Interval(1), Interval(2)])
769                .mode_nr_of_this(&Steps(vec![Interval(2), Interval(2)])),
770            None
771        );
772    }
773
774    #[test]
775    fn steps_as_relative_intervals(){
776        let a = Steps(vec![Interval(2), Interval(2), Interval(1), Interval(2),
777            Interval(2), Interval(2), Interval(1)]);
778        let b = Steps(vec![Interval(3), Interval(2), Interval(1), Interval(1),
779            Interval(2), Interval(2), Interval(1)]);
780        assert_eq!(
781            a.to_relative_intervals(&b),
782            Some(vec![Interval(0), Interval(-1), Interval(-1), Interval(-1),
783                        Interval(0), Interval(0), Interval(0)])
784        );
785
786        let scalea = vec![PC::C, PC::D, PC::E, PC::F, PC::G, PC::A, PC::B]
787            .to_scale_try(Note(1)).unwrap().to_steps(true);
788        let scaleb = vec![PC::A, PC::B, PC::C, PC::D, PC::E, PC::F, PC::G]
789            .to_scale_try(Note(1)).unwrap().to_steps(true);
790        assert_eq!(
791            scaleb.to_relative_intervals(&scalea),
792            Some(vec![Interval(0), Interval(0), Interval(-1), Interval(0),
793                    Interval(0), Interval(-1), Interval(-1)])
794        );
795    }
796
797    #[test]
798    fn steps_as_chord(){
799        assert_eq!(Steps(vec![]).to_chord(), Chord(vec![]));
800        assert_eq!(
801            Steps(vec![
802                Interval(4), Interval(3), Interval(4)
803            ]).to_chord(),
804            Chord::new(MAJOR_SEVENTH_CHORD)
805        );
806        assert_eq!(
807            Steps(vec![
808                Interval(0), Interval(4), Interval(3), Interval(4)
809            ]).to_chord(),
810            Chord::new(MAJOR_SEVENTH_CHORD)
811        );
812    }
813
814    #[test]
815    fn scale_as_enharmonic_notes(){
816        assert_eq!(Scale(vec![]).to_enharmonic_notes(), vec![]);
817        assert_eq!(
818            Scale(vec![
819                  Note(0), Note(1), Note(2), Note(3)
820            ]).to_enharmonic_notes(),
821            vec![
822                EnharmonicNote{ letter: Letter::A, accidental: Interval(0) },
823                EnharmonicNote{ letter: Letter::B, accidental: Interval(-1) },
824                EnharmonicNote{ letter: Letter::C, accidental: Interval(-1) },
825                EnharmonicNote{ letter: Letter::D, accidental: Interval(-2) },
826            ]
827        );
828    }
829
830    #[test]
831    fn scale_as_enharmonic_notes_with_start(){
832        assert_eq!(
833            Scale(vec![]).to_enharmonic_notes_with_start(
834                Some(EnharmonicNote{ letter: Letter::A, accidental: Interval(0) })
835            ),
836            vec![]
837        );
838        let scale = Scale(vec![Note(0), Note(1), Note(2), Note(3)]);
839        assert_eq!(
840            scale.clone().to_enharmonic_notes(),
841            scale.to_enharmonic_notes_with_start(
842                Some(EnharmonicNote{ letter: Letter::A, accidental: Interval(0) })
843            )
844        );
845        assert_eq!(
846            Scale(vec![
847                  Note(10), Note(11), Note(12), Note(13)
848            ]).to_enharmonic_notes_with_start(
849                Some(EnharmonicNote { letter: Letter::G, accidental: Interval(0) })
850            ),
851            vec![
852                EnharmonicNote { letter: Letter::G, accidental: Interval(0) },
853                EnharmonicNote { letter: Letter::A, accidental: Interval(-1) },
854                EnharmonicNote { letter: Letter::B, accidental: Interval(-2) },
855                EnharmonicNote { letter: Letter::C, accidental: Interval(-2) }
856            ]
857        );
858        assert_eq!(
859            Scale(vec![
860                  Note(10), Note(11), Note(12), Note(13)
861            ]).to_enharmonic_notes_with_start(
862                Some(EnharmonicNote { letter: Letter::F, accidental: Interval(2) })
863            ),
864            vec![
865                EnharmonicNote { letter: Letter::F, accidental: Interval(2) },
866                EnharmonicNote { letter: Letter::G, accidental: Interval(1) },
867                EnharmonicNote { letter: Letter::A, accidental: Interval(0) },
868                EnharmonicNote { letter: Letter::B, accidental: Interval(-1) }
869            ]
870        );
871        assert_eq!(
872            Scale(vec![
873                  Note(10), Note(11), Note(12), Note(13)
874            ]).to_enharmonic_notes_with_start(
875                Some(EnharmonicNote { letter: Letter::F, accidental: Interval(0) })
876            ),
877            vec![]
878        );
879    }
880
881    #[test]
882    fn mode_iterator(){
883        let mut iter = Steps(vec![Interval(1), Interval(2), Interval(3)]).mode_iter();
884        assert_eq!(iter.next(), Some(Steps(vec![Interval(1), Interval(2), Interval(3)])));
885        assert_eq!(iter.next(), Some(Steps(vec![Interval(2), Interval(3), Interval(1)])));
886        assert_eq!(iter.next(), Some(Steps(vec![Interval(3), Interval(1), Interval(2)])));
887        assert_eq!(iter.next(), None);
888    }
889
890    #[test]
891    fn scale_iterator(){
892        let major = crate::libr::ionian::steps();
893        let mut iter = major.scale_iter(Note::C1);
894        assert_eq!(iter.next(), Some(Note::C1));
895        assert_eq!(iter.next(), Some(Note::D1));
896        assert_eq!(iter.next(), Some(Note::E1));
897        assert_eq!(iter.next(), Some(Note::F1));
898        assert_eq!(iter.next(), Some(Note::G1));
899        assert_eq!(iter.next(), Some(Note::A2));
900        assert_eq!(iter.next(), Some(Note::B2));
901        assert_eq!(iter.next(), Some(Note::C2));
902        assert_eq!(iter.next(), Some(Note::D2));
903    }
904
905    #[test]
906    fn scale_as_octave_steps(){
907        assert_eq!( // C Major
908            Scale(vec![Note::C1, Note::D1, Note::E1, Note::F1, Note::G1, Note::A2, Note::B2])
909                .as_octave_steps(),
910            Some(Steps(vec![Interval(2), Interval(2), Interval(1), Interval(2),
911                        Interval(2), Interval(2), Interval(1)]))
912        );
913        assert_eq!(
914            Scale(vec![Note::A1, Note::B1, Note::C1, Note::D1, Note::E1, Note::F1, Note::G1])
915                .as_octave_steps(),
916            Some(Steps(vec![Interval(2), Interval(2), Interval(1), Interval(2),
917                        Interval(2), Interval(2), Interval(1)]).mode(5))
918        );
919        assert_eq!(
920            Scale(vec![Note::A1, Note::B1, Note::A1, Note::B1]).as_octave_steps(),
921            None
922        );
923        assert_eq!(
924            Scale(vec![Note::A1, Note::B1, Note::A1, Note::B1]).as_octave_steps(),
925            None
926        );
927        assert_eq!( // C Major
928            Scale(vec![Note::C1, Note::D1, Note::E1, Note::F1, Note::G1, Note::A2, Note::B2, Note::C2])
929                .as_octave_steps(),
930            Some(Steps(vec![Interval(2), Interval(2), Interval(1), Interval(2),
931                        Interval(2), Interval(2), Interval(1)]))
932        );
933    }
934}