0

I tried to implement the Karplus-Strong algorithm with some of the Jaffe-Smith extensions (improve pitch, dynamics, etc). Here is the code.

When I run it with a sampleRate of 48000Hz, I get very reasonably sounding string, without any hissing, aliasing or very high frequencies.

The thing that is messing me up is that when I increase the sampleRate (to 2x, 4x), I get a hissy/high freq sound. This is a 48k example and a 192k example.

I'm pretty sure I've messed something up on my implementation, as I was learning about this while reading the papers and writing the code. So please feel free to point anything else that I may be overlooking.

If I simplify the algorithm to be only a single lowpass filter (a filter like to the one I use for the random input) with the N-delay (which, as far as I understand, is the original algorithm), it works much better (without any difference between sample rates). As soon as I add any of the modifications (like the "pitch fix" on module C), it messes up.

My current guess is that increasing the sample rate increases the available frequencies. But I don't get how they are not being filtered like all other frequencies by any of the low pass filters.

The brown noise input is not part of the original algorithm, but it was one of my many attempts to figure out what's causing those extra frequencies (I was assuming that a higher sample would imply a higher frequency noise, which would make the sound naturally higher pitched). It didn't help much, but I left it there because I thought it makes sense.

Any comments, suggestions or ideas are appreciated.

update

The modification on the Karplus-Strong are the ones described in this paper. I do a simplified version, that shows on my top level comment. The relevant parts:

  • Instead of using a delay of N = round(sampleRate / freq) we use a modified N and include the C block ($H_c$ in the paper) to compensate for the rounding and improve how close the pitch is to the desired frequency. This is the first part of the update function and the cn line on the step.

  • I also apply what the paper call "Dynamics" ($H_d$). As far as I understand it's another lowpass filter that tries to balance the energy on each partial. On the code, it's the second block of _update that calculates R and the last step of the step function.

If you remove those two, you get a trivial Karplus-Strong with a delay line and a lowpass filter. When I add any of them, I get a similar sound to the examples above.

fserb
  • 101
  • 2

1 Answers1

1

An increased sample rate requires proportionally longer filters (both IIR, FIR, and FFT), in terms of the number of samples, for the same filter transition widths, flatness, and stop band attenuation. IIR or recursive filters can also become more sensitive to numerical noise (quantization, rounding, etc.) at higher ratios of sample rate to cut-off frequencies.

I suggest increasing the length of all your filter kernels and implementation sizes proportionately, and if you are using a short data type, try longer ones.

hotpaw2
  • 35,346
  • 9
  • 47
  • 90
  • does this mean that whatever is on those papers (and, well, ALL papers) is always conditional to a certain sample rate range? Is there a reason why this is not explicitly stated? (like: this approach makes sense up to X Hz) – fserb Jun 17 '21 at 13:12
  • 1
    I think the papers might assume (unstated) that one will try to pick a size of filter (etc.) appropriate to the sample rate. So there is no simple limit to the sample rate given enough computing horsepower (GFLOPs) and memory. – hotpaw2 Jun 17 '21 at 16:12
  • are we talking about the feedback filter? what filter? – robert bristow-johnson Jun 18 '21 at 01:57