| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Harmonic.Interface.Tidal.Form
Description
Encodes macro-level compositional arc as programmable structure, realised as TidalCycles patterns, looping endlessly.
A form is a list of nodes. Each node fixes a point in time and the two signals that drive everything downstream: kinetics (how active the music is) and dynamics (how loud). Instruments gate themselves on kinetics, so the arc is written once and every line follows it.
Nodes come in two time bases — at takes wall-clock seconds, rh takes
bars (rehearsal marks). Primed variants (at', rh') snap rather than
interpolate, for a hard cut into a new section:
form = -- time k d [ rh 0 0.0 0.0 s , rh 16 0.2 0.3 s -- elements layer in , rh' 28 0.35 0.55 s -- riser: sparse but loud, then snap , rh 32 1.0 1.0 s -- drop ]
The form is compiled into an IK — the performance context every
instrument reads — by pairing it with a tempo and a chord-selection
pattern:
k = iK tempo form (warp "[1 2 3 4]/4")
The simplest useful form is a single constant node, which holds one progression at full kinetics forever:
form = [ at 0 1.0 1.0 s ]
Synopsis
- data FormNode = FormNode {}
- data FormTime
- data Transition
- data Kinetics = Kinetics {}
- type IK = (Kinetics, Pattern Int)
- at :: Double -> Double -> Double -> ProgressionContext -> FormNode
- at' :: Double -> Double -> Double -> ProgressionContext -> FormNode
- rh :: Double -> Double -> Double -> ProgressionContext -> FormNode
- rh' :: Double -> Double -> Double -> ProgressionContext -> FormNode
- iK :: Double -> [FormNode] -> Pattern Int -> IK
- lK :: Pattern Double -> Pattern Double -> ProgressionContext -> Pattern Int -> IK
- formK :: Double -> [FormNode] -> Kinetics
- ki :: (Double, Double) -> IK -> Pattern a -> Pattern a
- slate :: (Double, Double) -> IK -> [Pattern a] -> Pattern a
- kinPick :: IK -> [Pattern a] -> Pattern a
- withForm :: IK -> (ProgressionContext -> Pattern ValueMap) -> Pattern ValueMap
Types
A node in a form definition: a point in time with kinetics level, dynamic level, active progression, and the transition style of the section starting here.
Constructors
| FormNode | |
Fields
| |
A node's position in time — wall-clock Secs or musical Bars (4/4).
Resolved to Tidal cycles at realization (see formK). Mix freely in one form.
data Transition Source #
How a section moves to the next node: Smooth (ramped) or Snap
(hold this node's value, then jump on the next node's exact time).
Instances
| Show Transition Source # | |
Defined in Harmonic.Interface.Tidal.Form Methods showsPrec :: Int -> Transition -> ShowS # show :: Transition -> String # showList :: [Transition] -> ShowS # | |
| Eq Transition Source # | |
Defined in Harmonic.Interface.Tidal.Form | |
Realized form: continuous and discrete signals for live performance.
Constructors
| Kinetics | |
Fields
| |
type IK = (Kinetics, Pattern Int) Source #
Performance context: Kinetics bundled with chord selection pattern.
Reduces parameter threading — r and k are always passed together.
Construction
at :: Double -> Double -> Double -> ProgressionContext -> FormNode Source #
Form node builders. Time unit and transition are orthogonal:
at/at' take wall-clock seconds, rh/rh' take bars (rehearsal marks, 4/4);
unprimed = smooth transition, primed = snap. at is unchanged from before.
at 0 0 0 s seconds, smooth rh 8 0.5 0.5 s bars, smooth
at' 60 1 1 s seconds, snap rh' 16 0.9 0.9 s bars, snap
at' :: Double -> Double -> Double -> ProgressionContext -> FormNode Source #
Form node builders. Time unit and transition are orthogonal:
at/at' take wall-clock seconds, rh/rh' take bars (rehearsal marks, 4/4);
unprimed = smooth transition, primed = snap. at is unchanged from before.
at 0 0 0 s seconds, smooth rh 8 0.5 0.5 s bars, smooth
at' 60 1 1 s seconds, snap rh' 16 0.9 0.9 s bars, snap
rh :: Double -> Double -> Double -> ProgressionContext -> FormNode Source #
Form node builders. Time unit and transition are orthogonal:
at/at' take wall-clock seconds, rh/rh' take bars (rehearsal marks, 4/4);
unprimed = smooth transition, primed = snap. at is unchanged from before.
at 0 0 0 s seconds, smooth rh 8 0.5 0.5 s bars, smooth
at' 60 1 1 s seconds, snap rh' 16 0.9 0.9 s bars, snap
rh' :: Double -> Double -> Double -> ProgressionContext -> FormNode Source #
Form node builders. Time unit and transition are orthogonal:
at/at' take wall-clock seconds, rh/rh' take bars (rehearsal marks, 4/4);
unprimed = smooth transition, primed = snap. at is unchanged from before.
at 0 0 0 s seconds, smooth rh 8 0.5 0.5 s bars, smooth
at' 60 1 1 s seconds, snap rh' 16 0.9 0.9 s bars, snap
iK :: Double -> [FormNode] -> Pattern Int -> IK Source #
Construct performance context from BPM, form nodes, and chord selection.
k = iK tempo [at 0 0 0 s, at 30 1 1 s] (warp "[1 2 3 4]/8")
Arguments
| :: Pattern Double | Kinetics signal (0-1, live) |
| -> Pattern Double | Dynamics signal (0-1, live) |
| -> ProgressionContext | Active 3-layer progression |
| -> Pattern Int | Chord-selection pattern |
| -> IK |
Live kinetics: build IK from reactive kinetics/dynamics signals. Bypasses form interpolation — use when the envelope is driven by live input (e.g. MIDI CC) rather than a static keyframed form.
k = lK exP exP s r -- pedal drives both kinetics and dynamics
Realization
formK :: Double -> [FormNode] -> Kinetics Source #
Realize a form definition into Kinetics signals at a given BPM.
Single-node forms produce constant signals (global state).
Multi-node forms produce per-segment signals — smooth (ramp) or snap (step)
per each node's fnTrans — and a step-function progression, looping at the
form's total duration. Time is resolved from each node's FormTime.
Primitives
ki :: (Double, Double) -> IK -> Pattern a -> Pattern a Source #
Range gate: mask a pattern by kinetics signal level. Events pass only when kSignal is within the (lo, hi) range.
slate :: (Double, Double) -> IK -> [Pattern a] -> Pattern a Source #
Gated stack: stack patterns and gate by kinetics range.
kinPick :: IK -> [Pattern a] -> Pattern a Source #
Kinetics-windowed dispatch: partition [0,1] into N equal windows of width 1/N, where N = length pats, and play only the pattern whose window contains the current kSignal. Windows are derived at call time; any N >= 1 works (N=1 collapses to "always play this pattern").
Boundaries belong to the lower window: window i covers
(i/N, (i+1)/N], with window 0 also including 0. So at the boundary
between window i and window i+1, the lower window plays.
N=2 → [0, 1/2], (1/2, 1] N=3 → [0, 1/3], (1/3, 2/3], (2/3, 1]
Empty list → silence. Outside [0,1] → silence (no window matches).
withForm :: IK -> (ProgressionContext -> Pattern ValueMap) -> Pattern ValueMap Source #
Bridge helper: apply a function taking ProgressionContext to a Kinetics context.
Uses innerJoin to reactively switch when the form changes progressions.