Cabbage Logo
Back to Cabbage Site

How do I implement glide?

My first VST is nearly finished and what is missing is a portamento legato/slide/glide effect. But I’m not exactly sure how to implement that effect of a smooth transition between notes. Does anybody have an idea? For example by using portk?

Thanks a lot!

I’ve never implemented this myself, but there are examples that ship with Cabbage that employ portamento. I think oscbnk_synth, PadSynth, gbuzz_synth, FOF Choir, and CZ_Synth all off portamento in monophonic mode. :+1:

I will take a look, thanks

Hi @paragogia, you’re right, portk will serve the purpose perfectly

The lag & lagud opcodes are also useful for this. lagud offers seperate smoothing times for ascending and descending values. Both can also operate on k or a-rate signals as well.

I have tried out portk but thus fur did not manage to get the desired effect. Will take a look at lag/lagud tho, thanks.

What was the issue with portk, what effect were you not getting? The lag opcodes function very similarly but have more of an exponential response. Other than that the one other main difference seems to be the initial value (isig) for port/portk - there always seems to be glide/port applied to the first note which is not the case with lag.
port_lag.csd (938 Bytes)

Thanks a lot, it seems lag or lagud are the right fit. My problem was that the portk opcode would transpose the note before any glide would be even applied which is probably what you are describing. Right now though I realised that I first need a monophony mode. And I am half way there. Except when I play some notes in poly mode and switch to mono while the notes still release, I get no output whatsoever.

if kPolyMode == 1 then
        kCps = p4
    elseif kPolyMode == 2 then
        kCps = p4
        if changed(iMidiNoteNum) == 1 then
            turnoff2 1, 1, 0
        endif
    endif

And I am honestly unsure why. Tried a few combinations. Turnoff does not work at all, only turnoff2. Any ideas why? Decided to put this issue into a response since it is linked to the glide question. My goal here is to get monophony going and then extend the code to support glide. Should’ve done it this way right away, my bad^^.

I think you’ll need to post a complete example in order for us to help. Even a very basic, but complete, example would help :slight_smile:

I don’t really know since the entire synth code is already quite long. and the current code that handles the mono/poly thing is the example above. Unless you want to see how kPolyMode is defined. Btw I forgot to copy over an “endif” but it exists.

Oh, are you trying to build a glide based on one of the examples? In that case, I’m not sure I can help. I really must sit down at some point and implement the simplest of Poly/Mono instrument for the community. Or perhaps I can cheekily request one from @iainmccurdy :slight_smile:

This would be my basic monophonic-glide template. (You need to play notes from an external MIDI keyboard or the QWERTY keyboard to hear the glides as notes need to overlap.)

<Cabbage>
form caption("Untitled") size(400, 300), guiMode("queue"), pluginId("def1")
keyboard bounds(8, 158, 381, 95)
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1

;instrument will be triggered by keyboard widget
instr 1
icps  cpsmidi
gkcps =       icps ; set global variable for oscillator frequency to MIDI freq.
                   ; coexisting notes are piled up so that the lasat note played will dictate the value of gkcps  

; only turn instr 2 on for the first note of a legato phrase
if active:i(p1) == 1 then
 turnon  2
endif

endin


instr 2
kport =     0.05 * linseg:k(0,0.001,1) ; change 0.05 for longer or shorter portamento times
kcps  portk gkcps, kport
a1    vco2  0.2, kcps
a1    *=    linsegr:a(0,0.01,1,0.01,0)
      outs  a1,a1

; when all MIDI notes (instr 1) have been released, turn this instrument off
if active:k(1) == 0 then
 turnoff
endif

endin

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

instr 1 simply keeps track of MIDI notes. Only one instance of instr 2 is ever instantiated and it creates the audio.
It’s a combination of turnon, turnoff, active and the use of a global variable for oscillator pitch such that multiple iterations of the instr 1 will overwrite the variable with the most recent note taking precedence when the variable is read in instr 2.

The problem with portk that you describe can be circumvented with the linseg trick you see here, but if you like lagud stick with that.

Envelopes applied to an entire legato phrase should be placed in instr 2. Envelopes that should be retriggered upon every note, whether legato or not, should be placed in instr 1 with a global variable output.

Things get more complicated if instr 2 has a long release time but can be handled.

Being able to switch between between monophonic and polyphonic while sharing most of the code is also possible but care needs to be taken in the design.

1 Like

Thanks for this @iainmccurdy. I’ve been looking for a template for this for ages :slight_smile:

Interesting, yeah I tried to implement glide and mono/poly based on the examples provided but it didn’t work out well due to the different approaches to how the instrument examples are designed as opposed to mine. Will try out the example detailed above, thanks for the help folks!

How do I have to modify the example to allow switching between poly and mono? Because this is exactly what I’m playing around with right now^^.

You could do something like this:

<Cabbage>
form size(500, 300), caption("Untitled")

keyboard bounds(44, 184, 400, 100) channel("keyboard10000")
checkbox bounds(64, 28, 100, 30) channel("mono"), text("Mono"), fontColour:1(200), radioGroup(99), value(1)
checkbox bounds(64, 58, 100, 30) channel("poly"), text("Poly"), fontColour:1(200), radioGroup(99)
</Cabbage>


<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1

;instrument will be triggered by keyboard widget
instr 1
kMono cabbageGetValue "mono"
if kMono == 1 then
    icps  cpsmidi
    gkcps =       icps ; set global variable for oscillator frequency to MIDI freq.
                       ; coexisting notes are piled up so that the lasat note played will dictate the value of gkcps  

    ; only turn instr 2 on for the first note of a legato phrase
    if active:i(p1) == 1 then
        turnon  2
    endif
else
    kEnv = madsr:k(0.01,0.1,.7,.01)
    a1    vco2  kEnv*p5, p4
    outs  a1,a1
endif

endin


instr 2
kport =     0.05 * linseg:k(0,0.001,1) ; change 0.05 for longer or shorter portamento times
kcps  portk gkcps, kport
a1    vco2  0.2, kcps
a1    *=    linsegr:a(0,0.01,1,0.01,0)
      outs  a1,a1

; when all MIDI notes (instr 1) have been released, turn this instrument off
if active:k(1) == 0 then
 turnoff
endif

endin

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