diff --git a/lib/src/interval/size.dart b/lib/src/interval/size.dart index 3a196b18..230366d9 100644 --- a/lib/src/interval/size.dart +++ b/lib/src/interval/size.dart @@ -130,12 +130,9 @@ extension type const Size._(int size) implements int { /// ``` int get semitones { final absSimple = simple.abs(); - 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(absSimple == octave ? 1 : absSimple); + final octaves = (abs() - absSimple) ~/ 7; - return (_sizeToSemitones[size]! + octaveShift) * sign; + return (_sizeToSemitones[absSimple]! + octaves * 12) * sign; } /// The absolute [Size] value taking octave shift into account. diff --git a/test/src/interval/interval_test.dart b/test/src/interval/interval_test.dart index 0dadf292..b76782f3 100644 --- a/test/src/interval/interval_test.dart +++ b/test/src/interval/interval_test.dart @@ -405,7 +405,33 @@ void main() { expect(const Interval.perfect(Size(15)).semitones, 24); expect(const Interval.perfect(Size(22)).semitones, 36); + expect( + const Interval.imperfect(Size(23), ImperfectQuality.minor).semitones, + 37, + ); + expect( + const Interval.imperfect(Size(23), ImperfectQuality.major).semitones, + 38, + ); + expect( + const Interval.imperfect(Size(-24), ImperfectQuality.minor).semitones, + -39, + ); + expect( + const Interval.imperfect(Size(24), ImperfectQuality.major).semitones, + 40, + ); + expect(const Interval.perfect(Size(25)).semitones, 41); + expect(const Interval.perfect(Size(-26)).semitones, -43); expect(const Interval.perfect(Size(29)).semitones, 48); + expect( + const Interval.imperfect(Size(30), ImperfectQuality.minor).semitones, + 49, + ); + expect( + const Interval.imperfect(Size(-30), ImperfectQuality.major).semitones, + -50, + ); }); });