Skip to content

Per-part clock divide + timing offset (polyrhythm / phasing) #3

Description

@philoking

Summary

Give each part its own clock divide and timing offset so the four lines don't all march on the same 16th grid. Today every part advances together at STEPS_PER_BAR = 16 (js/generator.js), driven globally by js/scheduler.js. Let the Pad run at 1/1, the bass at 1/4, the arp at 1/8-triplet, each optionally shifted by a 16th — and the lines drift into evolving, non-repeating polyrhythm.

Why it fits

Phasing and cross-rhythm are the most modular-native textures there are — exactly what you want under a long-evolving patch. Because the parts are already strictly monophonic and independently generated, staggering their rates is cheap musically and gives a lot of motion for very little UI.

Proposed scope

Per-part rate + offset (js/generator.js, js/scheduler.js)

  • Add per-part clockDiv (e.g. 1/1, 1/2, 1/4, 1/8, 1/16, plus triplet 1/4T, 1/8T) and offset (0, 1/16, 1/8, 3/16) to each entry in state.parts.
  • The scheduler already advances time incrementally; have each part decide whether this global step is one of its trigger steps given its divide, and apply its offset when stamping the note time.
  • Keep mono enforcement per part (drop coincident starts, clip before the next note / bar line) exactly as it works today.

The phasing trick (length ≠ length)

  • Allow a part's note-source length and its rhythmic length to differ, so the note pool rotates against the pulse and never lines up the same way twice. (Dovetails with the step/rhythm editor idea, but works on the generated streams too.)

UI (js/app.js)

  • Two selects in each part's ⚙ panel: Clock divide and Offset. Show the resulting feel (e.g. a "notes : beats" readout) so the polyrhythm is legible.

Where

js/generator.js (per-part step gating + offset), js/scheduler.js (time stamping), js/app.js (⚙ controls + state).

Done when

  • Each part can be set to a different clock divide and a 16th offset.
  • Triplet divides work against the straight grid.
  • Settings persist in presets / JSON.
  • Mono behaviour and clean gate retrigger are preserved per part.

Open questions

  • Should swing apply per divide, or stay global for now?
  • Cap on combined divides to avoid pathological density at high tempo?

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions