Skip to content

Commit

Permalink
refactor(size): ♻️ redeclare simple in extension types to allow cha…
Browse files Browse the repository at this point in the history
…ining (#438)

* refactor(size): ♻️ redeclare `simple` in extension types to allow expected chaining

* docs(example): 📖 add chaining `Size.simple` example

* refactor(size): ♻️ remove redundant `Size.` references
  • Loading branch information
albertms10 committed Mar 10, 2024
1 parent 25ac644 commit cf4a865
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 26 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,16 @@ Pitch.parse('Eb3'); // E♭3
Create an `Interval`:

```dart
Interval.P4; // P4
const Interval.imperfect(Size.tenth, ImperfectQuality.major); // M10
Interval.d5; // d5
Size.sixth.augmented; // A6
Size.eleventh.simple.perfect; // P4
```

Or turn it descending:

```dart
-Interval.m6; // m-6
-Interval.m7; // m-7
Interval.M3.descending(); // M-3
```

Expand Down
5 changes: 3 additions & 2 deletions example/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ void main() {
Pitch.parse('Eb3'); // E♭3

// Intervals
Interval.P4; // P4
const Interval.imperfect(Size.tenth, ImperfectQuality.major); // M10
Interval.d5; // d5
Size.sixth.augmented; // A6
Size.twelfth.simple.perfect; // P5

-Interval.m6; // m-6
-Interval.m7; // m-7
Interval.M3.descending(); // M-3

Note.c.interval(Note.g); // P5
Expand Down
47 changes: 25 additions & 22 deletions lib/src/interval/size.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ extension type const Size._(int size) implements int {
/// [Size] to the corresponding [ImperfectQuality.minor] or
/// [PerfectQuality.perfect] semitones.
static const _sizeToSemitones = {
Size.unison: 0, // P
Size.second: 1, // m
Size.third: 3, // m
Size.fourth: 5, // P
Size.fifth: 7, // P
Size.sixth: 8, // m
Size.seventh: 10, // m
Size.octave: 12, // P
unison: 0, // P
second: 1, // m
third: 3, // m
fourth: 5, // P
fifth: 7, // P
sixth: 8, // m
seventh: 10, // m
octave: 12, // P
};

/// The [Size] that matches with [semitones] in [_sizeToSemitones].
Expand Down Expand Up @@ -107,10 +107,10 @@ extension type const Size._(int size) implements int {
/// ```
int get semitones {
final simpleAbs = simple.abs();
final octaveShift = chromaticDivisions * (absShift ~/ Size.octave);
final octaveShift = chromaticDivisions * (absShift ~/ octave);
// We exclude perfect octaves (simplified as 8) from the lookup to consider
// them 0 (as if they were modulo `Size.octave`).
final size = Size(simpleAbs == Size.octave ? 1 : simpleAbs);
final size = Size(simpleAbs == octave ? 1 : simpleAbs);

return (_sizeToSemitones[size]! + octaveShift) * sign;
}
Expand All @@ -119,7 +119,7 @@ extension type const Size._(int size) implements int {
int get absShift {
final sizeAbs = abs();

return sizeAbs + sizeAbs ~/ Size.octave;
return sizeAbs + sizeAbs ~/ octave;
}

/// The [PerfectQuality.diminished] or [ImperfectQuality.diminished] interval
Expand Down Expand Up @@ -156,7 +156,7 @@ extension type const Size._(int size) implements int {
/// Size.sixth.isPerfect == false
/// (-Size.eleventh).isPerfect == true
/// ```
bool get isPerfect => absShift % (Size.octave / 2) < 2;
bool get isPerfect => absShift % (octave / 2) < 2;

/// Whether this [Size] is greater than [Size.octave].
///
Expand All @@ -169,7 +169,10 @@ extension type const Size._(int size) implements int {
/// (-Size.eleventh).isCompound == true
/// Size.thirteenth.isCompound == true
/// ```
bool get isCompound => abs() > Size.octave;
bool get isCompound => abs() > octave;

static int _simple(Size size) =>
size.isCompound ? size.absShift.nonZeroMod(octave) * size.sign : size;

/// The simplified version of this [Size].
///
Expand All @@ -180,9 +183,7 @@ extension type const Size._(int size) implements int {
/// Size.octave.simple == Size.octave
/// const Size(-22).simple == -Size.octave
/// ```
Size get simple => Size(
isCompound ? absShift.nonZeroMod(Size.octave) * sign : size,
);
Size get simple => Size(_simple(this));

/// This [Size] formatted as a string.
String format({IntervalNotation system = IntervalNotation.standard}) =>
Expand All @@ -205,9 +206,7 @@ extension type const PerfectSize._(int size) implements Size {
const PerfectSize(this.size)
// Copied from [Size.isPerfect] to allow const.
: assert(
((size < 0 ? 0 - size : size) + (size < 0 ? 0 - size : size) ~/ 8) %
4 <
2,
((size < 0 ? -size : size) + (size < 0 ? -size : size) ~/ 8) % 4 < 2,
'Interval must be perfect.',
);

Expand All @@ -221,6 +220,9 @@ extension type const PerfectSize._(int size) implements Size {
/// ```
Interval get perfect => Interval.perfect(this);

@redeclare
PerfectSize get simple => PerfectSize(Size._simple(this));

/// The negation of this [PerfectSize].
///
/// Example:
Expand All @@ -238,9 +240,7 @@ extension type const ImperfectSize._(int size) implements Size {
const ImperfectSize(this.size)
// Copied from [Size.isPerfect] to allow const.
: assert(
((size < 0 ? 0 - size : size) + (size < 0 ? 0 - size : size) ~/ 8) %
4 >=
2,
((size < 0 ? -size : size) + (size < 0 ? -size : size) ~/ 8) % 4 >= 2,
'Interval must be imperfect.',
);

Expand All @@ -264,6 +264,9 @@ extension type const ImperfectSize._(int size) implements Size {
/// ```
Interval get minor => Interval.imperfect(this, ImperfectQuality.minor);

@redeclare
ImperfectSize get simple => ImperfectSize(Size._simple(this));

/// The negation of this [ImperfectSize].
///
/// Example:
Expand Down
5 changes: 5 additions & 0 deletions test/src/interval/size_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ void main() {
expect(Size.unison.perfect, Interval.P1);
expect(Size.fourth.perfect, Interval.P4);
expect((-Size.fifth).perfect, -Interval.P5);
expect(Size.twelfth.simple.perfect, Interval.P5);
});
});

Expand All @@ -58,6 +59,7 @@ void main() {
expect(Size.second.major, Interval.M2);
expect(Size.sixth.major, Interval.M6);
expect((-Size.ninth).major, -Interval.M9);
expect(Size.thirteenth.simple.major, Interval.M6);
});
});

Expand All @@ -66,6 +68,7 @@ void main() {
expect(Size.third.minor, Interval.m3);
expect(Size.seventh.minor, Interval.m7);
expect((-Size.sixth).minor, -Interval.m6);
expect(Size.ninth.simple.minor, Interval.m2);
});
});

Expand All @@ -74,6 +77,7 @@ void main() {
expect(Size.second.diminished, Interval.d2);
expect(Size.fifth.diminished, Interval.d5);
expect((-Size.seventh).diminished, -Interval.d7);
expect(Size.eleventh.simple.diminished, Interval.d4);
});
});

Expand All @@ -82,6 +86,7 @@ void main() {
expect(Size.third.augmented, Interval.A3);
expect(Size.fourth.augmented, Interval.A4);
expect((-Size.sixth).augmented, -Interval.A6);
expect(Size.twelfth.simple.augmented, Interval.A5);
});
});
});
Expand Down

0 comments on commit cf4a865

Please sign in to comment.