Skip to main content

klib/core/
interval.rs

1//! A module for working with intervals.
2
3use std::fmt::{Display, Error, Formatter};
4
5#[cfg(feature = "wasm")]
6use wasm_bindgen::prelude::*;
7
8#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10
11use crate::core::octave::{HasOctave, Octave};
12
13// Traits.
14
15/// A trait for types that have a list of intervals.
16pub trait HasIntervals {
17    /// Returns the intervals of the type.
18    fn intervals(&self) -> &'static [Interval];
19}
20
21/// A trait for types that have an enharmonic distance.
22pub trait HasEnharmonicDistance {
23    /// Returns the enharmonic distance of the type (most likely an interval).
24    ///
25    /// Due to the nature of enharmonic intervals, the distance is always an integer,
26    /// and it looks a bit funky.  Basically, using the circle of fifths, the distance
27    /// is the number of fifths between the two notes.  For example, a perfect fifth
28    /// is 1 fifth away, and a major second is always two fifths away
29    ///  (look at the implementation).  This preserves enharmonic correctness.
30    fn enharmonic_distance(&self) -> i8;
31}
32
33/// A trait for types that can be "reduced" to a single "frame" (usually an interval, and usually within an octave).
34pub trait CanReduceFrame {
35    /// Returns the reduced frame of the type.
36    fn reduce_frame(self) -> Self;
37}
38
39// Enum.
40
41/// An enum representing the interval between two notes.
42#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Ord, PartialOrd)]
43#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
44#[repr(u8)]
45#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = KordInterval))]
46pub enum Interval {
47    /// A perfect unison interval.
48    PerfectUnison,
49    /// A diminished second interval.
50    DiminishedSecond,
51
52    /// An augmented unison interval.
53    AugmentedUnison,
54    /// A minor second interval.
55    MinorSecond,
56
57    /// A major second interval.
58    MajorSecond,
59    /// A diminished third interval.
60    DiminishedThird,
61
62    /// An augmented second interval.
63    AugmentedSecond,
64    /// A minor third interval.
65    MinorThird,
66
67    /// A major third interval.
68    MajorThird,
69    /// A diminished fourth interval.
70    DiminishedFourth,
71
72    /// An augmented third interval.
73    AugmentedThird,
74    /// A perfect fourth interval.
75    PerfectFourth,
76
77    /// An augmented fourth interval.
78    AugmentedFourth,
79    /// A diminished fifth interval.
80    DiminishedFifth,
81
82    /// A perfect fifth interval.
83    PerfectFifth,
84    /// A diminished sixth interval.
85    DiminishedSixth,
86
87    /// An augmented fifth interval.
88    AugmentedFifth,
89    /// A minor sixth interval.
90    MinorSixth,
91
92    /// A major sixth interval.
93    MajorSixth,
94    /// A diminished seventh interval.
95    DiminishedSeventh,
96
97    /// An augmented sixth interval.
98    AugmentedSixth,
99    /// A minor seventh interval.
100    MinorSeventh,
101
102    /// A major seventh interval.
103    MajorSeventh,
104    /// A diminished octave interval.
105    DiminishedOctave,
106
107    /// An augmented seventh interval.
108    AugmentedSeventh,
109    /// A perfect octave interval.
110    PerfectOctave,
111
112    /// An minor ninth interval.
113    MinorNinth,
114    /// A major ninth interval.
115    MajorNinth,
116    /// An augmented ninth interval.
117    AugmentedNinth,
118
119    /// A diminished eleventh interval.
120    DiminishedEleventh,
121    /// A perfect eleventh interval.
122    PerfectEleventh,
123    /// An augmented eleventh interval.
124    AugmentedEleventh,
125
126    /// A minor thirteenth interval.
127    MinorThirteenth,
128    /// A major thirteenth interval.
129    MajorThirteenth,
130    /// An augmented thirteenth interval.
131    AugmentedThirteenth,
132
133    /// A perfect octave and perfect fifth interval.
134    PerfectOctaveAndPerfectFifth,
135    /// Two perfect octaves.
136    TwoPerfectOctaves,
137    /// Two perfect octaves and a major third.
138    TwoPerfectOctavesAndMajorThird,
139    /// Two perfect octaves and a perfect fifth.
140    TwoPerfectOctavesAndPerfectFifth,
141    /// Two perfect octaves and a minor sixth.
142    TwoPerfectOctavesAndMinorSeventh,
143    /// Three perfect octaves.
144    ThreePerfectOctaves,
145    /// Three perfect octaves and a major second.
146    ThreePerfectOctavesAndMajorSecond,
147    /// Three perfect octaves and a major third.
148    ThreePerfectOctavesAndMajorThird,
149    /// Three perfect octaves and an augmented fourth.
150    ThreePerfectOctavesAndAugmentedFourth,
151    /// Three perfect octaves and a perfect fifth.
152    ThreePerfectOctavesAndPerfectFifth,
153    /// Three perfect octaves and a minor sixth.
154    ThreePerfectOctavesAndMinorSixth,
155    /// Three perfect octaves and a minor seventh.
156    ThreePerfectOctavesAndMinorSeventh,
157    /// Three perfect octaves and a major seventh.
158    ThreePerfectOctavesAndMajorSeventh,
159}
160
161// Impls.
162
163impl HasEnharmonicDistance for Interval {
164    fn enharmonic_distance(&self) -> i8 {
165        match self {
166            Interval::PerfectUnison => 0,
167            Interval::DiminishedSecond => -12,
168
169            Interval::AugmentedUnison => 7,
170            Interval::MinorSecond => -5,
171
172            Interval::MajorSecond => 2,
173            Interval::DiminishedThird => -10,
174
175            Interval::AugmentedSecond => 9,
176            Interval::MinorThird => -3,
177
178            Interval::MajorThird => 4,
179            Interval::DiminishedFourth => -8,
180
181            Interval::AugmentedThird => 11,
182            Interval::PerfectFourth => -1,
183
184            Interval::AugmentedFourth => 6,
185            Interval::DiminishedFifth => -6,
186
187            Interval::PerfectFifth => 1,
188            Interval::DiminishedSixth => -11,
189
190            Interval::AugmentedFifth => 8,
191            Interval::MinorSixth => -4,
192
193            Interval::MajorSixth => 3,
194            Interval::DiminishedSeventh => -9,
195
196            Interval::AugmentedSixth => 10,
197            Interval::MinorSeventh => -2,
198
199            Interval::MajorSeventh => 5,
200            Interval::DiminishedOctave => -7,
201
202            Interval::AugmentedSeventh => 12,
203            Interval::PerfectOctave => 0,
204
205            Interval::MinorNinth => -5,
206            Interval::MajorNinth => 2,
207            Interval::AugmentedNinth => 9,
208
209            Interval::DiminishedEleventh => -8,
210            Interval::PerfectEleventh => -1,
211            Interval::AugmentedEleventh => 6,
212
213            Interval::MinorThirteenth => -4,
214            Interval::MajorThirteenth => 3,
215            Interval::AugmentedThirteenth => 10,
216
217            Interval::PerfectOctaveAndPerfectFifth => 1,
218            Interval::TwoPerfectOctaves => 0,
219            Interval::TwoPerfectOctavesAndMajorThird => 4,
220            Interval::TwoPerfectOctavesAndPerfectFifth => 1,
221            Interval::TwoPerfectOctavesAndMinorSeventh => -2,
222            Interval::ThreePerfectOctaves => 0,
223            Interval::ThreePerfectOctavesAndMajorSecond => 2,
224            Interval::ThreePerfectOctavesAndMajorThird => 4,
225            Interval::ThreePerfectOctavesAndAugmentedFourth => 6,
226            Interval::ThreePerfectOctavesAndPerfectFifth => 1,
227            Interval::ThreePerfectOctavesAndMinorSixth => -4,
228            Interval::ThreePerfectOctavesAndMinorSeventh => -2,
229            Interval::ThreePerfectOctavesAndMajorSeventh => 5,
230        }
231    }
232}
233
234impl HasOctave for Interval {
235    fn octave(&self) -> Octave {
236        match self {
237            Interval::PerfectUnison => Octave::Zero,
238            Interval::DiminishedSecond => Octave::Zero,
239
240            Interval::AugmentedUnison => Octave::Zero,
241            Interval::MinorSecond => Octave::Zero,
242
243            Interval::MajorSecond => Octave::Zero,
244            Interval::DiminishedThird => Octave::Zero,
245
246            Interval::AugmentedSecond => Octave::Zero,
247            Interval::MinorThird => Octave::Zero,
248
249            Interval::MajorThird => Octave::Zero,
250            Interval::DiminishedFourth => Octave::Zero,
251
252            Interval::AugmentedThird => Octave::Zero,
253            Interval::PerfectFourth => Octave::Zero,
254
255            Interval::AugmentedFourth => Octave::Zero,
256            Interval::DiminishedFifth => Octave::Zero,
257
258            Interval::PerfectFifth => Octave::Zero,
259            Interval::DiminishedSixth => Octave::Zero,
260
261            Interval::AugmentedFifth => Octave::Zero,
262            Interval::MinorSixth => Octave::Zero,
263
264            Interval::MajorSixth => Octave::Zero,
265            Interval::DiminishedSeventh => Octave::Zero,
266
267            Interval::AugmentedSixth => Octave::Zero,
268            Interval::MinorSeventh => Octave::Zero,
269
270            Interval::MajorSeventh => Octave::Zero,
271            Interval::DiminishedOctave => Octave::Zero,
272
273            Interval::AugmentedSeventh => Octave::One,
274            Interval::PerfectOctave => Octave::One,
275
276            Interval::MinorNinth => Octave::One,
277            Interval::MajorNinth => Octave::One,
278            Interval::AugmentedNinth => Octave::One,
279
280            Interval::DiminishedEleventh => Octave::One,
281            Interval::PerfectEleventh => Octave::One,
282            Interval::AugmentedEleventh => Octave::One,
283
284            Interval::MinorThirteenth => Octave::One,
285            Interval::MajorThirteenth => Octave::One,
286            Interval::AugmentedThirteenth => Octave::One,
287
288            Interval::PerfectOctaveAndPerfectFifth => Octave::One,
289            Interval::TwoPerfectOctaves => Octave::Two,
290            Interval::TwoPerfectOctavesAndMajorThird => Octave::Two,
291            Interval::TwoPerfectOctavesAndPerfectFifth => Octave::Two,
292            Interval::TwoPerfectOctavesAndMinorSeventh => Octave::Two,
293            Interval::ThreePerfectOctaves => Octave::Three,
294            Interval::ThreePerfectOctavesAndMajorSecond => Octave::Three,
295            Interval::ThreePerfectOctavesAndMajorThird => Octave::Three,
296            Interval::ThreePerfectOctavesAndAugmentedFourth => Octave::Three,
297            Interval::ThreePerfectOctavesAndPerfectFifth => Octave::Three,
298            Interval::ThreePerfectOctavesAndMinorSixth => Octave::Three,
299            Interval::ThreePerfectOctavesAndMinorSeventh => Octave::Three,
300            Interval::ThreePerfectOctavesAndMajorSeventh => Octave::Three,
301        }
302    }
303}
304
305impl Display for Interval {
306    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
307        match self {
308            Interval::PerfectUnison => write!(f, "PerfectUnison"),
309            Interval::DiminishedSecond => write!(f, "DiminishedSecond"),
310
311            Interval::AugmentedUnison => write!(f, "AugmentedUnison"),
312            Interval::MinorSecond => write!(f, "MinorSecond"),
313
314            Interval::MajorSecond => write!(f, "MajorSecond"),
315            Interval::DiminishedThird => write!(f, "DiminishedThird"),
316
317            Interval::AugmentedSecond => write!(f, "AugmentedSecond"),
318            Interval::MinorThird => write!(f, "MinorThird"),
319
320            Interval::MajorThird => write!(f, "MajorThird"),
321            Interval::DiminishedFourth => write!(f, "DiminishedFourth"),
322
323            Interval::AugmentedThird => write!(f, "AugmentedThird"),
324            Interval::PerfectFourth => write!(f, "PerfectFourth"),
325
326            Interval::AugmentedFourth => write!(f, "AugmentedFourth"),
327            Interval::DiminishedFifth => write!(f, "DiminishedFifth"),
328
329            Interval::PerfectFifth => write!(f, "PerfectFifth"),
330            Interval::DiminishedSixth => write!(f, "DiminishedSixth"),
331
332            Interval::AugmentedFifth => write!(f, "AugmentedFifth"),
333            Interval::MinorSixth => write!(f, "MinorSixth"),
334
335            Interval::MajorSixth => write!(f, "MajorSixth"),
336            Interval::DiminishedSeventh => write!(f, "DiminishedSeventh"),
337
338            Interval::AugmentedSixth => write!(f, "AugmentedSixth"),
339            Interval::MinorSeventh => write!(f, "MinorSeventh"),
340
341            Interval::MajorSeventh => write!(f, "MajorSeventh"),
342            Interval::DiminishedOctave => write!(f, "DiminishedOctave"),
343
344            Interval::AugmentedSeventh => write!(f, "AugmentedSeventh"),
345            Interval::PerfectOctave => write!(f, "PerfectOctave"),
346
347            Interval::MinorNinth => write!(f, "MinorNinth"),
348            Interval::MajorNinth => write!(f, "MajorNinth"),
349            Interval::AugmentedNinth => write!(f, "AugmentedNinth"),
350
351            Interval::DiminishedEleventh => write!(f, "DiminishedEleventh"),
352            Interval::PerfectEleventh => write!(f, "PerfectEleventh"),
353            Interval::AugmentedEleventh => write!(f, "AugmentedEleventh"),
354
355            Interval::MinorThirteenth => write!(f, "MinorThirteenth"),
356            Interval::MajorThirteenth => write!(f, "MajorThirteenth"),
357            Interval::AugmentedThirteenth => write!(f, "AugmentedThirteenth"),
358
359            Interval::PerfectOctaveAndPerfectFifth => write!(f, "PerfectOctaveAndPerfectFifth"),
360            Interval::TwoPerfectOctaves => write!(f, "TwoPerfectOctaves"),
361            Interval::TwoPerfectOctavesAndMajorThird => write!(f, "TwoPerfectOctavesAndMajorThird"),
362            Interval::TwoPerfectOctavesAndPerfectFifth => write!(f, "TwoPerfectOctavesAndPerfectFifth"),
363            Interval::TwoPerfectOctavesAndMinorSeventh => write!(f, "TwoPerfectOctavesAndMinorSeventh"),
364            Interval::ThreePerfectOctaves => write!(f, "ThreePerfectOctaves"),
365            Interval::ThreePerfectOctavesAndMajorSecond => write!(f, "ThreePerfectOctavesAndMajorSecond"),
366            Interval::ThreePerfectOctavesAndMajorThird => write!(f, "ThreePerfectOctavesAndMajorThird"),
367            Interval::ThreePerfectOctavesAndAugmentedFourth => write!(f, "ThreePerfectOctavesAndAugmentedFourth"),
368            Interval::ThreePerfectOctavesAndPerfectFifth => write!(f, "ThreePerfectOctavesAndPerfectFifth"),
369            Interval::ThreePerfectOctavesAndMinorSixth => write!(f, "ThreePerfectOctavesAndMinorSixth"),
370            Interval::ThreePerfectOctavesAndMinorSeventh => write!(f, "ThreePerfectOctavesAndMinorSeventh"),
371            Interval::ThreePerfectOctavesAndMajorSeventh => write!(f, "ThreePerfectOctavesAndMajorSeventh"),
372        }
373    }
374}
375
376// Statics.
377
378/// All known [`Interval`]s.
379pub static ALL_INTERVALS: [Interval; 48] = [
380    Interval::PerfectUnison,
381    Interval::DiminishedSecond,
382    Interval::AugmentedUnison,
383    Interval::MinorSecond,
384    Interval::MajorSecond,
385    Interval::DiminishedThird,
386    Interval::AugmentedSecond,
387    Interval::MinorThird,
388    Interval::MajorThird,
389    Interval::DiminishedFourth,
390    Interval::AugmentedThird,
391    Interval::PerfectFourth,
392    Interval::AugmentedFourth,
393    Interval::DiminishedFifth,
394    Interval::PerfectFifth,
395    Interval::DiminishedSixth,
396    Interval::AugmentedFifth,
397    Interval::MinorSixth,
398    Interval::MajorSixth,
399    Interval::DiminishedSeventh,
400    Interval::AugmentedSixth,
401    Interval::MinorSeventh,
402    Interval::MajorSeventh,
403    Interval::DiminishedOctave,
404    Interval::AugmentedSeventh,
405    Interval::PerfectOctave,
406    Interval::MinorNinth,
407    Interval::MajorNinth,
408    Interval::AugmentedNinth,
409    Interval::DiminishedEleventh,
410    Interval::PerfectEleventh,
411    Interval::AugmentedEleventh,
412    Interval::MinorThirteenth,
413    Interval::MajorThirteenth,
414    Interval::AugmentedThirteenth,
415    Interval::PerfectOctaveAndPerfectFifth,
416    Interval::TwoPerfectOctaves,
417    Interval::TwoPerfectOctavesAndMajorThird,
418    Interval::TwoPerfectOctavesAndPerfectFifth,
419    Interval::TwoPerfectOctavesAndMinorSeventh,
420    Interval::ThreePerfectOctaves,
421    Interval::ThreePerfectOctavesAndMajorSecond,
422    Interval::ThreePerfectOctavesAndMajorThird,
423    Interval::ThreePerfectOctavesAndAugmentedFourth,
424    Interval::ThreePerfectOctavesAndPerfectFifth,
425    Interval::ThreePerfectOctavesAndMinorSixth,
426    Interval::ThreePerfectOctavesAndMinorSeventh,
427    Interval::ThreePerfectOctavesAndMajorSeventh,
428];
429
430/// The primary (first 13) harmonic series expressed as [`Interval`]s.
431pub static PRIMARY_HARMONIC_SERIES: [Interval; 13] = [
432    Interval::PerfectOctave,
433    Interval::PerfectOctaveAndPerfectFifth,
434    Interval::TwoPerfectOctaves,
435    Interval::TwoPerfectOctavesAndMajorThird,
436    Interval::TwoPerfectOctavesAndPerfectFifth,
437    Interval::TwoPerfectOctavesAndMinorSeventh,
438    Interval::ThreePerfectOctavesAndMajorSecond,
439    Interval::ThreePerfectOctavesAndMajorThird,
440    Interval::ThreePerfectOctavesAndAugmentedFourth,
441    Interval::ThreePerfectOctavesAndPerfectFifth,
442    Interval::ThreePerfectOctavesAndMinorSixth,
443    Interval::ThreePerfectOctavesAndMinorSeventh,
444    Interval::ThreePerfectOctavesAndMajorSeventh,
445];