| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Harmonic.Interface.Tidal.Arranger
Description
Shorthand for manipulating progressions in a TidalCycles performance
context. All functions are designed for live-coding ergonomics: short
names, intuitive parameter order, and no IO.
Two families, both wrapping the more verbose Harmonic.Rules.Types.Progression functions:
- Rearranging
rotate,excerpt,insert,switch,clone,extract,transposeP,reverse,fuse,fuse2,interleave,expandP,progOverlap,progOverlapF,progOverlapB.- Voicing
- five strategies that turn a progression into concrete pitches —
grid,flow,lite,literalandroot.gridandflowsolve a cyclic DP for smooth voice leading; the others are literal or bass-only.
Rearranging composes on the progression before it reaches a voicing:
s <- seek "*" $ len 8 $ entropy 0.4 $ gen s' = fuse (excerpt 0 4 s) (rotate 2 s)
The voicing is then chosen per instrument at the point of play, so two lines can read the same progression differently:
, cello T (0,1) k vl flow Tenor8vb , contrabass T (0,1) k vl grid Bass8vb
Synopsis
- rotate :: Int -> ProgressionContext -> ProgressionContext
- excerpt :: Int -> Int -> ProgressionContext -> ProgressionContext
- insert :: CadenceState -> Int -> ProgressionContext -> ProgressionContext
- switch :: Int -> Int -> ProgressionContext -> ProgressionContext
- clone :: Int -> Int -> ProgressionContext -> ProgressionContext
- extract :: Int -> ProgressionContext -> CadenceState
- transposeP :: Int -> ProgressionContext -> ProgressionContext
- reverse :: ProgressionContext -> ProgressionContext
- fuse :: [ProgressionContext] -> ProgressionContext
- fuse2 :: ProgressionContext -> ProgressionContext -> ProgressionContext
- interleave :: ProgressionContext -> ProgressionContext -> ProgressionContext
- expandP :: Int -> ProgressionContext -> ProgressionContext
- progOverlap :: Int -> Progression -> Progression
- progOverlapF :: Int -> Progression -> Progression
- progOverlapB :: Int -> Progression -> Progression
- grid :: Progression -> [[Int]]
- flow :: Progression -> [[Int]]
- lite :: Progression -> [[Int]]
- literal :: Progression -> [[Int]]
- root :: Progression -> [[Int]]
- strataModeFlow :: Progression -> [[Int]]
- fromChords :: [[Int]] -> ProgressionContext
- prog :: [[Int]] -> ProgressionContext
- data ScaleSource
- = ExplicitScale [[Int]]
- | HarmonyAsScale Progression
- | HarmonyWithOverlap Progression (Int -> Progression -> Progression)
- melodyStateFrom :: ScaleSource -> Progression
- lead :: String -> IO CadenceState
- lead' :: String -> IO CadenceState
- parseLeadTokens :: String -> [LeadToken]
- data LeadToken
Position/Range Operations
rotate :: Int -> ProgressionContext -> ProgressionContext Source #
Rotate a progression by n bars (positive = left, negative = right)
excerpt :: Int -> Int -> ProgressionContext -> ProgressionContext Source #
Extract bars start to end (1-indexed, inclusive)
insert :: CadenceState -> Int -> ProgressionContext -> ProgressionContext Source #
Insert a CadenceState at position (1-indexed), replacing the existing one
switch :: Int -> Int -> ProgressionContext -> ProgressionContext Source #
Switch two bars at positions m and n (1-indexed)
clone :: Int -> Int -> ProgressionContext -> ProgressionContext Source #
Clone bar m to position n (overwrites n with contents of m)
extract :: Int -> ProgressionContext -> CadenceState Source #
Extract a single CadenceState at index (1-indexed, modulo wrap) from the triad layer
Transformation Operations
transposeP :: Int -> ProgressionContext -> ProgressionContext Source #
Transpose a progression by n semitones
reverse :: ProgressionContext -> ProgressionContext Source #
Reverse a progression
fuse :: [ProgressionContext] -> ProgressionContext Source #
Fuse multiple progressions into one (concatenation)
fuse2 :: ProgressionContext -> ProgressionContext -> ProgressionContext Source #
Binary fuse for convenience in live coding
interleave :: ProgressionContext -> ProgressionContext -> ProgressionContext Source #
Interleave two progressions (alternating chords) Example: interleave [A,B,C] [X,Y,Z] = [A,X,B,Y,C,Z]
expandP :: Int -> ProgressionContext -> ProgressionContext Source #
Expand a progression by repeating each chord n times
Overlap Operations (Progression-level)
progOverlap :: Int -> Progression -> Progression Source #
Bidirectional overlap: merge pitches from n bars in both directions
progOverlapF :: Int -> Progression -> Progression Source #
Forward-only overlap: merge pitches from n bars ahead
progOverlapB :: Int -> Progression -> Progression Source #
Backward-only overlap: merge pitches from n bars behind
Voicing Extractors (Voicing paradigms)
grid :: Progression -> [[Int]] Source #
GRID paradigm: Root locked in bass with smooth compact voice leading. Uses cyclic DP to find globally optimal voicings. First chord starts compact with root in bass; all subsequent chords maintain root in bass with minimal voice movement.
flow :: Progression -> [[Int]] Source #
FLOW paradigm: Smoothest voice leading with any inversion allowed. Uses cyclic DP to find globally optimal voicings. Voice crossings permitted for optimal smoothness; bass doesn't need to be the root if an inversion provides smoother voice leading.
lite :: Progression -> [[Int]] Source #
LITE paradigm: Literal voicings with first-root normalization. Returns pitches as stored, but normalized so first chord's root is in [-12,-1]. No voice leading optimization applied (only octave normalization).
literal :: Progression -> [[Int]] Source #
Alias for lite (legacy compatibility)
root :: Progression -> [[Int]] Source #
ROOT paradigm: Root note only (root pitch class per chord). Extracts the root note (first element, mod 12) from each chord. Returns as single-element lists in [0,11] range.
strataModeFlow :: Progression -> [[Int]] Source #
STRATA-MODE-FLOW paradigm: each bar is the bar's chroma in
sorted-ascending compressed form rooted on its harmonic root, with the
whole voicing octave-shifted to minimise voice movement against the bar 0
anchor. Functions as a "key signature": pattern index i in any bar plays
the i-th scale degree of that bar's strata / mode, so pattern increments
of 1 always ascend by one set member and decrements descend by one.
Bar 0: initialCompact + normalizeByFirstRoot anchors the harmonic
root in the standard window ([-12, -1] note range). Span ≤ 12 semitones
from root upward.
Bar n+1: initialCompact rooted on bar n+1's harmonic root produces a
"natural" compressed-ascending voicing; the whole voicing is then shifted
by the octave (k·12 for k ∈ [-3..3]) that minimises total
|placed_MIDI - anchor_MIDI| across voices, where anchor is bar 0's
voicing. The root is allowed to migrate octaves freely if that makes the
line closer to the anchor. Voicing remains sorted ascending after the
shift (uniform shift preserves order), so "ascend by 1 with idx+1" holds.
Anchoring to bar 0 (rather than the previous bar) guarantees: * No drift over long walks — every bar stays within ~6 semitones of the anchor. * Cyclic return to anchor at the pattern wrap (bar N-1 → bar 0). * When chroma cycles back to bar 0's chroma (e.g. tristrata II-VI-X repeating), the bar lands on bar 0's exact MIDI (shift = 0).
O(n × k) per bar where n = chroma cardinality and k = number of octave
candidates (~7). Sub-microsecond per bar; eager forcing in arrange
still hoists the work to REPL evaluation time.
Explicit Progression Construction
fromChords :: [[Int]] -> ProgressionContext Source #
Construct a Progression from explicit pitch-class sets.
This is the main function for composing/arranging workflow (not generation).
Takes an enharmonic spelling and a list of chord pitch-class sets,
returns a Progression ready for arrange.
Example:
fromChords [[0,4,7], [5,9,0], [7,11,2]]
--> C major → F major → G major
prog :: [[Int]] -> ProgressionContext Source #
Legacy alias for fromChords (matches legacy prog function)
Scale Source (Switch Mechanism)
data ScaleSource Source #
Scale source for melody mapping. Enables flexible melody construction by allowing harmony (with optional overlap) to serve as the scale source instead of explicit scale definitions.
Constructors
| ExplicitScale [[Int]] | User-defined scale per chord |
| HarmonyAsScale Progression | Use harmony chords as scales |
| HarmonyWithOverlap Progression (Int -> Progression -> Progression) | Use harmony with overlap function applied |
melodyStateFrom :: ScaleSource -> Progression Source #
Create melody state from scale source. Converts a ScaleSource into a Progression suitable for melody arrangement.
Starting State Construction
lead :: String -> IO CadenceState Source #
Construct a CadenceState from a human-readable string.
Parses root, quality, and movement from space-separated tokens. Unspecified components fall through to randomness. Prints "root quality" to the console after construction.
Examples:
start <- lead "E min (5)" -- E minor, ascending 5th
start <- lead "E min" -- E minor, random movement
start <- lead "min" -- random root, minor quality, random movement
start <- lead E -- E, random quality, random movement
start <- lead "" -- fully random
start <- lead "(5)" -- random root and quality, fixed movement 5
lead' :: String -> IO CadenceState Source #
Construct a CadenceState from an explicit list of note names —
the arbitrary-cardinality counterpart to lead. The first note is the
root/bass; the rest become root-relative intervals (any count, so
4-note cues for gen4 and beyond are first-class). Never truncates:
builds via mkCadenceStatePCs, so all pitch content survives into the
cue. Enharmonics follow the typed accidentals (Eb spells flat,
D sharp; double accidentals accepted and resolved). An optional
(N) token fixes the approach movement, otherwise it is randomized
exactly like lead. Unrecognized tokens are reported and skipped;
with no valid notes at all, falls back to fully random lead.
Examples:
start <- lead' "Eb Gb Bb Db" -- Eb m7, random movement
start <- lead' "A C E G (5)" -- A m7, ascending 5th approach
start <- lead' "C E G" -- plain triad, same as lead "C maj"
parseLeadTokens :: String -> [LeadToken] Source #
Parse a lead string into a list of typed tokens. Each space-separated token is independently classified as root, quality, or movement.