marbles
marbles · sourcesRandom sampler / clock generator (Mutable Instruments Marbles archetype, Émilie Gillet, MIT-licensed). Clean-room TypeScript port of the eurorack/marbles/ DSP. The T-section (t1 / t2 gates) generates clocked random gates via one of six models — COIN (complementary Bernoulli), CLUSTERS, DRUMS (18 built-in 8-step patterns), INDEP (independent Bernoulli), 3-STATE, MARKOV — with a déjà-vu loop that locks the random stream into a repeating pattern (RATE / T BIAS / T JITTER / DÉJÀ VU / LENGTH). The X-section (x1 / x2 / x3 CV) draws random voltages shaped by SPREAD (variance), X BIAS (mean), and STEPS (quantization amount + STEPS-knob portamento), snapped through a weight-aware variable-resolution quantizer onto one of six scales (C major / C minor / Pentatonic / Pelog / Raag Bhairav / Raag Shri), with its own déjà-vu loop shared across the three X channels via pseudo-random hash shifts. clk is the master clock. CV outs are ±1 (= ±5V). Beta-distribution sampling is approximated analytically vs the firmware's precomputed table; the déjà-vu / Markov / quantizer / lag logic is ported line-for-line.
the faceplate
inputs
| id | cable | what it does |
|---|---|---|
rate_cv | cv | CV that modulates the master clock Rate (in semitones, summed with the knob) — speeds up or slows down both the T and X sections together. The law is exact: f = 2 Hz x 2^(RATE/12). control voltage (CV); modulates rate (additive offset — ±1 CV sweeps the full range, centered on the knob) |
tmodel_cv | cv | Discrete CV that modulates the T-section Model select, stepping between COIN / CLUSTERS / DRUMS / INDEP / 3-STATE / MARKOV. Note that CLUSTERS is not implemented in this port and behaves exactly as COIN, so the six positions are five behaviours. control voltage (CV); modulates t_model (integer buckets — CV selects a discrete step) |
tbias_cv | cv | CV that modulates the T-section Bias (0..1, summed with the knob) — for the two Bernoulli models it sets the split directly, P(t1) = 1 - Bias, and the two gates share every clock between them. control voltage (CV); modulates t_bias (additive offset — ±1 CV sweeps the full range, centered on the knob) |
tjitter_cv | cv | CV that modulates the T-section Jitter (0..1) — adds or removes timing humanization on the random gates. It is a zero-mean displacement, so the average tempo does not move with it. control voltage (CV); modulates t_jitter (additive offset — ±1 CV sweeps the full range, centered on the knob) |
dejavu_cv | cv | CV that modulates the T-section Déjà Vu (0..1). Not a monotone lock: the loop is tightest at 0.5 and both ends of the range are equally disordered — below 0.5 by re-rolling values, above it by jumping around the loop it already has. control voltage (CV); modulates deja_vu (additive offset — ±1 CV sweeps the full range, centered on the knob) |
length_cv | cv | CV that modulates the T loop Length (1..16 steps). It has no effect at all while Déjà Vu is 0, where every step re-rolls and the loop is never read back. control voltage (CV); modulates length (additive offset — ±1 CV sweeps the full range, centered on the knob) |
spread_cv | cv | CV that modulates the X-section Spread (0..1) — widens or narrows how far the three random voltages wander. Both ends are degenerate: at 0.01 and below the outputs are a DC constant, at 0.99 and above a two-level coin flip. control voltage (CV); modulates spread (additive offset — ±1 CV sweeps the full range, centered on the knob) |
xbias_cv | cv | CV that modulates the X-section Bias (0..1) — shifts the centre of the three random voltages, and sets WHERE the two degenerate ends of Spread land (a DC of 10*Bias - 5 volts, or the probability of the +5 V side of the coin flip). control voltage (CV); modulates x_bias (additive offset — ±1 CV sweeps the full range, centered on the knob) |
steps_cv | cv | CV that modulates the X-section Steps (0..1). Below 0.5 it is the portamento TIME — 0 glides for most of a step, and the glide is gone by 0.49. From 0.536 it is the quantizer depth instead, in seven levels. control voltage (CV); modulates steps (additive offset — ±1 CV sweeps the full range, centered on the knob) |
xdejavu_cv | cv | CV that modulates the X-section Déjà Vu (0..1) — the same non-monotone law as the T one, applied to the three control voltages. control voltage (CV); modulates x_deja_vu (additive offset — ±1 CV sweeps the full range, centered on the knob) |
scale_cv | cv | Discrete CV that modulates the X-section quantizer Scale select (C major, C minor, pentatonic, Pelog, Raag Bhairav, Raag Shri). It does nothing while Steps is below 0.536. control voltage (CV); modulates scale (integer buckets — CV selects a discrete step) |
outputs
| id | cable | what it does |
|---|---|---|
t1 | gate | First random gate from the T section, opening per the selected model's logic and bias. Its width is a FIXED fraction of the step — 5% + 90% x PWidth, the same for every gate — not a per-gate random span. Patch into a drum or envelope input. gate / trigger; gate — acts while the level is high (reacts to both edges) |
t2 | gate | Second random gate from the T section — complementary to t1 under COIN and CLUSTERS (exactly one of the two opens on every clock) and independent of it under INDEP (both can open at once, or neither). It stays high for the same fixed fraction of the step as t1 — 5% + 90% x PWidth — so the two together build call-and-response rhythms at a matched gate length. gate / trigger; gate — acts while the level is high (reacts to both edges) |
x1 | cv | First random control voltage from the X section, shaped by Spread and Bias, lagged or quantized by Steps, and snapped to the chosen Scale when the quantizer is engaged. Patch into a pitch input. control voltage (CV) |
x2 | cv | Second random control voltage, decorrelated from x1 — a different but related stream for a second voice or parameter. control voltage (CV) |
x3 | cv | Third random control voltage, decorrelated from x1 and x2 — a third independent stream. control voltage (CV) |
clk | gate | The master clock output that paces both sections. A 50% square at EVERY setting — PWidth moves the t1/t2 gate width and leaves this untouched — so clocking another module from here gives it a half-step gate regardless of how tight the T gates are set. gate / trigger; trigger — fires once per rising edge |
params
| id | label | range | default | curve |
|---|---|---|---|---|
rate | Rate | -60..60st | 0 | linear |
t_model | T Model | 0..? | 0 | discrete |
t_bias | T Bias | 0..1 | 0.5 | linear |
t_jitter | T Jitter | 0..1 | 0 | linear |
deja_vu | Déjà Vu | 0..1 | 0 | linear |
length | Length | 1..16 | 8 | discrete |
pw_mean | PWidth | 0..1 | 0.5 | linear |
spread | Spread | 0..1 | 0.5 | linear |
x_bias | X Bias | 0..1 | 0.5 | linear |
steps | Steps | 0..1 | 0.5 | linear |
x_deja_vu | X Déjà Vu | 0..1 | 0 | linear |
x_length | X Length | 1..16 | 8 | discrete |
scale | Scale | 0..? | 0 | discrete |
controls
| control | what it does |
|---|---|
| Déjà Vu | The T-section loop control (0..1), and its maximum is its MIDDLE. The per-step probability of departing from the loop is (2*dv - 1)^2: at 0 that is 1, so every step is a fresh random value and there is no loop; at 0.5 it is 0 and the loop plays back verbatim — this is the tightest setting; above 0.5 the loop's contents are frozen but each step may JUMP to a random position in it, with the same probability curve rising back to 1 at the top. So turning it past 12 o'clock makes the pattern repeat LESS. |
| Length | How many steps long the T-section loop is (1..16). BIT-EXACTLY INERT while Déjà Vu is 0 — the shipped default — because at that setting every step overwrites the slot it is about to read, so no loop is ever played back. Move Déjà Vu off zero before this control does anything. |
| Marbles loop {n} | The faceplate picture: one row of slots per section (T and X) showing each loop's length and how much of it survives a step, plus a one-octave ruler marking which of the current scale's degrees the quantizer is keeping. A section with no loop draws a single slot rather than a length it is not honouring, and an empty ruler means the quantizer is off. |
| PWidth | The width of the t1/t2 gates as a fraction of the step: exactly 5% + 90% x PWidth, the same for every gate. It does NOT affect clk, which stays a 50% square at every setting. |
| Rate | Master clock rate in semitones (-60..+60). Exact law: f = 2 Hz x 2^(RATE/12), i.e. 120 BPM at 0, 3.75 BPM at -60 (one pulse every 16 seconds) and 3840 BPM at +60. It drives both the T gates and the X voltages, and the clk output. |
| Scale | The quantizer scale the X voltages snap to: C major, C minor, pentatonic, Pelog, Raag Bhairav, or Raag Shri. Each scale weights its degrees, and the Steps level decides how many of them survive — so the six scales are only ALL distinguishable in the middle of the quantizer's range (Steps 0.607 to 0.893). Below Steps 0.536 the quantizer is off and Scale does nothing at all; at the very top only the root survives and every scale gives octaves. |
| Spread | How far the three X voltages wander from the centre (0..1). BOTH ENDS ARE DEGENERATE: at 0.01 and below all three outputs collapse to a DC constant at 10*XBias - 5 volts (0 V at the default Bias), and at 0.99 and above they become a two-level coin flip between -5 V and +5 V rather than a continuous voltage. The useful range is everything in between. |
| Steps | TWO CONTROLS IN ONE DIAL, with a gap between them. Below 0.5 it is the PORTAMENTO time: at 0 the voltages glide for roughly 90% of a step, and the glide shrinks to nothing by 0.49. From 0.5 the output steps hard. The QUANTIZER does not engage until 0.536, and then runs in seven levels up to the top, each level keeping fewer of the scale's degrees. The shipped default of 0.5 sits in the gap: no glide left, no quantization yet, and therefore no Scale. |
| T Bias | Sets the t1/t2 split. Under the two Bernoulli models the law is exact — P(t1) = 1 - Bias, so 0 sends every gate to t1 and 1 sends every gate to t2 — and the two outputs always share the clock between them. Under DRUMS it picks the pattern, under 3-STATE it steers all three outcomes, and under MARKOV it steers the transition logit. |
| T Jitter | Adds timing humanization to the T gates (0..1): 0 is metronomic, higher values loosen the placement. The displacement is zero-mean, so the average tempo is unchanged (measured stable to 0.44% across the whole range while the spread of intervals grows without bound). |
| T Model | Picks the T-section gate model: COIN (a complementary coin toss — exactly one of t1/t2 fires per clock), CLUSTERS, DRUMS (18 fixed 8-step patterns), INDEP (two independent coins, so both gates can fire on one clock or neither), 3-STATE (a clock can pass with no gate at all), or MARKOV (a state machine over its own recent history). CLUSTERS IS NOT IMPLEMENTED in this port: the DSP falls through to the COIN generator for it, so the six named models are five behaviours and the faceplate prints CLUSTERS as 'CLUSTERS -> COIN'. |
| X Bias | The centre the three X voltages sit around (0..1), and the value that decides WHERE Spread's two degenerate ends land — the DC level at the bottom (10*XBias - 5 volts) and the odds of the +5 V side of the coin flip at the top. On its own, at the shipped Spread, it skews the distribution; it does not freeze it. |
| X Déjà Vu | The X-section loop control (0..1) — the same law as Déjà Vu, applied to the three voltages: (2*dv - 1)^2 is the chance a step departs from the loop, so repetition peaks at 0.5 and falls away toward BOTH ends. |
| X Length | How many steps long the X-section loop is (1..16). Bit-exactly inert while X Déjà Vu is 0, for the same reason as Length. |
source
marbles.ts on GitHub.