theHarmonicAlgorithm-3.0.0: Real-time harmonic progression generation for TidalCycles live performance
Safe HaskellSafe-Inferred
LanguageHaskell2010

Harmonic.Rules.Types.Progression

Description

This module defines Progression as a sequence of CadenceState values with Monoid structure for composability.

DESIGN DECISION (from evaluation): "Stick to the Strict interpretation for the data structure (Seq CadenceState). Let the VoiceLeading module handle the cost calculation separately. Don't over-complicate the data type itself."

Therefore: * mempty = empty progression * (<>) = simple concatenation (seam smoothing is handled externally)

The manipulation functions (rotate, excerpt, insert, etc.) are ported from legacy Arranger.hs to enable macro-level musical operations.

Synopsis

Core Type

newtype Progression Source #

A Progression is a sequence of CadenceStates. Using Seq for O(1) access to both ends and O(log n) concatenation.

Note: This is the "strict interpretation" - the sequence holds concrete states, and voice leading costs are computed externally when needed.

Constructors

Progression 

Instances

Instances details
Monoid Progression Source # 
Instance details

Defined in Harmonic.Rules.Types.Progression

Semigroup Progression Source #

Monoid instance: empty progression as identity, concatenation as operation. The "seam" between concatenated progressions is NOT automatically smoothed; that responsibility lies with the VoiceLeading module.

Instance details

Defined in Harmonic.Rules.Types.Progression

Generic Progression Source # 
Instance details

Defined in Harmonic.Rules.Types.Progression

Associated Types

type Rep Progression :: Type -> Type #

Show Progression Source #

Visual Show instance for Progression (ported from legacy MusicData.hs). Displays progressions in a 4-column grid with bar number labels. Each chord is rendered using the enharmonic spelling stored in its CadenceState root. The final grid shows consistent note names throughout the progression.

Instance details

Defined in Harmonic.Rules.Types.Progression

Eq Progression Source # 
Instance details

Defined in Harmonic.Rules.Types.Progression

type Rep Progression Source # 
Instance details

Defined in Harmonic.Rules.Types.Progression

type Rep Progression = D1 ('MetaData "Progression" "Harmonic.Rules.Types.Progression" "theHarmonicAlgorithm-3.0.0-1Jyc2qhqYzxBLoiBHPE0av" 'True) (C1 ('MetaCons "Progression" 'PrefixI 'True) (S1 ('MetaSel ('Just "unProgression") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Seq CadenceState))))

Construction

singleton :: CadenceState -> Progression Source #

Create a progression from a single CadenceState

fromCadenceStates :: [CadenceState] -> Progression Source #

Create a progression from a list of CadenceStates

fromChordStates :: [ChordState] -> Progression Source #

Create a progression from a list of ChordStates (inferring cadences) Each consecutive pair forms a cadence.

Queries

progLength :: Progression -> Int Source #

Get the length of a progression

progChords :: Progression -> [Chord] Source #

Extract all chords from a progression

progCadences :: Progression -> [Cadence] Source #

Extract all cadences from a progression

getCadenceState :: Progression -> Int -> Maybe CadenceState Source #

Get a CadenceState at a specific index (1-indexed for user friendliness)

getChordState :: Progression -> Int -> Maybe ChordState Source #

Get a ChordState at a specific index (derived from CadenceState)

Manipulation (ported from legacy Arranger.hs)

rotateProgression :: Int -> Progression -> Progression Source #

Rotate a progression by n positions Positive n rotates left (first elements move to end) Negative n rotates right (last elements move to front)

excerptProgression :: Int -> Int -> Progression -> Progression Source #

Extract a subsequence from a progression Start and end are 1-indexed, inclusive

insertProgression :: Int -> Progression -> Progression -> Progression Source #

Insert a progression at a specific position (1-indexed)

fuseProgression :: Progression -> Progression -> Progression Source #

Fuse (interleave) two progressions

transposeProgression :: Int -> Progression -> Progression Source #

Transpose a progression by n semitones

overlapProgression :: Int -> Progression -> Progression -> Progression Source #

Overlap two progressions (start second before first ends)

expandProgression :: Int -> Progression -> Progression Source #

Expand a progression by repeating it n times

Splice Operations

spliceProgression :: Progression -> Int -> Int -> [CadenceState] -> Progression Source #

Splice new chords into a progression, replacing a range (1-indexed, wrapping).

Non-wrapping (start <= end): replaces positions start..end. Wrapping (start > end): replaces start..N and 1..end. Fixes the movement at the seam where new chords meet kept chords.

fixMovementAt :: Int -> Progression -> Progression Source #

Fix the movement at a 1-indexed position by recomputing from predecessor's root.

Voicing Extractors

literalVoicing :: Progression -> [[Int]] Source #

Extract literal voicings (pitch integers as stored)

harmonyVoicing :: Progression -> [[Int]] Source #

Extract harmony voicings (pitch classes only, 0-11)

closeVoicing :: Progression -> [[Int]] Source #

Extract close voicings (smallest possible span)

wideVoicing :: Progression -> [[Int]] Source #

Extract wide voicings (spread across octaves)

Display Helpers

showTriad :: (PitchClass -> NoteName) -> Chord -> String Source #

Show a chord using the given enharmonic function. Ported from legacy MusicData.hs showTriad Maps the chord to a human-readable string representation with proper enharmonic spelling (e.g., "C maj" or "F# min/A")

showHarmony :: (PitchClass -> NoteName) -> CadenceState -> String Source #

Cardinality-dispatching display for a CadenceState. The display seam for every printed chord name (grid, scoreboard, traces, cue messages):

  • <= 3 intervals — the triad path (fromCadenceState / showTriad), byte-identical to the historical behaviour, including inversion detection and slash-chord rendering. All corpus-generated cadences have exactly 3 intervals, so this arm covers all gen/genP output.
  • 4-6 intervals — root name + the stored cadenceFunctionality (populated by toFunctionalityChord at construction). Recomputed only when the stored name is empty (legacy chroma states). No inversion vocabulary exists for extended harmonies.
  • 7 intervals — mode classification pinned at the state's root (classifyModeAt), falling back to the chord namer when the set doesn't classify.

Never reduces pitch content: replaces the old path that forced every state through toTriad's most-consonant reduction before naming.