Karplus-Strong
Tier: Primitives | ComponentType: 39 | Params: 5
Plucked string physical model using a filtered delay loop with noise excitation.
Overview
KarplusStrong simulates a plucked string by filling a delay buffer with filtered noise (the "pluck") and then circulating it through a feedback loop with lowpass damping and energy decay. The delay length determines the pitch, the damping filter simulates frequency-dependent string loss, and the decay parameter controls how quickly the string dies away.
A brightness parameter filters the initial noise excitation (pre-pluck), and a pluck position parameter applies a comb filter to the excitation, mimicking the tonal effect of plucking at different positions along the string (near bridge = bright, near center = mellow).
File Locations
| Path | |
|---|---|
| Header | Sources/FolioDSP/include/FolioDSP/Primitives/KarplusStrong.h |
| Implementation | Sources/FolioDSP/src/Primitives/KarplusStrong.cpp |
| Tests | Tests/FolioDSPTests/KarplusStrongTests.swift |
| Bridge | Sources/FolioDSPBridge/src/FolioDSPBridge.mm (KarplusStrongBridge) |
Parameters
| Index | Name | Description | Min | Max | Default Min | Default Max | Default | Unit |
|---|---|---|---|---|---|---|---|---|
| 0 | Frequency | Fundamental pitch of the string | 20.0 | 5000.0 | 60.0 | 1000.0 | 220.0 | Hz |
| 1 | Damping | Lowpass damping in feedback loop (0=bright, 1=dark) | 0.0 | 1.0 | 0.0 | 1.0 | 0.5 | |
| 2 | Decay | Energy retention per cycle (0.99=fast, 1.0=infinite) | 0.9 | 1.0 | 0.99 | 1.0 | 0.998 | |
| 3 | Pluck Position | Position along string (0=bridge, 0.5=center) | 0.0 | 0.5 | 0.0 | 0.5 | 0.0 | |
| 4 | Brightness | Pre-filter on excitation noise (0=dark, 1=bright) | 0.0 | 1.0 | 0.0 | 1.0 | 1.0 |
Processing Algorithm
1. Excitation (on excite() call)
Noise burst fills the delay buffer behind the write pointer:
Brightness pre-filter (one-pole LP on noise):
Pluck position comb filter (subtracts delayed copy):
where \(p\) = pluck position, \(L\) = delay length.
2. Read from Delay (linear interpolation)
3. One-Pole LP Damping
4. Decay
5. Write Back
6. DC Blocker
where \(R = 1 - 2\pi \cdot 10 / f_s\).
Snapshot Fields
| Field | Type | Range | Unit | Description |
|---|---|---|---|---|
| Frequency | Float | 20–5000 | Hz | Current frequency |
| Damping | Float | 0–1 | Current damping | |
| Decay | Float | 0.9–1.0 | Current decay | |
| Pluck Position | Float | 0–0.5 | Current position | |
| Output Level | Float | 0–1 | Smoothed output | |
| Energy | Float | 0–1 | Remaining string energy | |
| Ringing | Bool | 0–1 | Whether string is still sounding |
Implementation Notes
- 4096-sample raw delay buffer (NOT CircularBuffer template) -- supports frequencies down to ~10.7 Hz
- xorshift32 PRNG for noise excitation
- Noise is written BEHIND writePos so the delay reader picks it up immediately
- Pluck position comb filter creates spectral nulls at harmonics corresponding to the pluck point
- ParamSmoother on all parameters for stable real-time modulation
- DC blocker essential for removing subsonic drift from the feedback loop
Equation Summary
y = delay[f] · LP(damping) · decay