Tonic
Tonic copied to clipboard
Lazy Chord loading on Key Type
Description
From what I understand, when you initialize a Key
, all the chords are generated inside the init.
However, if you want to create all the available keys for a certain note, the performance is pretty bad.
Here is a piece of code that illustrates this concept:
let newKeys = Scale.allCases.map {
Key(root: note, scale: $0)
}
This code creates an array of keys for all the scales of a given note.
Proposed Solution
I would suggest implementing lazy chord creation. This would allow users to request the chords for a specific key only when needed, instead of generating them automatically during initialization. I believe that generating chords during initialization is unnecessarily complex and pollutes the domain of the Key
Object, in addition, it also impacts the performance.
/// All the traditional triads representable root, third, and fifth from each note in the key
public func primaryTriads() ->[Chord] {
let table = ChordTable.shared
var primaryTriads: [Chord] = []
let allowablePrimaryTriads: [ChordType] = [.majorTriad, .minorTriad, .diminishedTriad, .augmentedTriad]
for (_, chord) in table.chords where chord.noteClassSet.isSubset(of: noteSet.noteClassSet) {
if allowablePrimaryTriads.contains(chord.type) {
primaryTriads.append(Chord(chord.root, type: chord.type))
}
}
let primaryTriadsStartingWithC = primaryTriads.sorted(by: { $0.root.letter < $1.root.letter })
let rootPosition = primaryTriadsStartingWithC.firstIndex(where: { $0.root == root }) ?? 0
return Array(primaryTriadsStartingWithC.rotatingLeft(positions: rootPosition))
}
/// All chords that fit in the key
public func chords() -> [Chord] {
let table = ChordTable.shared
var chords: [Chord] = []
for (_, chord) in table.chords where chord.noteClassSet.isSubset(of: noteSet.noteClassSet) {
chords.append(Chord(chord.root, type: chord.type))
}
return chords
}
We could also think about adding a static global cache, similar to Chordtable
, that stores a key and all the corresponding chords globally for faster access.
Wdyt?
These sound like good solutions. Thank you for pushing on this.