Skip to content

Commit

Permalink
refactor(accidental): rewrite new Accidental class (#8)
Browse files Browse the repository at this point in the history
* refactor(accidental): rewrite new `Accidental` class

* test(accidental): add test cases for `Accidental`

* docs(tonality): fix typo

* docs(accidental): reformat Markdown list
  • Loading branch information
albertms10 committed Apr 5, 2023
1 parent 86067fb commit 202f0b2
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 166 deletions.
2 changes: 1 addition & 1 deletion lib/music_notes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ part 'src/classes/key_signature.dart';
part 'src/classes/note.dart';
part 'src/classes/relative_tonalities.dart';
part 'src/classes/tonality.dart';
part 'src/enums/accidentals.dart';
part 'src/enums/intervals.dart';
part 'src/enums/modes.dart';
part 'src/enums/notes.dart';
part 'src/enums/qualities.dart';
part 'src/interfaces/music_item.dart';
part 'src/interfaces/transposable.dart';
part 'src/note/accidental.dart';
part 'src/utils/music.dart';
10 changes: 5 additions & 5 deletions lib/src/classes/enharmonic_note.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,24 @@ class EnharmonicNote extends Enharmonic<Note> {
return SplayTreeSet<Note>.from({
Note(
noteBelow,
AccidentalsValues.fromValue(note.value - noteBelow.value),
Accidental(note.value - noteBelow.value),
),
Note(note),
Note(
noteAbove,
AccidentalsValues.fromValue(note.value - noteAbove.value),
Accidental(note.value - noteAbove.value),
),
});
}

return SplayTreeSet<Note>.from({
Note(
NotesValues.fromValue(semitones - 1)!,
Accidentals.sharp,
Accidental.sharp,
),
Note(
NotesValues.fromValue(semitones + 1)!,
Accidentals.flat,
Accidental.flat,
),
});
}
Expand All @@ -50,7 +50,7 @@ class EnharmonicNote extends Enharmonic<Note> {
/// EnharmonicNote.note(5, Accidentals.flat)
/// == const Note(Notes.fa, Accidentals.flat)
/// ```
static Note note(int semitones, [Accidentals? preferredAccidental]) {
static Note note(int semitones, [Accidental? preferredAccidental]) {
final enharmonicNotes = EnharmonicNote.fromSemitones(semitones).items;

return enharmonicNotes.firstWhere(
Expand Down
8 changes: 4 additions & 4 deletions lib/src/classes/key_signature.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ part of '../../music_notes.dart';
@immutable
class KeySignature {
final int number;
final Accidentals? accidental;
final Accidental? accidental;

const KeySignature(this.number, [this.accidental])
: assert(number >= 0, 'Provide a positive number'),
Expand All @@ -18,8 +18,8 @@ class KeySignature {
distance == 0
? null
: distance > 0
? Accidentals.sharp
: Accidentals.flat,
? Accidental.sharp
: Accidental.flat,
);

/// Returns [RelativeTonalities] with the two tonalities that are defined
Expand Down Expand Up @@ -50,7 +50,7 @@ class KeySignature {
final n =
i == iterations ? nModExcludeZero(number, notesValues) : notesValues;

list.add('$n × ${accidental!.increment(i - 1)!.name}');
list.add('$n × ${Accidental(accidental!.value + i - 1).symbol}');
}

return list.join(', ');
Expand Down
26 changes: 13 additions & 13 deletions lib/src/classes/note.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ part of '../../music_notes.dart';
@immutable
class Note implements MusicItem, Comparable<Note> {
final Notes note;
final Accidentals? accidental;
final Accidental? accidental;

const Note(this.note, [this.accidental]);

factory Note.fromSemitones(
int semitones, [
Accidentals? preferredAccidental,
Accidental? preferredAccidental,
]) =>
EnharmonicNote.note(semitones, preferredAccidental);

Expand All @@ -27,7 +27,7 @@ class Note implements MusicItem, Comparable<Note> {
factory Note.fromTonalityAccidentals(
int accidentals,
Modes mode, [
Accidentals? accidental,
Accidental? accidental,
]) {
final note = Note.fromRawAccidentals(accidentals, accidental);

Expand All @@ -51,18 +51,18 @@ class Note implements MusicItem, Comparable<Note> {
/// Note.fromRawAccidentals(0)
/// == const Note(Notes.la)
/// ```
factory Note.fromRawAccidentals(int accidentals, [Accidentals? accidental]) =>
factory Note.fromRawAccidentals(int accidentals, [Accidental? accidental]) =>
Note.fromSemitones(
Interval(
Intervals.fifth,
Qualities.perfect,
descending: accidental == Accidentals.flat,
descending: accidental == Accidental.flat,
).semitones *
accidentals +
1,
(accidental == Accidentals.flat && accidentals > 8) ||
(accidental == Accidentals.sharp && accidentals > 10)
? accidental!.incremented
(accidental == Accidental.flat && accidentals > 8) ||
(accidental == Accidental.sharp && accidentals > 10)
? Accidental(accidental!.value + 1)
: accidental,
);

Expand Down Expand Up @@ -97,15 +97,15 @@ class Note implements MusicItem, Comparable<Note> {
final distance = _runSemitonesDistance(
note,
interval.semitones,
Accidentals.sharp,
Accidental.sharp,
);

return distance < chromaticDivisions
? distance
: _runSemitonesDistance(
note,
interval.inverted.semitones,
Accidentals.flat,
Accidental.flat,
) *
-1;
}
Expand All @@ -117,7 +117,7 @@ class Note implements MusicItem, Comparable<Note> {
int _runSemitonesDistance(
Note note,
int semitones,
Accidentals preferredAccidental,
Accidental preferredAccidental,
) {
var distance = 0;
var currentPitch = this.semitones;
Expand Down Expand Up @@ -173,12 +173,12 @@ class Note implements MusicItem, Comparable<Note> {
/// ) == const Note(Notes.mi, Accidentals.flat)
/// ```
/// ```
Note transposeBy(int semitones, [Accidentals? preferredAccidental]) =>
Note transposeBy(int semitones, [Accidental? preferredAccidental]) =>
Note.fromSemitones(this.semitones + semitones, preferredAccidental);
@override
String toString() =>
note.name + (accidental != null ? ' ${accidental!.name}' : '');
note.name + (accidental != null ? ' ${accidental!.symbol}' : '');
@override
bool operator ==(Object other) =>
Expand Down
8 changes: 4 additions & 4 deletions lib/src/classes/relative_tonalities.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ class RelativeTonalities implements Comparable<RelativeTonalities> {
static int _itemsAccidentals(Set<Tonality> tonalities) =>
tonalities.first.accidentals;

/// Returns an [Accidentals] enum item of [tonalities].
/// Returns the [Accidental] of [tonalities].
///
/// It is mainly used by [accidental] getter.
static Accidentals _itemsAccidental(Set<Tonality> tonalities) =>
static Accidental _itemsAccidental(Set<Tonality> tonalities) =>
tonalities.first.accidental;

/// Returns the number of accidentals of this [RelativeTonalities].
Expand All @@ -38,7 +38,7 @@ class RelativeTonalities implements Comparable<RelativeTonalities> {
/// ```
int get accidentals => _itemsAccidentals(tonalities);

/// Returns an [Accidentals] enum item of this [RelativeTonalities].
/// Returns the [Accidental] of this [RelativeTonalities].
///
/// Example:
/// ```dart
Expand All @@ -47,7 +47,7 @@ class RelativeTonalities implements Comparable<RelativeTonalities> {
/// const Tonality(Note(Notes.ut), Modes.minor),
/// }).accidental == Accidentals.flat
/// ```
Accidentals get accidental => _itemsAccidental(tonalities);
Accidental get accidental => _itemsAccidental(tonalities);

@override
String toString() => '$tonalities';
Expand Down
14 changes: 7 additions & 7 deletions lib/src/classes/tonality.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Tonality implements Comparable<Tonality> {
factory Tonality.fromAccidentals(
int accidentals,
Modes mode, [
Accidentals? accidental,
Accidental? accidental,
]) =>
Tonality(
Note.fromTonalityAccidentals(accidentals, mode, accidental),
Expand All @@ -29,23 +29,23 @@ class Tonality implements Comparable<Tonality> {
note,
).abs();

/// Returns an [Accidentals] enum item of this [Tonality]’s key signature.
/// Returns the [Accidental] of this [Tonality]’s key signature.
///
/// Examples:
/// ```dart
/// const Tonality(Note(Notes.mi), Modes.major).accidental
/// == Accidentals.sharp
/// == Accidental.sharp
///
/// const Tonality(Note(Notes.fa), Modes.minor).accidental
/// == Accidentals.flat
/// == Accidental.flat
/// ```
Accidentals get accidental => exactFifthsDistance(
Accidental get accidental => exactFifthsDistance(
Tonality.fromAccidentals(0, mode).note,
note,
) >
0
? Accidentals.sharp
: Accidentals.flat;
? Accidental.sharp
: Accidental.flat;

/// Returns the [Modes.major] or [Modes.minor] relative [Tonality]
/// of this [Tonality].
Expand Down
106 changes: 0 additions & 106 deletions lib/src/enums/accidentals.dart

This file was deleted.

49 changes: 49 additions & 0 deletions lib/src/note/accidental.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
part of '../../music_notes.dart';

/// An accidental.
class Accidental {
/// The value representing this [Accidental]:
///
/// - `> 0` for sharps.
/// - `== 0` for natural.
/// - `< 0` for flats.
final int value;

/// Creates a new [Accidental] from a [value].
const Accidental(this.value);

static const Accidental tripleSharp = Accidental(3);
static const Accidental doubleSharp = Accidental(2);
static const Accidental sharp = Accidental(1);
static const Accidental natural = Accidental(0);
static const Accidental flat = Accidental(-1);
static const Accidental doubleFlat = Accidental(-2);
static const Accidental tripleFlat = Accidental(-3);

static const String doubleSharpSymbol = '𝄪';
static const String sharpSymbol = '♯';
static const String naturalSymbol = '♮';
static const String flatSymbol = '♭';
static const String doubleFlatSymbol = '𝄫';

/// Returns the symbol of this [Accidental].
///
/// Examples:
/// ```dart
/// assert(Accidental.flat.symbol == '♭')
/// assert(Accidental.doubleSharp.symbol == '𝄪')
/// ```
String get symbol {
if (value == 0) return naturalSymbol;

return (value.isOdd ? (value.isNegative ? flatSymbol : sharpSymbol) : '') +
(value.isNegative ? doubleFlatSymbol : doubleSharpSymbol) *
(value.abs() ~/ 2);
}

@override
bool operator ==(Object other) => other is Accidental && value == other.value;

@override
int get hashCode => value.hashCode;
}

0 comments on commit 202f0b2

Please sign in to comment.