A triggerable linear envelope with sustain segment
linenv is similar to linsegr with an additional gate argument, allowing
to retrigger it at will. One of the values can be defined as a sustain point,
meaning that as long as the gate is held, the envelope enters a sustain
state when reaching this point. When the gate is set to 0, the envelope traverses
the rest of the defined points.
If the gate is closed before reaching the sustain segment, the envelope slides to the release section skipping any segments in between.
linenv does not extend the time of the instrument. Use
xtratim for that
Similarly to linseg/linsegr, it is possible to define segments of 0 duration to force sharp jumps
xout linenv kgate, isustindex, kval0, [ktime1, kval1, ktime2, kval2, ...]
kgate: whenever this switches from 0 to 1 a new envelope starts. If a sustain segment was defined, when closing the gate (transition from 1 to 0) the envelope jumps to the sustain segment. Otherwise it just continues until it reaches the last segment (a "oneshot" envelope)
isustindex: the index of the sustain point. For example, if
isustindexis 2, then when the envelope reaches kval2 (after ktime0+ktime1), it enters a sustain phase, where its value remains unmodified until the gate is set to 0. If no sustain point is desired, set
isustindexto 0. NB: negative values count from end. To imitate the behaviour of linsegr, use -1 as sustain index.
ktime1, ...: a linear envelope, similar to
linsegr. The release part can have as many segments as desired. ktimen values are defined as time interval between two values, not as absolute timestamps
xout: value of the envelope (k- or a- rate)
<CsoundSynthesizer> <CsOptions> -odac </CsOptions> <CsInstruments> /* This is the example file for opcode "linenv" linenv is a triggerable envelope with a sustain segment aout linenv kgate, isustidx, kval0, ktime1, kval1, ..., ktimen, kvaln NB: use xtratim if necessary to allow for release segment */ sr = 44100 ksmps = 64 nchnls = 2 0dbfs = 1 gkgate init 0 FLpanel "linenv", 240, 100, 100, 100 gkgate, gih1 FLbutton " Gate", 1, 0, 2, 80, 40, 10, 10, -1 FLpanelEnd FLrun instr 1 kgate = trighold:k(metro(1/2), 0.5) kenv linenv kgate, 1, 0, 0.15, 1, 0.1, 0 printf "t: %f, kenv: %f \n", timeinstk(), timeinsts(), kenv kenv *= 0.2 asig = pinker() * interp(kenv) outs asig, asig endin instr 2 iperiod = 2 igatedur = 1 kgate = trighold:k(metro(1/iperiod), igatedur) aenv linenv kgate, -2, 0, 0.05, 1, 0.2, 0.5, 0.2, 1, 0.4, 0 asig = oscili:a(0.2, 1000) * aenv FLsetVal changed(kgate), kgate, gih1 outs asig, asig endin instr 3 asig pinker aenv linenv gkgate, 2, 0, 0.05, 1, 0.1, 0.2, 0.5, 0 asig *= aenv outs asig, asig endin instr 4 ; no sustain ("one shot") asig pinker aenv linenv gkgate, 0, 0, 0.05, 1, 0.1, 0.2, 0.5, 0 asig *= aenv outs asig, asig endin </CsInstruments> <CsScore> ; i1 0 10 ; i2 0 10 i3 0 100 ; i4 0 100 </CsScore> </CsoundSynthesizer>
Eduardo Moguillansky, 2019
(idea based on pd/else's
envgen and supercollider's