rstmt_nrt/impls/
impl_triad_base.rs1use crate::triad::TriadBase;
7
8use crate::traits::{TriadRepr, TriadReprMut, TriadType};
9use crate::types::LPR;
10use num_traits::{Float, FromPrimitive, ToPrimitive, Zero};
11use rstmt_core::{Octave, PitchMod, Transform};
12
13impl<S, T, K> TriadBase<S, K, T>
14where
15 K: TriadType,
16 S: TriadRepr<Elem = T>,
17{
18 pub fn new(chord: S, class: K) -> Self
20 where
21 T: Zero,
22 {
23 Self {
24 chord,
25 class,
26 octave: Octave::zero(),
27 }
28 }
29 pub fn from_root_with_class(root: T, class: K) -> Self
31 where
32 T: Copy + FromPrimitive + Zero + PitchMod<Output = T> + core::ops::Add<Output = T>,
33 {
34 let chord = [
36 root,
37 (root + T::from_usize(class.root()).unwrap()).pmod(),
38 (root + T::from_usize(class.fifth()).unwrap()).pmod(),
39 ];
40 Self {
41 class,
42 chord: S::from_arr(chord),
43 octave: Octave::zero(),
44 }
45 }
46 #[inline]
47 pub fn dynamic(self) -> TriadBase<S, crate::Triads, T> {
49 TriadBase {
50 chord: self.chord,
51 class: crate::Triads::from_class(self.class),
52 octave: self.octave,
53 }
54 }
55 pub const fn chord(&self) -> &S {
57 &self.chord
58 }
59 pub const fn chord_mut(&mut self) -> &mut S {
61 &mut self.chord
62 }
63 pub const fn class(&self) -> &K {
65 &self.class
66 }
67 pub const fn class_mut(&mut self) -> &mut K {
69 &mut self.class
70 }
71 pub const fn octave(&self) -> &Octave<T> {
73 &self.octave
74 }
75 pub const fn octave_mut(&mut self) -> &mut Octave<T> {
76 &mut self.octave
77 }
78 pub fn root(&self) -> &T
80 where
81 S: TriadRepr,
82 {
83 self.chord().root()
84 }
85 pub fn root_mut(&mut self) -> &mut T
87 where
88 S: TriadReprMut,
89 {
90 self.chord_mut().root_mut()
91 }
92 pub fn third(&self) -> &T
94 where
95 S: TriadRepr,
96 {
97 self.chord().third()
98 }
99 pub fn third_mut(&mut self) -> &mut T
101 where
102 S: TriadReprMut,
103 {
104 self.chord_mut().third_mut()
105 }
106 pub fn fifth(&self) -> &T
108 where
109 S: TriadRepr,
110 {
111 self.chord().fifth()
112 }
113 pub fn fifth_mut(&mut self) -> &mut T
115 where
116 S: TriadReprMut,
117 {
118 self.chord_mut().fifth_mut()
119 }
120 pub fn set_chord(&mut self, chord: S) -> &mut Self {
122 self.chord = chord;
123 self
124 }
125 pub fn set_class(&mut self, class: K) -> &mut Self {
127 self.class = class;
128 self
129 }
130 #[inline]
131 pub fn with_chord<S2>(self, chord: S2) -> TriadBase<S2, K>
133 where
134 S2: TriadRepr<Elem = T>,
135 T: Sized,
136 {
137 TriadBase {
138 chord,
139 class: self.class,
140 octave: self.octave,
141 }
142 }
143 #[inline]
144 pub fn with_class<K2>(self, class: K2) -> TriadBase<S, K2>
146 where
147 K2: TriadType,
148 {
149 TriadBase {
150 chord: self.chord,
151 class,
152 octave: self.octave,
153 }
154 }
155 #[inline]
156 pub fn with_octave(self, octave: Octave<T>) -> Self {
157 Self { octave, ..self }
158 }
159 pub fn into_parts(self) -> (S, K) {
161 (self.chord, self.class)
162 }
163 pub fn is_augmented(&self) -> bool {
165 self.class().is_augmented()
166 }
167 pub fn is_diminished(&self) -> bool {
169 self.class().is_diminished()
170 }
171 pub fn is_major(&self) -> bool {
173 self.class().is_major()
174 }
175 pub fn is_minor(&self) -> bool {
177 self.class().is_minor()
178 }
179 pub fn centroid<U>(&self) -> Option<[U; 2]>
181 where
182 T: Copy + ToPrimitive,
183 U: Float + FromPrimitive + ToPrimitive + core::iter::Sum<T>,
184 S: Clone + IntoIterator<Item = T>,
185 {
186 let y = U::from(*self.octave().get())?;
187 let x = self.chord().clone().into_iter().sum::<U>() / U::from_u8(3)?;
188 Some([x, y])
189 }
190 pub fn contains<Q>(&self, note: &Q) -> bool
192 where
193 for<'a> &'a S: IntoIterator<Item = &'a T>,
194 T: PartialEq,
195 Q: core::borrow::Borrow<T>,
196 {
197 self.chord().into_iter().any(|n| n == note.borrow())
198 }
199 #[cfg(feature = "alloc")]
200 pub fn common_tones(&self, other: &Self) -> alloc::vec::Vec<T>
202 where
203 T: Clone + PartialEq,
204 for<'a> &'a S: IntoIterator<Item = &'a T>,
205 {
206 self.chord()
207 .into_iter()
208 .filter(|n| other.contains(n))
209 .cloned()
210 .collect::<alloc::vec::Vec<_>>()
211 }
212 pub fn transform<X, Y>(self, step: X) -> Y
216 where
217 Self: Transform<X, Output = Y>,
218 {
219 <Self as Transform<X>>::transform(self, step)
220 }
221 pub fn leading<Y>(self) -> Y
223 where
224 Self: Transform<LPR, Output = Y>,
225 {
226 self.transform(LPR::Leading)
227 }
228 pub fn parallel<Y>(self) -> Y
230 where
231 Self: Transform<LPR, Output = Y>,
232 {
233 self.transform(LPR::Parallel)
234 }
235 pub fn relative<Y>(self) -> Y
237 where
238 Self: Transform<LPR, Output = Y>,
239 {
240 self.transform(LPR::Relative)
241 }
242 #[cfg(feature = "motion")]
243 pub fn path_finder(&self) -> crate::motion::PathFinder<'_, S, K, T> {
245 crate::motion::PathFinder::new(self)
246 }
247}