| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Harmonic.Framework.Builder.JazzGen
Description
The jazz counterpart of the triadic walk, decomposed R→E→T with every shared concern imported from its home module rather than re-implemented:
- R — the
Changegraph's adjacency (no consonance fallback: the corpus measures rich enough that none is needed — 0 dead ends, ~219-candidate typical pools) intersected with the caller'sHarmonicContextvia the samematchesContextWithTargetfilter the classical walk applies (it is arity-agnostic and anchors exactly as jazz movement does) — including the rise/fall bass-direction spec (resolved per step, 1-based, so rotate selectors stay in phase with the classical walk), the dissonance drift and the pedal-tone filters. Inversion spacing (invSkip) is inert here by design: jazz slash structures are graph vocabulary, not a voicing choice the walk makes. A step whose R-filter empties the pool relaxes down a ladder, each stage with a notice: exact rise/fall target, then any arrival in the spec's direction (step size freed), then the direction with only chord-colour containment freed (bass still lands on an allowed root), then plain membership, then everything — there is no fallback pool to fill from, and continuity beats a hard stop, but a pedal repeat is the last resort under an active direction, never the first. - E — corpus frequency under the seek spec
(
resolveWeights), plus the classical steer boost when the spec names classical composers. - T — the shared gamma entropy dial
(
gammaIndexScaledWith).
Seek semantics (genJ)
One spec drives both corpora, split by
splitSeekByCorpus:
"*"— aggregate corpus-frequency walk over the whole jazz graph.- Jazz names (
"monk:60 coltrane:40") — composer-blend scoring over jazz edge weights (substring-matched against jazz keys). - Classical names (
"debussy") — the jazz walk runs on"*"and each step is steered: the current chord's most consonant embedded triad queries the classical graph under that blend, and jazz candidates containing one of the top recommended triads (arriving by the same movement) are boosted by thesteerstrength. - Mixed (
"monk debussy") — blend and steer together. "none"— refused: the jazz graph IS the generator; no offline mode.
Synopsis
- runJazzGen :: GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
- runJazzGenFrom :: ProgressionContext -> Int -> Int -> GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
- jazzGuardSeek :: GenConfig -> IO ()
- jazzStartCue :: GenConfig -> IO CadenceState
Documentation
runJazzGenFrom :: ProgressionContext -> Int -> Int -> GenConfig -> IO (ProgressionContext, GenerationDiagnostics) Source #
Regenerate bars s..e (1-indexed, wrap-aware; len expands the
range like the classical genFrom) of a
jazz-family source in place. The cue is the bar before s (or the
caller's override); regenerated bars are spliced back via
pcSplice, whose triad-layer path applies the standard seam
movement-fix — the bar after the range keeps its chord but its
movement metadata is corrected to the actual arrival interval, exactly
the legacy-family regen contract.
jazzGuardSeek :: GenConfig -> IO () Source #
Refuse seek "none" before any Neo4j contact: the jazz graph IS the
generator — there is no offline fallback. Exported so the attempt loop
can guard before opening its scoring connection.
jazzStartCue :: GenConfig -> IO CadenceState Source #
Draw an uncued genJ starting chord from
the jazz graph itself: the STRUCTURE is sampled from the Change nodes
proportionally to outgoing corpus mass (the corpus's own sense of a
common departure point), and the ROOT comes from the caller's tonal
context — Change nodes are zero-form, so the two are independent.
Structure-in-key containment is preferred but relaxes when the
context admits no node whole, mirroring the walk's own per-step
relaxation; roots stay hard-filtered. Replaces the whole-corpus
random major triad, which is not jazz vocabulary at all — and which
resolveStart then flagged as outside it on every uncued run.