karplus

karplus · sources

Extended Karplus-Strong STRING/HARP VOICE built on the COFEFVE DELAY's own fractional delay-line core (owner directive — no parallel delay implementation): a strike fires a seeded noise burst into a recirculating delay-line "string" and the ring IS the note, decaying like a real vibrating string. The full Jaffe–Smith/CCRMA EKS extension set, curated to 6 voice knobs + CV: DECAY is t60 in real SECONDS, frequency-compensated with the ρ = 0.001^(1/(f0·t60)) per-period loss law so low notes do NOT ring 10× longer than high ones (the classic K-S sin, fixed); BRIGHT is the string material — an in-loop damping low-pass whose cutoff TRACKS the note (fc = f0·2^(0.5+5.5·knob), so ≈1.4×f0 felt-dark … 64×f0 steel-bright, the Rings damping vocabulary), phase-compensated at f0 so it never detunes the note (below BRIGHT ≈0.1 the safety cap on loop gain does shorten it — a dark string cannot ring for 10 s); POS is the pick position (feedforward comb at β of the period — β=0.5 cancels even harmonics for a hollow mid-pluck, small β = bridge-thin); STIFF adds dispersion allpasses that stretch upper partials SHARP toward piano wire / bell / gong; COLOR (200 Hz mallet → 10 kHz pick low-pass) and BURST (0.1–4 PERIODS of noise, energy-normalized: near-impulse tick → classic 1-period pluck → scraped/bowed onset) shape the exciter. Tuning: 1 V/oct (f0 = Tune × 2^V, 30 Hz–4.2 kHz) with every loop stage's phase delay at f0 compensated in closed form and the fraction realized by the cofefve Catmull-Rom read — measured ≤ 0.1 cents across C2–C7 (unit-gated < 3). Inputs: trigger_in (edge-trigger STRIKE, burst reseeded per hit — deterministic), pitch (1 V/oct), accent_in (per-hit velocity latched at the edge: louder + brighter), damp_in (level-sensitive palm mute WHILE high, ~50 ms choke), plus a per-control CV on EVERY one of the eight knobs (tune_cv/decay_cv/bright_cv/position_cv/stiff_cv/color_cv/burst_cv/level_cv — each ±1 sweeps its param full-range around the knob, all 80 Hz-smoothed in the worklet, so `pitch` is the module's only genuinely audio-rate input). Mono out (the string tap, taken pre-damping) with LEVEL −24..+12 dB. Card: STRING·EXCITER fader bands + a PLUCK audition button (fires the canonical shared trigger pulse). RACKLINE face (?shell=1): hero ranks DECAY + BRIGHT with a live output scope; pages string·ring / pick·strike / output; rear card groups the four play jacks into a striking hand (STRIKE + ACCENT) and a fretting hand (1 V/OCT + DAMP). Stability is proven, not hoped: modes k ≥ 1 are bounded by ρ < 1 and the k = 0 loop mode is pinned below unity by an f0-tracked DC blocker (unit-gated at the hostile knob extremes).

A plucked/struck STRING voice — the extended Karplus-Strong algorithm, physical-modeling's original trick: instead of an oscillator plus filter, a short burst of noise is fired into a recirculating delay-line 'string' and everything you hear is that burst ringing around the loop, decaying naturally like a real vibrating string. There is no envelope generator anywhere in it: the note's shape IS the string losing energy. KARPLUS builds the loop on the COFEFVE DELAY's own fractional delay-line core and extends it the Jaffe–Smith/CCRMA way: the loop delay is tuned with sub-sample precision (1 V/oct is unit-gated under 3 cents across five octaves, C2–C7, at 44.1 and 48 kHz and with the tone knobs off their defaults — a naively rounded delay would be audibly sour above C5), and the per-period loop loss is frequency-COMPENSATED so the DECAY knob reads in real seconds at every pitch (classic K-S low notes drone for tens of seconds while high notes choke in milliseconds — fixed here). Six voice knobs then span the string and how it is struck: BRIGHT is the material (an in-loop damping low-pass whose cutoff tracks the note — felt-damped nylon to ringing steel), POS is where you pluck it (a comb filter: bridge-thin to hollow mid-string), STIFF bends the partials sharp toward piano wire, bells and gongs (dispersion allpasses), and COLOR + BURST shape the EXCITER itself — from a soft dark mallet thump (short, low-passed) through the classic pluck (exactly one period of noise) to a scraped/bowed attack (several periods of bright noise). It has no exciter of its own, so it needs a STRIKE: patch any trigger, clock or drum-lane gate (the PLUCK button — on the card, and on the dock faceplate's pick/strike band — auditions one hit with nothing patched). ACCENT gives each hit its own velocity — louder AND brighter, latched at the strike edge — DAMP is a palm mute while held, and EVERY one of the eight knobs has its own CV input. One mono voice: patch several for chords, or clock it fast for harp arpeggios.

the faceplate

karplustrigger_ingatepitchpitchaccent_incvdamp_ingatedecay_cvcvbright_cvcvposition_cvcvstiff_cvcvcolor_cvcvtune_cvcvburst_cvcvlevel_cvcvoutaudioaudiocvgatepitch
12 inputs · 1 outputs · 8 params

inputs

idcablewhat it does
trigger_ingateThe STRIKE/pluck: each rising edge fires one excitation burst into the string. At that instant the burst noise is re-seeded (so hit N sounds bit-identical to hit 1) and the ACCENT input and BURST length are both sampled. How long the signal stays high doesn't matter — it's a trigger, not a hold. The string is NOT cleared first, so a still-ringing note is re-plucked on top of its own ring-over, exactly like a real string. Patch a sequencer gate, clock or drum-seq lane here; the PLUCK button on either surface fires the same pulse for auditioning.
gate / trigger; trigger — fires once per rising edge
pitchpitch1 V/oct pitch input: transposes the whole voice as a true frequency multiplier (f0 = Tune × 2^volts, clamped to 30 Hz–4.2 kHz). Note that 0 V plays the TUNE knob itself (220 Hz = A3 by default), not a fixed C4 — this is a free-tuned voice, like a VCO's coarse tune. Tuning is compensated stage by stage, so melodic sequences from a quantizer/sequencer play in tune (measured ≤ 0.1 cents across C2–C7). This is the ONE input the DSP reads raw at audio rate — the delay line's ~10 ms read-pointer ease is the only smoothing on it, so slow moves glide like a slide guitar and fast ones are real FM.
V/oct pitch CV
accent_incvPer-hit velocity CV (0..1), LATCHED at the strike edge only — between hits it's ignored, so an LFO or sequencer accent lane gives each pluck its own dynamics. A full-scale accent makes the hit both LOUDER (burst amplitude 0.55 → 0.95, about +4.7 dB) and BRIGHTER (COLOR is pushed +0.25 up its 0–1 scale for that hit only), which is what plucking harder actually does.
control voltage (CV)
damp_ingatePalm-mute gate (level-sensitive): WHILE the level is high the string's decay collapses to ~50 ms — the ring chokes like a hand laid on a harp string — and on the falling edge the mute releases so the next strike rings freely again. Both edges matter: hold it to keep the string dead, pulse it to clip tails. Striking INTO a held mute still works and gives you a short muted-picking thunk, so a gate lane running alongside the trigger lane articulates the part.
gate / trigger; gate — acts while the level is high (reacts to both edges)
decay_cvcvCV modulation of DECAY (log-scaled): ±1 multiplies or divides the ring-out time by 10 around the knob — from the 2 s default that is 0.2 s … 10 s. Sequence it to alternate staccato plinks with long ringing notes. Like all eight knob CVs it is smoothed by an 80 Hz one-pole inside the worklet, so it is a control-rate input, not an audio-rate one.
control voltage (CV); modulates decay (multiplicative ≈ octaves — ±1 CV spans the param’s log range)
bright_cvcvCV modulation of BRIGHT (linear): ±1 moves the material ±0.5 up its 0–1 scale, so the pair of extremes spans the whole knob centred on your setting. A decaying envelope here mimics a real string whose tone darkens as it fades.
control voltage (CV); modulates brightness (additive offset — ±1 CV sweeps the full range, centered on the knob)
position_cvcvCV modulation of POS (linear): ±1 moves the virtual pluck point ±0.24 along its 0.02–0.5 travel — comb-filter animation like a player drifting between the bridge and the middle of the string. Sample-and-hold it per step for a different pluck point on every note.
control voltage (CV); modulates position (additive offset — ±1 CV sweeps the full range, centered on the knob)
stiff_cvcvCV modulation of STIFF (linear): ±1 moves inharmonicity ±0.5 up its 0–1 scale. From the 0 default a positive CV alone reaches 0.5 (piano-wire to early bell); raise the knob first if you want the full metallic zone under CV. Great per-step for alternating string and chime timbres.
control voltage (CV); modulates stiffness (additive offset — ±1 CV sweeps the full range, centered on the knob)
color_cvcvCV modulation of COLOR (linear): ±1 moves the exciter's tone ±0.5 up its 0–1 scale — soft mallet strikes to hard bright picks under sequencer control. It only shapes noise WHILE the burst is being generated (a few ms), so in practice a change lands on the NEXT strike.
control voltage (CV); modulates color (additive offset — ±1 CV sweeps the full range, centered on the knob)
tune_cvcvCV modulation of TUNE (log-scaled): ±1 multiplies or divides the string's base pitch by √(1760/55) ≈ 5.66 — about ±2½ octaves each way around the knob, so the two extremes span the knob's full 55–1760 Hz range (clamped at the ends). An LFO gives vibrato, a sequencer plays melodic runs. Distinct from the 1 V/oct pitch input, and unlike it this one is smoothed at 80 Hz before the loop retunes.
control voltage (CV); modulates tune (multiplicative ≈ octaves — ±1 CV spans the param’s log range)
burst_cvcvCV modulation of BURST (log-scaled): ±1 multiplies or divides the exciter length by √(4/0.1) ≈ 6.3 around the knob, morphing the attack from percussive tick to scraped/bowed. The length is LATCHED at the strike edge, so a change is heard on the next strike.
control voltage (CV); modulates burst (multiplicative ≈ octaves — ±1 CV spans the param’s log range)
level_cvcvCV modulation of LEVEL (linear): ±1 moves the output gain ±18 dB around the knob (the two extremes span its full 36 dB range) — an envelope or LFO here gives the voice tremolo or dynamic swells.
control voltage (CV); modulates level (additive offset — ±1 CV sweeps the full range, centered on the knob)

outputs

idcablewhat it does
outaudioThe string itself — the mono voice output, tapped straight off the delay line BEFORE the damping filter (the brightest point of the loop), scaled by LEVEL. Stability is proven rather than hoped: every loop mode above the fundamental is bounded below unity by the decay law, and an f0-tracked DC blocker inside the loop pins the lowest mode, so the line cannot run away or drift onto an offset at any knob setting. Feed it to a VCA/mixer or straight to an output — the voice's own envelope IS the string decay, no ADSR needed.
audio signal

params

idlabelrangedefaultcurve
tuneTune55..1760Hz220log
decayDecay0.1..10s2log
brightnessBright0..10.7linear
positionPos0.02..0.50.2linear
stiffnessStiff0..10linear
colorColor0..10.6linear
burstBurst0.1..41log
levelLevel-24..12dB0linear

controls

controlwhat it does
BrightBRIGHT — the string material: an in-loop damping low-pass whose cutoff TRACKS the note (fc = f0 · 2^(0.5 + 5.5·knob), i.e. ≈1.4×f0 at 0 up to 64×f0 at 1), so the knob means the same thing at every pitch. 0 = felt-muted nylon, where even the 2nd partial is heavily damped; 1 = ringing steel/glass with a near-lossless top. Its phase delay at the fundamental is compensated in closed form, so moving this knob NEVER detunes the string. It does interact with DECAY at the dark end — below ≈0.1 the loop-gain cap shortens the note (see DECAY).
BurstBURST — exciter length in PERIODS of the note (0.1–4, log). 0.1 = a near-impulse tick (percussive harp/marimba attack), 1 = the classic Karplus-Strong pluck (fills the string exactly once), 4 = a noisy scraped/bowed onset. Energy-normalized (1/√periods) so short ticks and long scrapes land at comparable loudness. Because it is measured in periods rather than milliseconds, the attack character stays consistent across the keyboard. The length is fixed at the strike edge, so it takes effect on the next hit.
ColorCOLOR — the exciter's tone: a low-pass on the noise burst sweeping 200 Hz → 10 kHz exponentially (0 = soft felt mallet / thumb, 1 = hard pick / metal tine). Dark bursts put proportionally more energy into the string's lower modes, so the whole note sounds rounder — not just the attack. An accented hit pushes this up +0.25 for that hit only.
DecayDECAY — ring-out time to −60 dB in SECONDS (0.1–10, log), frequency-compensated (the Jaffe–Smith ρ law): 2 s means 2 s at C2 AND at C6, instead of the classic Karplus-Strong behaviour where low notes drone and high notes choke. Short = plucked staccato/koto; long = open piano strings. ONE caveat, and it is audible: compensating a very dark string would need more loop gain than is safe, so the loop gain is capped. The full 0.1–10 s range is honoured down to BRIGHT ≈0.1 (the same threshold at every pitch); BELOW that the note decays SOONER than the knob says — at BRIGHT 0 the real ceiling is about 0.3 s at A3 and 0.07 s at A5. That is a heavily muted string, which cannot physically ring for ten seconds either. The DAMP gate overrides the knob entirely to ~50 ms while it is held.
Karplus strike {n}PLUCK — the audition button: one strike, exactly as if a rising edge had arrived at trigger_in. karplus has no exciter of its own, so with nothing patched into trigger_in it is not quiet, it is MUTE — this is how you hear the string while you are dialling it in, which is most of the time you are dialling it in. Mechanically it is a host-side source summed into the same trigger input a cable feeds, fired through the shared trigger waveform, so it behaves identically to a patched sequencer gate: the burst noise is re-seeded, BURST length and accent_in are latched at that instant (unpatched accent reads 0, i.e. an un-accented pluck), and the string is NOT cleared first, so hitting it again over a ringing note re-plucks on top of the ring-over. It writes NOTHING to the patch — no param moves, nothing is shared with the rackspace, nothing is persisted or undoable — and a cable already patched into trigger_in keeps working while you use it (Web Audio sums the two, and the worklet edge-detects the crossing).
LevelLEVEL — output gain in dB (−24..+12, default 0). The string loop is stability-bounded on its own, but nothing normalizes the voice's loudness across settings — a bright, long, hard-picked note is far hotter than a dark mallet thump, so use LEVEL to sit it in the mix or to drive a downstream stage. That is why it earns a lane rank on this module rather than sitting in the dock: the two knobs that cause the swing, DECAY and BRIGHT, are the two knobs beside it.
PosPOS — pick position β along the string (0.02–0.5): a feedforward comb on the exciter that subtracts a copy of the burst delayed by β of the period. 0.5 = plucked dead-centre: even harmonics cancel for a hollow, clarinet-ish pluck; small values = plucked at the bridge: thin, bright, all harmonics present. 0.12–0.25 is the natural guitar/harp zone. It shapes the EXCITER, not the loop, so it colours each hit rather than the ring-out.
StiffSTIFF — string stiffness/inharmonicity (0–1): two dispersion allpasses in the loop make upper partials run ahead of the fundamental, stretching them SHARP like real piano wire — and well past it. 0 = a perfectly harmonic string (the allpasses stay in the loop but become plain unit delays, so the knob is continuous with no topology switch); small amounts = piano realism; high values = detuned metallic clang and bell. The taper is set so the knob is audible at EVERY pitch, not just the top octaves — at A3 the third partial walks ≥ +45 cents sharp by full travel (unit-gated). Above ≈A5 the dispersion is capped at half the period so the loop stays tunable, which softens the effect on the very highest notes. The fundamental itself stays in tune at any setting: the tuning compensation accounts for the allpasses exactly.
TuneTUNE — the string's base pitch (55–1760 Hz, log; default 220 Hz = A3). This is a coarse tune, not a keyboard reference: the pitch input multiplies it at 1 V/oct, so 0 V plays whatever TUNE says. Together they cover 30 Hz–4.2 kHz, where the voice clamps.

source

karplus.ts on GitHub.

Generated from packages/web/src/lib/{audio,video}/module-registry.ts · repo