1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#![warn(clippy::pedantic, missing_docs, missing_doc_code_examples)]

//! A library for handling tonal pitch classes, keys, intervals, accidentals and
//! alterations. A tonal pitch class (`Tpc`) does not distinguish pitches in
//! different octaves, but it does distinguish different enharmonic spellings of
//! notes, intervals, and keys. This is done based on the "line of fifths"
//! concept.
//! 
//! Distinguishing enharmonic spellings is desirable in several applications:
//! 
//! - In musical notation, where using an incorrect enharmonic spelling harms
//!   legibility
//! - When using other tunings than twelve tone equal temperament (12TET), in
//!   which case notes normally considered enharmonic should actually be played at
//!   different pitches.
//! 
//! Another important type is the `Step`, which represents the fact that G sharp
//! and G flat are written on the same line of the staff. A `Step` combined with
//! a `Key` or `Accidental` gives a `Tpc`.
//! 
//! Using the `Step` type also helps you handle octaves. If you want the F above
//! A flat, for instance, you would compare their `Step`s, see that F has a lower
//! step than A flat, and therefore should be raised an octave.
//! 
//! Arithmetic operations with `Tpc`s and `Interval`s return optional values,
//! because they may result in alterations beyond the domain of the library.
//! Triple sharps/flats or double diminished/augmented intervals are not
//! supported.
//!
//! ## Alteration versus accidental
//!
//! Though they are similar, these two types serve different purposes. An
//! `Alteration` is a relative change that applies to a `Tpc`.
//! An accidental is an absolute change that can only apply to a
//! Step - turning it into a Tpc.
//!
//! # Example
//!
//! It can be used for finding the tonal pitch classes in a chord:
//!
//! ```
//! # use tonality::*;
//! let root = Tpc::Fs;
//! type Chord = Vec<Interval>;
//! let dom7: Chord = {
//!     use Interval::*;
//!     vec![Unison, Maj3, P5, Min7]
//! };
//! let tpcs: Vec<Tpc> = dom7
//!     .iter()
//!     .filter_map(|&interval| root + interval)
//!     .collect();
//! let expected = vec![Tpc::Fs, Tpc::As, Tpc::Cs, Tpc::E];
//! assert_eq!(expected, tpcs);
//! ```

#[doc(inline)]
pub mod accidental;
#[doc(inline)]
pub mod alteration;
#[doc(inline)]
pub mod interval;
#[doc(inline)]
pub mod key;
#[doc(inline)]
pub mod step;
#[doc(inline)]
pub mod tpc;

pub use {
    accidental::Accidental, alteration::Alteration, interval::Interval, key::Key, step::Step,
    tpc::Tpc,
};