Skip to content

Commit

Permalink
Merge 776aaba into f72a068
Browse files Browse the repository at this point in the history
  • Loading branch information
albertms10 committed Jan 21, 2024
2 parents f72a068 + 776aaba commit 904d9e3
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 148 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ for working with music theory concepts through a beautifully crafted API.
- Intervals and qualities
- Notes, frequencies, accidentals, and enharmonic operations
- Scales and scale degrees
- Tonalities, key signatures, and modes
- Keys, key signatures, and modes
- Tuning systems (_work in progress_)

## Usage
Expand Down Expand Up @@ -96,7 +96,7 @@ Note.c.circleOfFifths();
// (flats: [F, B♭, E♭, A♭, D♭, G♭], sharps: [G, D, A, E, B, F♯])
```

### Tonalities
### Keys

Create a `Tonality` or get it from a given `Note`:

Expand All @@ -108,8 +108,8 @@ Note.a.flat.major; // A♭ major
Know its `KeySignature`:

```dart
Note.d.major.keySignature; // 2 (F♯ C♯)
Note.e.flat.minor.keySignature; // -6 (B♭ E♭ A♭ D♭ G♭ C♭)
Note.d.major.signature; // 2 (F♯ C♯)
Note.e.flat.minor.signature; // -6 (B♭ E♭ A♭ D♭ G♭ C♭)
```

And its relative `Tonality`:
Expand All @@ -129,21 +129,21 @@ KeySignature([Note.b.flat, Note.e.flat]); // -2 (B♭ E♭)
KeySignature([Note.g.sharp, Note.a.sharp]); // null (G♯ A♯)
```

And know its tonalities:
And know its `Key`s:

```dart
KeySignature([Note.f.sharp]).tonalities!.major; // G major
KeySignature.empty.tonalities!.minor; // A minor
KeySignature([Note.f.sharp]).keys!.major; // G major
KeySignature.empty.keys!.minor; // A minor
```

Non-canonical key signatures are also supported, although they
return `null` when asked about their fifths distance or tonalities:
return `null` when asked about their fifths distance or keys:

```dart
KeySignature([Note.a.flat])
..isCanonical // false
..distance // null
..tonalities; // null
..keys; // null
```

### Modes
Expand Down
14 changes: 7 additions & 7 deletions example/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ void main() {
Note.c.circleOfFifths();
// (flats: [F, B♭, E♭, A♭, D♭, G♭], sharps: [G, D, A, E, B, F♯])

// Tonalities
const Tonality(Note.e, TonalMode.minor); // E minor
// Keys
const Key(Note.e, TonalMode.minor); // E minor
Note.a.flat.major; // A♭ major

Note.d.major.keySignature; // 2 (F♯ C♯)
Note.e.flat.minor.keySignature; // -6 (B♭ E♭ A♭ D♭ G♭ C♭)
Note.d.major.signature; // 2 (F♯ C♯)
Note.e.flat.minor.signature; // -6 (B♭ E♭ A♭ D♭ G♭ C♭)

Note.d.major.relative; // B minor
Note.c.minor.relative; // E♭ major
Expand All @@ -51,13 +51,13 @@ void main() {
KeySignature([Note.b.flat, Note.e.flat]); // -2 (B♭ E♭)
KeySignature([Note.g.sharp, Note.a.sharp]); // null (G♯ A♯)

KeySignature([Note.f.sharp]).tonalities!.major; // G major
KeySignature.empty.tonalities!.minor; // A minor
KeySignature([Note.f.sharp]).keys!.major; // G major
KeySignature.empty.keys!.minor; // A minor

KeySignature([Note.a.flat])
..isCanonical // false
..distance // null
..tonalities; // null
..keys; // null

// Modes
TonalMode.minor.scale; // ScalePattern.minor
Expand Down
6 changes: 3 additions & 3 deletions lib/music_notes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ part 'src/harmony/harmonic_function.dart';
part 'src/interval/interval.dart';
part 'src/interval/interval_class.dart';
part 'src/interval/quality.dart';
part 'src/key/key.dart';
part 'src/key/key_signature.dart';
part 'src/key/mode.dart';
part 'src/music.dart';
part 'src/note/accidental.dart';
part 'src/note/base_note.dart';
Expand All @@ -34,9 +37,6 @@ part 'src/scalable.dart';
part 'src/scale/scale.dart';
part 'src/scale/scale_degree.dart';
part 'src/scale/scale_pattern.dart';
part 'src/tonality/key_signature.dart';
part 'src/tonality/mode.dart';
part 'src/tonality/tonality.dart';
part 'src/transposable.dart';
part 'src/tuning/cent.dart';
part 'src/tuning/equal_temperament.dart';
Expand Down
48 changes: 24 additions & 24 deletions lib/src/tonality/tonality.dart → lib/src/key/key.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
part of '../../music_notes.dart';

/// A musical tonality, also known as key.
/// A musical key or tonality.
///
/// See [Key (music)](https://en.wikipedia.org/wiki/Key_(music)).
///
Expand All @@ -10,33 +10,33 @@ part of '../../music_notes.dart';
/// * [Mode].
/// * [KeySignature].
@immutable
final class Tonality implements Comparable<Tonality> {
/// The tonal center representing this [Tonality].
final class Key implements Comparable<Key> {
/// The tonal center representing this [Key].
final Note note;

/// The mode representing this [Tonality].
/// The mode representing this [Key].
final TonalMode mode;

/// Creates a new [Tonality] from [note] and [mode].
const Tonality(this.note, this.mode);
/// Creates a new [Key] from [note] and [mode].
const Key(this.note, this.mode);

/// Returns the [TonalMode.major] or [TonalMode.minor] relative [Tonality]
/// of this [Tonality].
/// Returns the [TonalMode.major] or [TonalMode.minor] relative [Key]
/// of this [Key].
///
/// Example:
/// ```dart
/// Note.d.minor.relative == Note.f.major
/// Note.b.flat.major.relative == Note.g.minor
/// ```
Tonality get relative => Tonality(
Key get relative => Key(
note.transposeBy(
Interval.m3.descending(isDescending: mode == TonalMode.major),
),
mode.opposite,
);

/// Returns the [TonalMode.major] or [TonalMode.minor] parallel [Tonality]
/// of this [Tonality].
/// Returns the [TonalMode.major] or [TonalMode.minor] parallel [Key]
/// of this [Key].
///
/// See [Parallel key](https://en.wikipedia.org/wiki/Parallel_key).
///
Expand All @@ -45,21 +45,21 @@ final class Tonality implements Comparable<Tonality> {
/// Note.d.minor.parallel == Note.d.major
/// Note.b.flat.major.parallel == Note.b.flat.minor
/// ```
Tonality get parallel => Tonality(note, mode.opposite);
Key get parallel => Key(note, mode.opposite);

/// Returns the [KeySignature] of this [Tonality].
/// Returns the [KeySignature] of this [Key].
///
/// Example:
/// ```dart
/// Note.c.major.keySignature == KeySignature.empty
/// Note.a.major.keySignature == KeySignature.fromDistance(3)
/// Note.g.flat.major.keySignature == KeySignature.fromDistance(-6)
/// Note.c.major.signature == KeySignature.empty
/// Note.a.major.signature == KeySignature.fromDistance(3)
/// Note.g.flat.major.signature == KeySignature.fromDistance(-6)
/// ```
KeySignature get keySignature => KeySignature.fromDistance(
KeySignature.empty.tonality(mode)!.note.fifthsDistanceWith(note),
KeySignature get signature => KeySignature.fromDistance(
KeySignature.empty.key(mode)!.note.fifthsDistanceWith(note),
);

/// Whether this [Tonality] is theoretical, whose [keySignature] would have
/// Whether this [Key] is theoretical, whose [signature] would have
/// at least one [Accidental.doubleFlat] or [Accidental.doubleSharp].
///
/// See [Theoretical key](https://en.wikipedia.org/wiki/Theoretical_key).
Expand All @@ -70,9 +70,9 @@ final class Tonality implements Comparable<Tonality> {
/// Note.g.sharp.major.isTheoretical == true
/// Note.f.flat.minor.isTheoretical == true
/// ```
bool get isTheoretical => keySignature.distance!.abs() > 7;
bool get isTheoretical => signature.distance!.abs() > 7;

/// Returns the scale notes of this [Tonality].
/// Returns the scale notes of this [Key].
///
/// Example:
/// ```dart
Expand All @@ -86,17 +86,17 @@ final class Tonality implements Comparable<Tonality> {

@override
String toString({NoteNotation system = NoteNotation.english}) =>
system.tonality(this);
system.key(this);

@override
bool operator ==(Object other) =>
other is Tonality && note == other.note && mode == other.mode;
other is Key && note == other.note && mode == other.mode;

@override
int get hashCode => Object.hash(note, mode);

@override
int compareTo(Tonality other) => compareMultiple([
int compareTo(Key other) => compareMultiple([
() => note.compareTo(other.note),
() => mode.name.compareTo(other.mode.name),
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ part of '../../music_notes.dart';
/// ---
/// See also:
/// * [Note].
/// * [Tonality].
/// * [Key].
@immutable
final class KeySignature implements Comparable<KeySignature> {
/// The set of [Note] that define this [KeySignature], which may include
Expand Down Expand Up @@ -91,7 +91,7 @@ final class KeySignature implements Comparable<KeySignature> {
: null;
}

/// Whether this [KeySignature] is canonical (has an associated [Tonality]).
/// Whether this [KeySignature] is canonical (has an associated [Key]).
///
/// Cancellation [Accidental.natural]s are ignored.
///
Expand All @@ -102,30 +102,29 @@ final class KeySignature implements Comparable<KeySignature> {
/// ```
bool get isCanonical => distance != null;

/// Returns the [Tonality] that corresponds to this [KeySignature] from
/// Returns the [Key] that corresponds to this [KeySignature] from
/// [mode].
///
/// Example:
/// ```dart
/// KeySignature.empty.tonality(TonalMode.major) == Note.c.major
/// KeySignature.fromDistance(-2).tonality(TonalMode.minor) == Note.g.minor
/// KeySignature.empty.key(TonalMode.major) == Note.c.major
/// KeySignature.fromDistance(-2).key(TonalMode.minor) == Note.g.minor
/// ```
Tonality? tonality(TonalMode mode) => switch (mode) {
TonalMode.major => tonalities?.major,
TonalMode.minor => tonalities?.minor,
Key? key(TonalMode mode) => switch (mode) {
TonalMode.major => keys?.major,
TonalMode.minor => keys?.minor,
};

/// Returns a [Set] with the two tonalities that are defined
/// by this [KeySignature].
/// Returns a [Set] with the two keys that are defined by this [KeySignature].
///
/// Example:
/// ```dart
/// KeySignature.fromDistance(-2).tonalities == (
/// KeySignature.fromDistance(-2).keys == (
/// major: Note.b.flat.major,
/// minor: Note.g.minor,
/// )
/// ```
({Tonality major, Tonality minor})? get tonalities {
({Key major, Key minor})? get keys {
final distance = this.distance;
if (distance == null) return null;

Expand Down
2 changes: 1 addition & 1 deletion lib/src/tonality/mode.dart → lib/src/key/mode.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ part of '../../music_notes.dart';
///
/// ---
/// See also:
/// * [Tonality].
/// * [Key].
/// * [ScalePattern].
sealed class Mode implements Enum, Comparable<Mode> {
/// The [ScalePattern] related to this [Mode].
Expand Down
34 changes: 17 additions & 17 deletions lib/src/note/note.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ part of '../../music_notes.dart';
/// * [Accidental].
/// * [Pitch].
/// * [KeySignature].
/// * [Tonality].
/// * [Key].
@immutable
final class Note extends Scalable<Note> implements Comparable<Note> {
/// The base note that defines this [Note].
Expand Down Expand Up @@ -130,23 +130,23 @@ final class Note extends Scalable<Note> implements Comparable<Note> {
/// ```
Note get natural => Note(baseNote);

/// Returns the [TonalMode.major] [Tonality] from this [Note].
/// Returns the [TonalMode.major] [Key] from this [Note].
///
/// Example:
/// ```dart
/// Note.c.major == const Tonality(Note.c, TonalMode.major)
/// Note.e.flat.major == Tonality(Note.e.flat, TonalMode.major)
/// Note.c.major == const Key(Note.c, TonalMode.major)
/// Note.e.flat.major == Key(Note.e.flat, TonalMode.major)
/// ```
Tonality get major => Tonality(this, TonalMode.major);
Key get major => Key(this, TonalMode.major);

/// Returns the [TonalMode.minor] [Tonality] from this [Note].
/// Returns the [TonalMode.minor] [Key] from this [Note].
///
/// Example:
/// ```dart
/// Note.d.minor == const Tonality(Note.d, TonalMode.minor)
/// Note.g.sharp.minor == Tonality(Note.g.sharp, TonalMode.minor)
/// Note.d.minor == const Key(Note.d, TonalMode.minor)
/// Note.g.sharp.minor == Key(Note.g.sharp, TonalMode.minor)
/// ```
Tonality get minor => Tonality(this, TonalMode.minor);
Key get minor => Key(this, TonalMode.minor);

/// Returns the [ChordPattern.diminishedTriad] on this [Note].
///
Expand Down Expand Up @@ -453,10 +453,10 @@ abstract class NoteNotation {
/// Returns the string notation for [tonalMode].
String tonalMode(TonalMode tonalMode);

/// Returns the string notation for [tonality].
String tonality(Tonality tonality) {
final note = tonality.note.toString(system: this);
final mode = tonality.mode.toString(system: this);
/// Returns the string notation for [key].
String key(Key key) {
final note = key.note.toString(system: this);
final mode = key.mode.toString(system: this);

return '$note $mode';
}
Expand Down Expand Up @@ -518,10 +518,10 @@ class GermanNoteNotation extends NoteNotation {
};

@override
String tonality(Tonality tonality) {
final note = tonality.note.toString(system: this);
final mode = tonality.mode.toString(system: this);
final casedNote = switch (tonality.mode) {
String key(Key key) {
final note = key.note.toString(system: this);
final mode = key.mode.toString(system: this);
final casedNote = switch (key.mode) {
TonalMode.minor => note.toLowerCase(),
_ => note,
};
Expand Down
Loading

0 comments on commit 904d9e3

Please sign in to comment.