redact_composer_musical/
lib.rs1#![deny(missing_docs, missing_debug_implementations)]
2pub mod rhythm;
6
7mod timing;
8pub use timing::*;
9
10mod chord;
11pub use chord::*;
12
13mod pitch_class;
14pub use pitch_class::*;
15
16mod note;
17pub use note::*;
18
19mod interval;
20pub use interval::*;
21
22mod key;
23pub use key::*;
24
25mod scale;
26pub use scale::*;
27
28#[cfg(feature = "redact-composer")]
30pub mod elements {
31 pub use super::{
32 rhythm::Rhythm, Chord, ChordShape, Degree, Interval, Key, Mode, Note, NoteName, PitchClass,
33 Scale, TimeSignature,
34 };
35}
36
37pub trait IntervalStepSequence {
39 fn interval_steps(&self) -> Vec<Interval>;
41}
42
43pub trait IntervalCollection {
45 fn intervals(&self) -> Vec<Interval>;
47}
48
49impl<T> IntervalCollection for T
50where
51 T: IntervalStepSequence,
52{
53 fn intervals(&self) -> Vec<Interval> {
54 let mut intervals = self
55 .interval_steps()
56 .into_iter()
57 .fold(
58 (vec![Interval::P1], Interval::P1),
59 |(mut intervals, mut last), step| {
60 last += step;
61 intervals.push(last);
62
63 (intervals, last)
64 },
65 )
66 .0;
67
68 if intervals.len() > 1 && (intervals[intervals.len() - 1].0 - intervals[0].0) % 12 == 0 {
69 intervals.pop();
70 }
71
72 intervals
73 }
74}
75
76pub trait PitchClassCollection {
78 fn pitch_classes(&self) -> Vec<PitchClass>;
80}
81
82impl<P: Into<PitchClass> + Copy, I: IntoIterator<Item = P> + Clone> PitchClassCollection for I {
83 fn pitch_classes(&self) -> Vec<PitchClass> {
84 self.clone().into_iter().map(|p| p.into()).collect()
85 }
86}