Pluck.

A string is a ring buffer, a filter and a feedback path. Play the fretboard below, or press the keys, and watch that ring buffer while it sounds. Every note here is one loop of about ten lines of arithmetic.

The delay line, while it rings

This is the loop buffer itself, drawn from the read head so the wave holds still instead of scrolling past. Watch the pluck start as a jagged burst and get rounded off a little more on every trip around, until only the fundamental is left. The height is auto gained so the shape stays readable as the note fades; the teal meter along the bottom and the figure beside it are the real level, in dB below where the note started.

Spectrum of the last note

Vertical ticks are the harmonics. Ones drawn in red are the harmonics the pick position cancels, predicted before the note was rendered.

Controls

Fretboard, standard tuning

Keys: Z X C V B N pluck the six open strings low to high. 1 to 9 set the fret those keys play. Space strums the last chord.
What is actually happening
delay N ring buffer one zero brightness allpass a the fraction pluck out feedback, gain g

The loop. Fill a buffer of N samples with something noisy. Then read it out one sample at a time, and every time you read one, put a filtered copy of it back at the other end. The buffer contents come round again every N samples, so the output repeats at sample rate / N hertz, which is the pitch. The filter shaves a little off the high frequencies on every pass, so the jagged noise smooths into a sine and fades out. That is the whole algorithm, and it was published in 1983.

Why the allpass is there. N is a whole number, so a plain loop can only make the pitches 44100 / N. Around the top of the neck those land tens of cents apart, which is out of tune by any standard. The first order allpass filter has flat gain and a phase delay you can dial in, so it supplies the leftover fraction of a sample. Its coefficient is exact rather than approximate: a = sin((1-d)w/2) / sin((1+d)w/2) gives a phase delay of d samples at angular frequency w. Switch the tuning control to Integer and read the cents error above to see what it is worth.

Why the loop filter has to be measured. The one zero filter contributes its own phase delay to the loop, so the delay you need from the buffer is not 44100 / f, it is that minus whatever the filter is already supplying. The readout shows all three parts adding up: N whole samples, d from the allpass, and the filter's share.

Pick position. Plucking a real string a fraction p of the way along it cannot excite any harmonic that has a node at that point, so those harmonics go missing. The model here is a comb: subtract the signal from a copy of itself delayed by p times the loop period, which cancels every harmonic that is a multiple of 1/p. Set pick position to 0.5 and the whole even harmonic series disappears, which is why plucking a guitar over the twelfth fret sounds hollow and flute like. Two details matter more than they look. The delay is a fraction of a sample and is interpolated, because rounding it to a whole sample drags the null off the harmonic it is aiming at. And it is a fraction of the LOOP period rather than of the buffer length, which differ by up to a sample and a half: combing against the buffer instead left the null 13 dB deep here, where doing it properly reaches 43 to 57 dB.

Decay, and the bucket brigade. The loop gain sits inside a per sample loop, which makes it look like a per sample control. It is not. A delay line is a bucket brigade, so any one sample is multiplied by that gain once per trip around the buffer, and there are only f0 trips a second. Getting that backwards puts the decay out by a factor of the delay length. The loop filter also takes its own bite on every trip, so the gain here has the filter's loss at the fundamental divided back out. That is why moving Brightness changes the tone of the note without changing how long it lasts, which is not what the classic algorithm does and is the point of having two knobs.

Sign coherence. Drop it below 1 and the fed back sample gets its sign flipped at random. Periodicity is what makes a pitch, so destroying it turns the string into a drum without changing a single other thing. At 0.5 it is pure noise burst percussion.

Honest limits. The delay line is drawn as the string, and it is really the travelling wave state of the loop, not a physical displacement, though the shape of the decay is the real thing. The body resonance is three fixed resonators and is not modelled on any instrument. Everything renders offline before it plays, so the knobs affect the next note, not the one currently sounding, which is also true of a real pluck.