I’m a bit over excited as I just managed to successfully implement Karplus-Strong’s guitar string algorithm.
The Wikipedia description was too complicated for me. I had to get the original paper and try to study it. It’s rather old and the terminology was a bit weird, so it took me a while to really understand it.
This snippet assumes you have
SRATE defined somewhere (the sample rate), and that you already managed to setup the audio output and the mixer and everything else. I’m using
audiodata.js to output audio using Firefox4’s Audio Data API.
guitar here returns a function which takes a sample index/point and returns the sample. It assumes that it will be called with all the samples sequentially, otherwise it won’t work. Something like:
signal_fn = guitar(440) # 440 being the frequency we want to sound point = 0 while not done sample = signal_fn(point++) # output sample
Not exactly that, but something like that.
Here’s the code:
period_len = (freq) -> Math.floor (SRATE/freq) avg = (a, b) -> (a + b) / 2 ks_noise_sample = (val) -> # get either val or -val with 50% chance if Math.random() > 0.5 val else -val # karplus strong algorithm guitar = (freq) -> samples = period_len freq table = new Float32Array(samples) getsample = (index) -> point = index % samples if index == point table[point] = ks_noise_sample(1) else prev = (index - 1) % samples table[point] = avg(table[point], table[prev])
Note that this is coffee-script, where the last expression in a function is returned, and
A = B expressions return
guitar returns the
getsample function, and
table[point] after we calculate it.
Here’s what this does:
Fill a table of length
p with random values (actually: fill it with either A or -A, with 50% chance each). Where
p is the period of the signal, which is the
To produce samples, just keep cycling on this table. That is, to get any point
table[t % p].
BUT, as you loop on the table, average each two adjacent samples. That is, everytime you get
table[t] (except the first time around), let
(table[t] + table[t-1]) / 2.
This causes the signal to decay overtime, or something like that.