Encodings
implements mappings between models of music, music notation and my Pitch Spelling Model. Models of music and music notation drawn from the dn-m ecosystem (cf. Music
, NotationModel
), .
NetworkStructures
implements all the network operations and algorithms needed for the performance of Pitch Spelling Algorithms in forward and inverse directions.
SpellingNetworks
specializes the Encodings and NetworkStructures modules to the use cases of the Pitch Spelling model.
First, make an InvertingSpellingNetwork
(inputs can be spellings: [Pitch]
, spellings: [Int: Pitch]
or spellings:[[Pitch]]
, where the last definition splits spellings easily into groups.
let invertingSpellingNetwork = InvertingSpellingNetwork(spellings: [
1: Pitch.Spelling(.f,.sharp),
2: Pitch.Spelling(.a,.sharp),
...
])
Second, generate a PitchSpellingNetworkFactory
. sets
parameter forces arrays of PitchedEdge
values to be equal in the inverting process (stabilization). A preset
parameter can also be used to fix certain PitchedEdge
weights in the process.
let factory = invertingSpellingNetwork.pitchSpellingNetworkFactory(
sets: [
[
PitchedEdge(.source, .internal(.init(1, .down))),
PitchedEdge(.source, .internal(.init(6, .down))),
PitchedEdge(.internal(.init(3, .up)), .sink),
PitchedEdge(.internal(.init(10, .up)), .sink),
],
...
]
)
Third, generate a PitchSpellingNetwork
from the factory. withPhantomPitches
feeds in pitches that cannot be adjusted by the user, but will affect the spelling. The phantom pitches will always take their default spelling - hence [0,4]
is acting as [Pitch.Spelling(.c), Pitch.Spelling(.e)]
let pitchSpellingNetwork = factory.build(from: [6,10,1], withPhantomPitches: [0,4])
Fourth, adjust PitchSpellingNetwork
weights using mask schemes. Using the following mask function.
// Adjusts edge weights based on an external scaling rule
func mask <T> (scheme: FlowNetworkScheme<T>, _ lens: @escaping (Int) -> T)
scheme
defines some weight scale factors based on Edge<T>
values. These are pulled back to the PitchSpellingNetwork
's weight scheme via the lens: @escaping (Int) -> T
parameter, which gives us a map from the pitch index Int
to the index of the newly supplied FlowNetworkScheme
.
Fifth, spell! preferring
is an optional parameter, .sharps
by default. It determines whether the search to determine the minimum cut found by the Edmonds-Karp maximum flow algorithm is taken from the .source
or the .sink
.
let spellings: [Int: SpelledPitch] = pitchSpellingNetwork.spell(preferring: .flats)