Cabbage Logo
Back to Cabbage Site

How to improve Karplus-Strong instrument?

Hi. I was inspired by this tutorial for Vital and Erica Synths Steampipe and wanted to implement some physical modelling instrument inspired by Karplus-Strong algorithm.

I started with tuned comb opcode and slowly implemented lowpass filter inside feedback loop with noise burst exciter. It kinda works when it’s in pluck mode. When it’s in flute mode it sounds either too metalic or too noisy (depends on parameters and played note).

Does anyone here have some low-level implementation of Karplus-Strong?

Or does anyone have some tip how to improve my instument?

I am especially interested in these questions:

  • How to control decay time? It seems it depends both on exciter impulse amplitude, lowpass frequency and note… (It’s controllable using comb opcode, so there is some internal math in it.)
  • How to introduce resonances? In Vital one can add resonances to comb filter itself but I don’t understand how to implement it in Csound. I tried adding some resonances using moogladder or reson opcodes but I did something wrong and it started producing screeching sounds.
  • Why does it sound kinda like a sitar? What am I missing to made it’s tone more guitarish?

Here is the code of my instrument:

<Cabbage>
form caption("Karplus-Strong hard way") size(400, 300), colour(58, 110, 182), pluginid("def1")
keyboard bounds(8, 158, 381, 95)
rslider bounds(14, 48, 60, 60) range(0, 3, 0.5, 1, 0.001) channel("jetvol") text("jetvol") 
checkbox bounds(14, 114, 130, 30) text("pluck?") channel("pluck")
rslider bounds(80, 48, 60, 60) range(-0.9, 0.9, 0, 1, 0.001) text("noisecol") channel("noisecol")
label bounds(38, 20, 80, 16) text("EXCITER")
label bounds(182, 22, 80, 16) text("FILTER")
rslider bounds(164, 48, 60, 60) range(800, 8000, 8000, 1, 0.001) text("freq") channel("freq")
rslider bounds(226, 48, 60, 60) range(0, 1, 0.8, 1, 0.001) channel("clip") text("clip")
rslider bounds(332, 48, 60, 60) range(0, 2, 1, 1, 0.001) channel("vol")
label bounds(320, 24, 80, 16) text("VOL")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 -m0d --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1

; Karplus-Strong done in hard way (manually)

;instrument will be triggered by keyboard widget
instr 1
    ; exciter volume (0-3)
    kjetvol chnget "jetvol"
    ; noise color (-0.9-0.9)
    knoisecol chnget "noisecol"
    ; is pluck?
    ipluck chnget "pluck"
    if ipluck==1 then
        kEnv madsr .01, .01, 0, .1
    else
        kEnv madsr .1, .01, 0.8, .1
    endif
    
    anoise noise 0.3, knoisecol
    ; exciter signal: 
    aping = kEnv*anoise*kjetvol
    
    ; debug to print delay times
    ; printf_i "delay = %f\n", 1, (1/p4)
    printf_i "hz = %d\n", 1, p4
    
    ; tuned delay line: (this whole block until delayw)
    adump delayr 1
    ares deltapi 1/p4
    
    ifreq chnget "freq"
    ; lowpass to smooth out higher harmonics
    ares butterlp ares, ifreq
    
    ares dcblock ares ; dcblock for good measure
    
    iclip chnget "clip"    
    ares clip ares, 0, iclip
    
    delayw (ares*0.998)+aping
    
    kvol chnget "vol"
    kanticlick madsr 0.01, 0, 1, 0.01
    ares = ares * kanticlick * kvol
    
    outs ares, ares
endin

</CsInstruments>
<CsScore>
;causes Csound to run for about 7000 years...
f0 z
</CsScore>
</CsoundSynthesizer>

Did you explore the example here: https://flossmanual.csound.com/sound-synthesis/physical-modelling

One of the Lazzarini books I have has a chapter on this approach to synthesis. I didn’t get too excited when reading it the first time, but the Steamipe got me interested.

1 Like

yeah, page 386 onwards in Csound, A Sound And Music Computing System has a lot of info on this type of modelling. It’s definitely worth checking out. The examples are available online on github.


The first one is a very basic implementation, the second addresses the problems with tuning, the 3rd is a clarinet example.

1 Like