[sdiy] karplus-strong drum synthesis

Joel B onephatcat at earthlink.net
Sat Aug 20 23:58:57 CEST 2011


On Aug 20, 2011, at 1:43 PM, Olivier Gillet wrote:

> On which page is the equation you are trying to implement? I can't
> find anything in the paper resembling the equation you give.
> 

The one on page 46, under the heading "Drum Algorithm". The equation was my mathematically illiterate attempt to render what I thought i saw in the equation on that page.  

> Karplus strong synthesis is always done in a circular buffer, so when
> looking at the past samples you "wrap around" the buffer. One way to
> look at it is to say you're doing wavetable synthesis while constantly
> filtering the wavetable as it is being played.
> 
> A practical implementation of the algorithm on page 46 would be:
> 
> allocate a 2 * p array A and fill it with random numbers.

Would that be random 16 bit integers for 16 bit sound? 

> ptr = 0
> for each sample:
> if rnd > blend:
>   A[ptr] = 0.5 * (A[ (ptr + p) % (2 * p)] + A[(ptr + p - 1) % (2 * p)]

% in this context is the modulo function if I'm not mistaken? 

> else:
>   A[ptr] = -0.5 * (A[(ptr + p) % (2 * p)] + A[(ptr + p - 1) % (2 * p)]
> output = A[ptr]
> ptr = (ptr + 1) % (2 * p)


so this is how you do the wrapping on the wavetable. Very nice, no "if ptr > 880 then ptr=0" statement.

if the pitch is A440, then that would be an array of size 880 samples. 

so, in a VB like language:


//create an array
   a=[]
//create output array
   out=[]
//set value of p
   p=440

//fill array with random numbers

for i=0 to p*2       
   a[i]=rnd(65536)-32768
next i

blend=0.3 //pick arbitrary number less than 1 as experiment

outputLength=11024

while i < outputLength

r=rnd(65536)-32768 
//seems perhaps redundant to run a second random number generator when we already have an array full of random numbers?

if r > blend 
//if blend is usually < 1 and rnd is either a positive or negative integer, seems like this is to determine if we dealing with positive or negative number

   a[i]=0.5*(a[(i+p) mod (2*p)] +a[(i+p-1) mod (2*p)])

else

   a[i]=-0.5*(a[i+p) mod (2*p)]+a[(i+p-1) %(2*p)])

end if
out[i]=a[i]
i=(i+1) mod (2*p)
end while

Assuming I've translated all that correctly, my question is: is the second rnd function needed, or can use "if a[i] < blend" ?

- Joel




More information about the Synth-diy mailing list