Rory, just to let you know, I’ve made some progress on this with the help of the Csound List. I’ve included my most recent version, if you’re curious. I also got a response from the list that mentioned a plugin opcode that does this very thing, except I can’t seem to get those dylibs to load. I get a number of messages saying that some libraries aren’t loading. I guess this is a topic for another thread…
<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 -m0d --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>
; Initialize the global variables.
ksmps = 32
nchnls = 2
0dbfs = 1
gkCPS init 0
gkAMP init 0
;instrument will be triggered by keyboard widget
instr 1
; trigger a new note only if this is the first of a group of notes that is played
if active:i(p1) == 1 then
event_i "i", 2, 0, -1
endif
; read in note frequency and set global k-var to this.
; gkCPS will always be determined by the most recent key played, but will return to the value of the previous note if the most recent key is released.
; iCPS notnum
iCPS cpsmidi
iAMP ampmidi 1
prints "iCPS %d %d\n", iCPS, active:i(p1)
gkCPS init iCPS
gkAMP init iAMP
endin
giLevels[] fillarray 0, 1, .75, .25, .5, .3, .7, .4, 0
giRates[] fillarray .01, .1, 3, 4, 5, 1, .8, 2
opcode TimeTrigger, k, i
iTime xin
kCounter init iTime
kFlag init 0
; if metro(4) == 1 then
; printks "TimeTrigger kCounter: %f\n", 0, kCounter
; endif
if kCounter >= 0 then
kCounter = kCounter - (1 / kr)
else
kFlag = 1
endif
xout kFlag
endop
instr 2
iCount = 6
iExtend = 0
while iCount < 8 do
iExtend = iExtend + (giRates[iCount] * 1.02)
iCount = iCount + 1
od
kSet init 0
kLastSampIndex = ksmps - 1
kActive active 1
; if metro(4) == 1 then
; printk2 kActive
; endif
if kActive > 0 then
aCarEnv linseg giLevels[0], giRates[0], giLevels[1], giRates[1], giLevels[2], giRates[2], giLevels[3], giRates[3], giLevels[4], giRates[4], giLevels[5], giRates[5], giLevels[6]
kLastSample = aCarEnv[kLastSampIndex]
;printk2 kLastSample
elseif kActive == 0 then
if kSet == 0 then
reinit setCurr
endif
setCurr:
iLast = i(kLastSample)
kSet = 1
; print iLast
rireturn
aCarEnv linseg iLast, giRates[6], giLevels[7], giRates[7], giLevels[8]
if TimeTrigger(iExtend) == 1 then
turnoff
endif
endif
aOut vco2 gkAMP, gkCPS
outs aOut * aCarEnv * gkAMP, aOut * aCarEnv * gkAMP
endin
</CsInstruments>
<CsScore>
;causes Csound to run for about 7000 years...
f0 z
</CsScore>
</CsoundSynthesizer>