Skip to content

Commit

Permalink
refactor!(key_signature): rewrite keys method to return a Map
Browse files Browse the repository at this point in the history
  • Loading branch information
albertms10 committed Feb 21, 2024
1 parent 6b2e04a commit 94247c1
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 97 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ KeySignature([Note.g.sharp, Note.a.sharp]); // null (G♯ A♯)
And know its `Key`s:

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

Non-canonical key signatures are also supported, although they
Expand Down
4 changes: 2 additions & 2 deletions example/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ 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]).keys!.major; // G major
KeySignature.empty.keys!.minor; // A minor
KeySignature([Note.f.sharp]).keys[TonalMode.major]; // G major
KeySignature.empty.keys[TonalMode.minor]; // A minor

KeySignature([Note.a.flat])
..isCanonical // false
Expand Down
2 changes: 1 addition & 1 deletion lib/src/key/key.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ final class Key implements Comparable<Key> {
/// Note.g.flat.major.signature == KeySignature.fromDistance(-6)
/// ```
KeySignature get signature => KeySignature.fromDistance(
KeySignature.empty.key(mode)!.note.fifthsDistanceWith(note),
KeySignature.empty.keys[mode]!.note.fifthsDistanceWith(note),
);

/// Whether this [Key] is theoretical, whose [signature] would have
Expand Down
27 changes: 7 additions & 20 deletions lib/src/key/key_signature.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,36 +112,23 @@ final class KeySignature implements Comparable<KeySignature> {
/// ```
bool get isCanonical => distance != null;

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

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

final rootNote = Interval.P5.circleFrom(Note.c, distance: distance).last;
final major = rootNote.major;

return (major: major, minor: major.relative);
return {TonalMode.major: major, TonalMode.minor: major.relative};
}

static const _noteNotation = EnglishNoteNotation(showNatural: true);
Expand Down
130 changes: 58 additions & 72 deletions test/src/key/key_signature_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -121,144 +121,130 @@ void main() {
});
});

group('.key()', () {
test('returns the Key from TonalMode', () {
expect(
KeySignature.fromDistance(-4).key(TonalMode.major),
Note.a.flat.major,
);
expect(
KeySignature.fromDistance(-4).key(TonalMode.minor),
Note.f.minor,
);
expect(
KeySignature.fromDistance(-2).key(TonalMode.major),
Note.b.flat.major,
);
expect(
KeySignature.fromDistance(-2).key(TonalMode.minor),
Note.g.minor,
);
expect(KeySignature.empty.key(TonalMode.major), Note.c.major);
expect(KeySignature.empty.key(TonalMode.minor), Note.a.minor);
expect(
KeySignature.fromDistance(1).key(TonalMode.major),
Note.g.major,
);
expect(
KeySignature.fromDistance(1).key(TonalMode.minor),
Note.e.minor,
);
expect(
KeySignature.fromDistance(5).key(TonalMode.major),
Note.b.major,
);
expect(
KeySignature.fromDistance(5).key(TonalMode.minor),
Note.g.sharp.minor,
);
});

test('returns null when this KeySignature is not canonical', () {
expect(KeySignature([Note.c.flat]).key(TonalMode.major), isNull);
expect(
KeySignature([Note.f.sharp, Note.e.sharp]).key(TonalMode.minor),
isNull,
);
});
});

group('.keys', () {
test('returns the Keys for this KeySignature', () {
test('returns the TonalMode to Keys Map for this KeySignature', () {
expect(
KeySignature.fromDistance(-10).keys,
(major: Note.e.flat.flat.major, minor: Note.c.flat.minor),
{
TonalMode.major: Note.e.flat.flat.major,
TonalMode.minor: Note.c.flat.minor,
},
);
expect(
KeySignature.fromDistance(-9).keys,
(major: Note.b.flat.flat.major, minor: Note.g.flat.minor),
{
TonalMode.major: Note.b.flat.flat.major,
TonalMode.minor: Note.g.flat.minor,
},
);
expect(
KeySignature.fromDistance(-8).keys,
(major: Note.f.flat.major, minor: Note.d.flat.minor),
{
TonalMode.major: Note.f.flat.major,
TonalMode.minor: Note.d.flat.minor,
},
);
expect(
KeySignature.fromDistance(-7).keys,
(major: Note.c.flat.major, minor: Note.a.flat.minor),
{
TonalMode.major: Note.c.flat.major,
TonalMode.minor: Note.a.flat.minor,
},
);
expect(
KeySignature.fromDistance(-6).keys,
(major: Note.g.flat.major, minor: Note.e.flat.minor),
{
TonalMode.major: Note.g.flat.major,
TonalMode.minor: Note.e.flat.minor,
},
);
expect(
KeySignature.fromDistance(-5).keys,
(major: Note.d.flat.major, minor: Note.b.flat.minor),
{
TonalMode.major: Note.d.flat.major,
TonalMode.minor: Note.b.flat.minor,
},
);
expect(
KeySignature.fromDistance(-4).keys,
(major: Note.a.flat.major, minor: Note.f.minor),
{TonalMode.major: Note.a.flat.major, TonalMode.minor: Note.f.minor},
);
expect(
KeySignature.fromDistance(-3).keys,
(major: Note.e.flat.major, minor: Note.c.minor),
{TonalMode.major: Note.e.flat.major, TonalMode.minor: Note.c.minor},
);
expect(
KeySignature.fromDistance(-2).keys,
(major: Note.b.flat.major, minor: Note.g.minor),
{TonalMode.major: Note.b.flat.major, TonalMode.minor: Note.g.minor},
);
expect(
KeySignature.fromDistance(-1).keys,
(major: Note.f.major, minor: Note.d.minor),
{TonalMode.major: Note.f.major, TonalMode.minor: Note.d.minor},
);
expect(
KeySignature.empty.keys,
(major: Note.c.major, minor: Note.a.minor),
{TonalMode.major: Note.c.major, TonalMode.minor: Note.a.minor},
);
expect(
KeySignature.fromDistance(1).keys,
(major: Note.g.major, minor: Note.e.minor),
{TonalMode.major: Note.g.major, TonalMode.minor: Note.e.minor},
);
expect(
KeySignature.fromDistance(2).keys,
(major: Note.d.major, minor: Note.b.minor),
{TonalMode.major: Note.d.major, TonalMode.minor: Note.b.minor},
);
expect(
KeySignature.fromDistance(3).keys,
(major: Note.a.major, minor: Note.f.sharp.minor),
{TonalMode.major: Note.a.major, TonalMode.minor: Note.f.sharp.minor},
);
expect(
KeySignature.fromDistance(4).keys,
(major: Note.e.major, minor: Note.c.sharp.minor),
{TonalMode.major: Note.e.major, TonalMode.minor: Note.c.sharp.minor},
);
expect(
KeySignature.fromDistance(5).keys,
(major: Note.b.major, minor: Note.g.sharp.minor),
{TonalMode.major: Note.b.major, TonalMode.minor: Note.g.sharp.minor},
);
expect(
KeySignature.fromDistance(6).keys,
(major: Note.f.sharp.major, minor: Note.d.sharp.minor),
{
TonalMode.major: Note.f.sharp.major,
TonalMode.minor: Note.d.sharp.minor,
},
);
expect(
KeySignature.fromDistance(7).keys,
(major: Note.c.sharp.major, minor: Note.a.sharp.minor),
{
TonalMode.major: Note.c.sharp.major,
TonalMode.minor: Note.a.sharp.minor,
},
);
expect(
KeySignature.fromDistance(8).keys,
(major: Note.g.sharp.major, minor: Note.e.sharp.minor),
{
TonalMode.major: Note.g.sharp.major,
TonalMode.minor: Note.e.sharp.minor,
},
);
expect(
KeySignature.fromDistance(9).keys,
(major: Note.d.sharp.major, minor: Note.b.sharp.minor),
{
TonalMode.major: Note.d.sharp.major,
TonalMode.minor: Note.b.sharp.minor,
},
);
expect(
KeySignature.fromDistance(10).keys,
(major: Note.a.sharp.major, minor: Note.f.sharp.sharp.minor),
{
TonalMode.major: Note.a.sharp.major,
TonalMode.minor: Note.f.sharp.sharp.minor,
},
);
});

test('returns null when this KeySignature is not canonical', () {
expect(KeySignature([Note.d.flat]).keys, isNull);
expect(KeySignature([Note.c.sharp.sharp]).keys, isNull);
test('returns an empty Map when this KeySignature is not canonical', () {
expect(KeySignature([Note.d.flat]).keys, <TonalMode, Key>{});
expect(KeySignature([Note.c.sharp.sharp]).keys, <TonalMode, Key>{});
});
});

Expand Down

0 comments on commit 94247c1

Please sign in to comment.