top of page

Karplus Strong Algorithm in SuperCollider

Updated: Dec 10, 2019


Karplus Strong Overview



The Karplus-Strong algorithm, besides being one of the cutest algorithms I know, and my first foray into modelling the sound of an actual instrument in code (in it´s case a string sound) - is more generally, a CPU cost-effective way of synthesising a string sound on a computer and one of the earliest examples of physical modelling in computer music. It consists of a noise burst which is run through a feedback delay unit. The noise burst imitates the attack of the string, while the feedback delay unit provides the pitch and decay of the sound, characteristic of the natural decay of a plucked string.




The pitch of our Karplus Strong string is the result of the feedback loop. In the diagram above you see a short noise burst get passed to the output, but also get sent into a delay. This delay, let´s say, stops the sound or withholds it, before passing it (first to a filter) and then both out to the output and back into the delay line. The delay we are talking about is 0.01 (or one hundreths) of a second. So this noise burst repeated (100 times a second, will indeed produce a pitch of 100 Hz (100 times a second!).


The decay comes from using the delay line to dampen the sound. If on each rotation, we multiply the signal by 0.9 using a filter, which causes the overall sound to slowly lose power with each revolution of the feedback loop. This can be referred to as gain.



In Supercollider


Noise Burst

For our noise burst, we use Impulse.ar(0.5); This will send an Impulse every 30 seconds into our system.


Delay Line

Our delay is handled by an object called DelayC.ar Using an argument called del to define the speed of delay, we enter the value of 0.01, which will produce a pitch of 100 Hz. (100 times a second).


Decaying

With LPF.ar, we send the sound through a filter and multiply it by our gain factor 0.9. This dampens, or decays our sound.


Feedback Loop

LocalOut.ar sends the sound immediately to LocalIn.ar, its counterpart. Then you will notice the sound from LocalIn is sent immediately back into the delay line. This is the main source of our feedback loop.


Tuning the Thing!

**One drawback of LocalIn and LocalOut is that the introduce a delay of their own, this is simply a result of the computer's processing speed. The time it takes the computer to process a "block size" of samples, is the extra amount of time added to the delay line. If left alone, this would not cause too much damage to the sound of our string but it would mean a delay of 0.01/seconds would no longer result in 100 Hz. For this reason, we subtract the time it takes our blocksize (probably 512 samples- you may test it by running the line "s.options.blockSize" in SuperCollider) from the overall delay time. How do you subtract the time it takes 512 samples fromthe total delay time? First you take one sample, which should be 1/s.sampleRate, then you multiply that by your block size, s.options.blockSize. So: (1/s.sampleRate * s.options.blockSize)) This is subtracted by our value for delay below. **


Enjoy!


(

SynthDef(\karplus_tuneable, { arg amp = 0.5, del = 0.01, gain = 0.9, lpf = 2000;

var in = Impulse.ar(0.5);

var infeed = LocalIn.ar(1);

var delay = DelayC.ar(in + infeed, 3, del - (1/s.sampleRate * s.options.blockSize));

var lpdelay = LPF.ar(delay * gain, lpf);

LocalOut.ar(lpdelay);

Out.ar(0, lpdelay*amp);

}

).add

)



x = Synth(\karplus_tuneable);

x.set(\del, 0.01);

0 comments
bottom of page