Skip to content

Commit

Permalink
refactor(interval): move EnharmonicInterval.fromDesiredSemitones
Browse files Browse the repository at this point in the history
  • Loading branch information
albertms10 committed Apr 14, 2023
1 parent 241a1f8 commit 4843db3
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 91 deletions.
42 changes: 5 additions & 37 deletions lib/src/interval/enharmonic_interval.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,53 +25,21 @@ class EnharmonicInterval extends Enharmonic<Interval> {
final intervalAbove = interval + 1;

return SplayTreeSet<Interval>.of({
Interval.fromDesiredSemitones(intervalBelow, semitones - 1),
Interval.fromDesiredSemitones(interval, semitones - 1),
Interval.fromDesiredSemitones(intervalAbove, semitones - 1),
Interval.fromSemitones(intervalBelow, semitones - 1),
Interval.fromSemitones(interval, semitones - 1),
Interval.fromSemitones(intervalAbove, semitones - 1),
});
}

final intervalBelow = IntIntervalExtension.fromSemitones(semitones - 2);
final intervalAbove = IntIntervalExtension.fromSemitones(semitones);

return SplayTreeSet<Interval>.of({
Interval.fromDesiredSemitones(intervalBelow!, semitones - 1),
Interval.fromDesiredSemitones(intervalAbove!, semitones - 1),
Interval.fromSemitones(intervalBelow!, semitones - 1),
Interval.fromSemitones(intervalAbove!, semitones - 1),
});
}

/// Returns the [Interval] from [semitones] and a [preferredQuality].
///
/// Example:
/// ```dart
/// EnharmonicInterval.intervalFromSemitones(4)
/// == const Interval.imperfect(3, ImperfectQuality.minor)
///
/// EnharmonicInterval.intervalFromSemitones(7)
/// == const Interval.perfect(4, PerfectQuality.augmented)
///
/// EnharmonicInterval.intervalFromSemitones(7, PerfectQuality.diminished)
/// == const Interval.perfect(5, PerfectQuality.diminished)
/// ```
static Interval intervalFromSemitones(
int semitones, [
Quality? preferredQuality,
]) {
final intervals = EnharmonicInterval(semitones).items;

return intervals.firstWhereOrNull(
(interval) => interval.quality == preferredQuality,
) ??
// Find the Interval with the smaller Quality delta semitones.
intervals
.sorted(
(a, b) => a.quality.semitones
.abs()
.compareTo(b.quality.semitones.abs()),
)
.first;
}

/// Returns a transposed [EnharmonicInterval] by [semitones]
/// from this [EnharmonicInterval].
///
Expand Down
37 changes: 36 additions & 1 deletion lib/src/interval/interval.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,47 @@ class Interval implements MusicItem {
: this._(size, Quality.fromInterval(size, delta));

/// Creates a new [Interval] from [semitones].
Interval.fromDesiredSemitones(int size, int semitones)
Interval.fromSemitones(int size, int semitones)
: this._(
size,
Quality.fromInterval(size, semitones - size.semitones),
);

/// Creates a new [Interval] from [semitones] and a [preferredQuality].
///
/// Example:
/// ```dart
/// Interval.fromSemitonesQuality(4)
/// == const Interval.imperfect(3, ImperfectQuality.minor)
///
/// Interval.fromSemitonesQuality(7)
/// == const Interval.perfect(4, PerfectQuality.augmented)
///
/// Interval.fromSemitonesQuality(7, PerfectQuality.diminished)
/// == const Interval.perfect(5, PerfectQuality.diminished)
/// ```
factory Interval.fromSemitonesQuality(
int semitones, [
Quality? preferredQuality,
]) {
final intervals = EnharmonicInterval(semitones).items;

if (preferredQuality != null) {
final interval = intervals.firstWhereOrNull(
(interval) => interval.quality == preferredQuality,
);
if (interval != null) return interval;
}

// Find the Interval with the smaller Quality delta semitones.
return intervals
.sorted(
(a, b) =>
a.quality.semitones.abs().compareTo(b.quality.semitones.abs()),
)
.first;
}

/// Returns the number of semitones of this [Interval].
///
/// Example:
Expand Down
27 changes: 0 additions & 27 deletions test/src/interval/enharmonic_interval_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,33 +70,6 @@ void main() {
);
});

group('.intervalFromSemitones()', () {
test('should return the correct Interval from semitones', () {
expect(
EnharmonicInterval.intervalFromSemitones(4),
equals(const Interval.imperfect(3, ImperfectQuality.minor)),
);
expect(
EnharmonicInterval.intervalFromSemitones(7),
equals(const Interval.perfect(4, PerfectQuality.augmented)),
);
expect(
EnharmonicInterval.intervalFromSemitones(
7,
PerfectQuality.augmented,
),
equals(const Interval.perfect(4, PerfectQuality.augmented)),
);
expect(
EnharmonicInterval.intervalFromSemitones(
7,
PerfectQuality.diminished,
),
equals(const Interval.perfect(5, PerfectQuality.diminished)),
);
});
});

group('.transposeBy()', () {
test(
'should return the transposed EnharmonicInterval by semitones',
Expand Down
79 changes: 53 additions & 26 deletions test/src/interval/interval_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,114 +18,141 @@ void main() {
});
});

group('.fromDesiredSemitones()', () {
test('should create a new Interval from desired semitones', () {
group('.fromSemitones()', () {
test('should create a new Interval from semitones', () {
expect(
Interval.fromDesiredSemitones(1, -1),
Interval.fromSemitones(1, -1),
const Interval.perfect(1, PerfectQuality.diminished),
);
expect(
Interval.fromDesiredSemitones(1, 0),
Interval.fromSemitones(1, 0),
const Interval.perfect(1, PerfectQuality.perfect),
);
expect(
Interval.fromDesiredSemitones(1, 1),
Interval.fromSemitones(1, 1),
const Interval.perfect(1, PerfectQuality.augmented),
);

expect(
Interval.fromDesiredSemitones(2, 0),
Interval.fromSemitones(2, 0),
const Interval.imperfect(2, ImperfectQuality.diminished),
);
expect(
Interval.fromDesiredSemitones(2, 1),
Interval.fromSemitones(2, 1),
const Interval.imperfect(2, ImperfectQuality.minor),
);
expect(
Interval.fromDesiredSemitones(2, 2),
Interval.fromSemitones(2, 2),
const Interval.imperfect(2, ImperfectQuality.major),
);
expect(
Interval.fromDesiredSemitones(2, 3),
Interval.fromSemitones(2, 3),
const Interval.imperfect(2, ImperfectQuality.augmented),
);

expect(
Interval.fromDesiredSemitones(3, 2),
Interval.fromSemitones(3, 2),
const Interval.imperfect(3, ImperfectQuality.diminished),
);
expect(
Interval.fromDesiredSemitones(3, 3),
Interval.fromSemitones(3, 3),
const Interval.imperfect(3, ImperfectQuality.minor),
);
expect(
Interval.fromDesiredSemitones(3, 4),
Interval.fromSemitones(3, 4),
const Interval.imperfect(3, ImperfectQuality.major),
);
expect(
Interval.fromDesiredSemitones(3, 5),
Interval.fromSemitones(3, 5),
const Interval.imperfect(3, ImperfectQuality.augmented),
);

expect(
Interval.fromDesiredSemitones(4, 4),
Interval.fromSemitones(4, 4),
const Interval.perfect(4, PerfectQuality.diminished),
);
expect(
Interval.fromDesiredSemitones(4, 5),
Interval.fromSemitones(4, 5),
const Interval.perfect(4, PerfectQuality.perfect),
);
expect(
Interval.fromDesiredSemitones(4, 6),
Interval.fromSemitones(4, 6),
const Interval.perfect(4, PerfectQuality.augmented),
);

expect(
Interval.fromDesiredSemitones(5, 6),
Interval.fromSemitones(5, 6),
const Interval.perfect(5, PerfectQuality.diminished),
);
expect(
Interval.fromDesiredSemitones(5, 7),
Interval.fromSemitones(5, 7),
const Interval.perfect(5, PerfectQuality.perfect),
);
expect(
Interval.fromDesiredSemitones(5, 8),
Interval.fromSemitones(5, 8),
const Interval.perfect(5, PerfectQuality.augmented),
);

expect(
Interval.fromDesiredSemitones(6, 8),
Interval.fromSemitones(6, 8),
const Interval.imperfect(6, ImperfectQuality.minor),
);
expect(
Interval.fromDesiredSemitones(6, 9),
Interval.fromSemitones(6, 9),
const Interval.imperfect(6, ImperfectQuality.major),
);

expect(
Interval.fromDesiredSemitones(7, 10),
Interval.fromSemitones(7, 10),
const Interval.imperfect(7, ImperfectQuality.minor),
);
expect(
Interval.fromDesiredSemitones(7, 11),
Interval.fromSemitones(7, 11),
const Interval.imperfect(7, ImperfectQuality.major),
);

expect(
Interval.fromDesiredSemitones(8, 11),
Interval.fromSemitones(8, 11),
const Interval.perfect(8, PerfectQuality.diminished),
);
expect(
Interval.fromDesiredSemitones(8, 12),
Interval.fromSemitones(8, 12),
const Interval.perfect(8, PerfectQuality.perfect),
);
expect(
Interval.fromDesiredSemitones(8, 13),
Interval.fromSemitones(8, 13),
const Interval.perfect(8, PerfectQuality.augmented),
);
});
});

group('.fromSemitonesQuality()', () {
test('should return the correct Interval from semitones and Quality', () {
expect(
Interval.fromSemitonesQuality(4),
equals(const Interval.imperfect(3, ImperfectQuality.minor)),
);
expect(
Interval.fromSemitonesQuality(7),
equals(const Interval.perfect(4, PerfectQuality.augmented)),
);
expect(
Interval.fromSemitonesQuality(
7,
PerfectQuality.augmented,
),
equals(const Interval.perfect(4, PerfectQuality.augmented)),
);
expect(
Interval.fromSemitonesQuality(
7,
PerfectQuality.diminished,
),
equals(const Interval.perfect(5, PerfectQuality.diminished)),
);
});
});

group('.semitones', () {
test('should return the number of semitones of this Interval', () {
expect(
Expand Down

0 comments on commit 4843db3

Please sign in to comment.