Monday 11 May 2015

pitch - Synthesizing harmonic tones with Karplus Strong



I'm building my own MIDI synth.


I have to create a decent sounding tone for every note on the piano keyboard (A-1 through C7, or MIDI 21 through 21+88=109)


I've been using a basic ring resonator, where I create a ring of the right size (for example, sampling at 44.1 kHz the ring for A440 a.k.a. concert pitch would be 44100/440 i.e. 100.25 ~ 100 samples), fill it with static (values between -1 and +1) and then walk through it, averaging consecutive values.


The problem is that A-1 rumbles for 30 seconds, whereas C7 dies almost instantly.


I never noticed this problem before as I was working with a much smaller range; < two octaves.


Attempting to balance out the decays by multiplying by a suitable decay constant, say X[n] = .995*(X[n-1] + X[n-2])/2, where I choose the constant carefully for each note, is also failing.


Problem here is that even with decay=1.0, a high note still disappears almost instantly. And it makes sense thinking about it; if the ring is only 10 samples, even in 1/100sec we have covered 440 samples i.e. 44 revolutions, which will have smeared everything pretty close to 0.


One method I tried is feeding energy into the ring; creating a buffer of static enveloped by an exponential decay, and feeding this buffer into the ring. It isn't working very well.


What I found works better is linear interpolation, so instead of doing ( X[n-1] + X[n-2] ) / 2, I do maybe:


0.98 * X[n-1]  +  0.02 * X[n-2] for a high note,  and 

0.6 * X[n-1] + 0.4 * X[n-2] for a note lower down

etc.


But now the question is: how to choose the interpolation factor depending on the note?


I need a much better model to work with.


I think I also need to implement fractional delay;


Samp[ N ] += k *  Samp[ N - L ], 

and if L = 10.2 say, I would have to do:


Samp[ N ] += k * ( 0.8 * Samp[10]  +  0.2 * Samp[ 11 ] )


so that is a completely different linear interpolation.


So my main question is: How to mathematically determine the necessary interpolation factor for a given note, so that all notes have an equal decay?


Supplementary questions are:
- do I need to use a decay constant in addition to adjusting the interpolation? - is my understanding of fractional delay sufficient to get a working result?


If anyone knows of any resource for simulating a harmonic tone that is reasonably accessible, please do put it in as an answer. I've looked through JOS's resources, but he writes at a very advanced level, and I have difficulty understanding the material.


π


PS I can't find an appropriate tag; pitch, note, gen*, tone, synth*, none of these are available.




No comments:

Post a Comment

readings - Appending 内 to a company name is read ない or うち?

For example, if I say マイクロソフト内のパートナーシップは強いです, is the 内 here read as うち or ない? Answer 「内」 in the form: 「Proper Noun + 内」 is always read 「ない...