| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Harmonic.Rules.Import.Transform
Contents
Description
Transforms raw CSV corpus records into Cadence structures suitable for
Neo4j graph storage: fundamental extraction, triad generation via
Harmonic.Rules.Constraints.Overtone, and dissonance scoring.
BEFORE RE-INGESTING THE CORPUS, READ THIS ==
The LIVE database's node keys (show = movement + functionality) carry
functionality names produced under LEGACY naming rules — e.g. zero form
[0,3,8] is stored as maj_1stInv, [0,2,7] as sus4_1stInv,
[0,5,10] as sus4_2ndInv. The CURRENT namers in this pipeline
(toTriad via toCadence below) deliberately diverge from those
rules (min#5, sus2, 7sus4 for the same forms). Every read-side
fetch key is therefore built through corpusFunctionality, whose
55-form corpusNameTable (Harmonic.Rules.Types.Harmony) was
transcribed verbatim from the live database (2026-08-19).
Consequence: running this ingestion pipeline as-is would create a graph
whose keyspace DIVERGES from corpusNameTable — every fetch would miss
and generation would silently drop to fallback-only. Any re-ingestion
must do one of:
(a) route write-side naming through corpusFunctionality so the
new keyspace is identical to the table (preferred — keeps read
and write sides on one contract), or
(b) re-ingest with the current namers and then REGENERATE
corpusNameTable from the fresh database:
MATCH (c:Cadence) RETURN DISTINCT c.chord, c.show.
Either way, verify afterwards with an online gen' run: graph counts
([nG/...]) must stay nonzero across steps that select inversion forms.
Synopsis
- buildCadences :: [ChordSlice] -> [Cadence]
- buildCadencesPerPiece :: [[ChordSlice]] -> [Cadence]
- fundamentals :: Vector [Int] -> [Int]
Cadence construction
buildCadences :: [ChordSlice] -> [Cadence] Source #
Convert a sequence of chord slices into a cadence list that reflects every reasonable triad interpretation. Instead of picking a single "best" triad, we duplicate the top three options (3/2/1 copies) and cross-multiply adjacent slices so the Markov model can learn from alternate paths without fractional weights.
buildCadencesPerPiece :: [[ChordSlice]] -> [Cadence] Source #
Build cadences piece by piece, then concatenate. Keeping pieces separate matters: it stops a transition being invented across the boundary between the last chord of one piece and the first of the next.
Helpers
fundamentals :: Vector [Int] -> [Int] Source #
Extract the fundamental bass note of each chord: the lowest pitch present.
Empty chords yield 0.