302 lines
No EOL
15 KiB
HTML
302 lines
No EOL
15 KiB
HTML
<!doctype html><html lang='en'><head><title>EnvGen | SuperCollider 3.12.2 Help</title>
|
|
<link rel='stylesheet' href='./../scdoc.css' type='text/css' />
|
|
<link rel='stylesheet' href='./../codemirror.css' type='text/css' />
|
|
<link rel='stylesheet' href='./../editor.css' type='text/css' />
|
|
<link rel='stylesheet' href='./../frontend.css' type='text/css' />
|
|
<link rel='stylesheet' href='./../custom.css' type='text/css' />
|
|
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
|
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
|
|
<script src='./../lib/jquery.min.js'></script>
|
|
<script src='./../lib/codemirror-5.39.2.min.js' type='text/javascript'></script>
|
|
<script src='./../lib/codemirror-addon-simple-5.39.2.min.js' type='text/javascript'></script>
|
|
<script>
|
|
var helpRoot = './..';
|
|
var scdoc_title = 'EnvGen';
|
|
var scdoc_sc_version = '3.12.2';
|
|
</script>
|
|
<script src='./../scdoc.js' type='text/javascript'></script>
|
|
<script src='./../docmap.js' type='text/javascript'></script>
|
|
<script src='qrc:///qtwebchannel/qwebchannel.js' type='text/javascript'></script>
|
|
</head>
|
|
<body onload='fixTOC()'>
|
|
<div id='toc'>
|
|
<div id='toctitle'>EnvGen:</div>
|
|
<span class='toc_search'>Filter: <input id='toc_search'></span><ul class='toc'><li class='toc1'><a href='#description'>Description</a></li>
|
|
<ul class='toc'></ul><li class='toc1'><a href='#classmethods'>Class methods</a></li>
|
|
<ul class='toc'><li class='toc3'><a href='#*ar'>ar</a> <a href='#*kr'>kr</a> </li>
|
|
<li class='toc2'><a href='#Inherited%20class%20methods'>Inherited class methods</a></li>
|
|
</ul><li class='toc1'><a href='#instancemethods'>Instance methods</a></li>
|
|
<ul class='toc'><li class='toc2'><a href='#Inherited%20instance%20methods'>Inherited instance methods</a></li>
|
|
<li class='toc2'><a href='#Undocumented%20instance%20methods'>Undocumented instance methods</a></li>
|
|
<ul class='toc'><li class='toc3'><a href='#-canFreeSynth'>canFreeSynth</a> </li>
|
|
</ul></ul><li class='toc1'><a href='#examples'>Examples</a></li>
|
|
<ul class='toc'><li class='toc2'><a href='#Specifying%20an%20envelope%20for%20each%20new%20synth'>Specifying an envelope for each new synth</a></li>
|
|
<ul class='toc'></ul><li class='toc2'><a href='#Forced%20release'>Forced release</a></li>
|
|
<ul class='toc'></ul><li class='toc2'><a href='#Fast%20triggering%20tests'>Fast triggering tests</a></li>
|
|
<ul class='toc'></ul><li class='toc2'><a href='#Modulating%20the%20levelScale'>Modulating the levelScale</a></li>
|
|
<ul class='toc'></ul><li class='toc2'><a href='#More%20examples'>More examples</a></li>
|
|
<ul class='toc'></ul></ul></ul></div><div id='menubar'></div>
|
|
<div class='contents'>
|
|
<div class='header'>
|
|
<div id='label'>
|
|
<span id='folder'>Classes</span>
|
|
| <span id='categories'><a href='./../Browse.html#UGens'>UGens</a> > <a href='./../Browse.html#UGens>Envelopes'>Envelopes</a></span>
|
|
</div><h1>EnvGen<span id='superclasses'> : <a href="../Classes/UGen.html">UGen</a> : <a href="../Classes/AbstractFunction.html">AbstractFunction</a> : <a href="../Classes/Object.html">Object</a></span>
|
|
</h1>
|
|
<div id='summary'>Envelope generator</div>
|
|
</div>
|
|
<div class='subheader'>
|
|
<div id='filename'>Source: <a href='file:///Applications/SuperCollider.app/Contents/Resources/SCClassLibrary/Common/Audio/EnvGen.sc' title='/Applications/SuperCollider.app/Contents/Resources/SCClassLibrary/Common/Audio/EnvGen.sc'>EnvGen.sc</a></div><div id='related'>See also: <a href="./../Classes/Linen.html">Linen</a>, <a href="./../Classes/Env.html">Env</a></div>
|
|
</div>
|
|
<h2><a class='anchor' name='description'>Description</a></h2>
|
|
|
|
<p>Plays back break point envelopes. The envelopes are instances of the <a href="./../Classes/Env.html">Env</a> class. The envelope and the arguments for <code>levelScale</code>, <code>levelBias</code>, and <code>timeScale</code> are polled when the EnvGen is triggered, and at the start of a new envelope segment. All values remain constant for the duration of each segment.<textarea class='editor'>{ PinkNoise.ar(EnvGen.kr(Env.perc, doneAction: Done.freeSelf)) }.play</textarea>
|
|
<h2><a class='anchor' name='classmethods'>Class Methods</a></h2>
|
|
<h3 class='method-code'><span class='method-prefix'>EnvGen.</span><a class='method-name' name='*ar' href='./../Overviews/Methods.html#ar'>ar</a>(<span class='argstr'>envelope</span>, <span class='argstr'>gate: 1.0</span>, <span class='argstr'>levelScale: 1.0</span>, <span class='argstr'>levelBias: 0.0</span>, <span class='argstr'>timeScale: 1.0</span>, <span class='argstr'>doneAction: 0</span>)</h3>
|
|
<h3 class='method-code'><span class='method-prefix'>EnvGen.</span><a class='method-name' name='*kr' href='./../Overviews/Methods.html#kr'>kr</a>(<span class='argstr'>envelope</span>, <span class='argstr'>gate: 1.0</span>, <span class='argstr'>levelScale: 1.0</span>, <span class='argstr'>levelBias: 0.0</span>, <span class='argstr'>timeScale: 1.0</span>, <span class='argstr'>doneAction: 0</span>)</h3>
|
|
<div class='method'>
|
|
<p><h4>Arguments:</h4>
|
|
<table class='arguments'>
|
|
<tr><td class='argumentname'>envelope<td class='argumentdesc'>
|
|
<p>An <a href="./../Classes/Env.html">Env</a> instance, or an Array of Controls. (See <a href="./../Classes/Control.html">Control</a> and the example below for how to use this.)
|
|
<p>The envelope is polled when the EnvGen is triggered, and at the start of a new envelope segment. The Env inputs can be other UGens.<tr><td class='argumentname'>gate<td class='argumentdesc'>
|
|
<p>This triggers the envelope and holds it open while > 0. If the Env is fixed-length (e.g. Env.linen, Env.perc), the gate argument is used as a simple trigger. If it is an sustaining envelope (e.g. Env.adsr, Env.asr), the envelope is held open until the gate becomes 0, at which point is released.
|
|
<p>If <strong>gate</strong> < 0, force release with time <code>-1.0 - gate</code>. See <a href="#Forced%20release">Forced release</a> below.<tr><td class='argumentname'>levelScale<td class='argumentdesc'>
|
|
<p>The levels of the breakpoints are multiplied by this value. This value can be modulated, but is only sampled at the start of a new envelope segment.<tr><td class='argumentname'>levelBias<td class='argumentdesc'>
|
|
<p>This value is added as an offset to the levels of the breakpoints. This value can be modulated, but is only sampled at the start of a new envelope segment.<tr><td class='argumentname'>timeScale<td class='argumentdesc'>
|
|
<p>The durations of the segments are multiplied by this value. This value can be modulated, but is only sampled at the start of a new envelope segment.<tr><td class='argumentname'>doneAction<td class='argumentdesc'>
|
|
<p>An integer representing an action to be executed when the env is finished playing. This can be used to free the enclosing synth, etc. See <a href="./../Classes/Done.html">Done</a> for more detail.</table><h4>Discussion:</h4>
|
|
<div class='note'><span class='notelabel'>NOTE:</span> The actual minimum duration of a segment is not zero, but one sample step for audio rate and one block for control rate. This may result in asynchronicity when in two envelopes of different number of levels, the envelope times add up to the same total duration. Similarly, when modulating times, the new time is only updated at the end of the current segment - this may lead to asynchronicity of two envelopes with modulated times.</div><textarea class='editor'>// as amplitude envelope
|
|
(
|
|
{
|
|
var env = Env([0, 1, 0.5, 1, 0], [0.01, 0.5, 0.02, 0.5]);
|
|
SinOsc.ar(470) * EnvGen.kr(env, doneAction: Done.freeSelf)
|
|
}.play
|
|
)
|
|
|
|
// as amplitude and modulation envelope
|
|
(
|
|
{
|
|
var env = Env([0, 1, 0.5, 0.8, 0, 1.2, 0], [0.01, 0.5, 0.02, 0.5, 0.2, 0.5]);
|
|
var gate = Impulse.kr(MouseX.kr(0.2, 3), 0.5);
|
|
var gen = EnvGen.kr(env, gate);
|
|
SinOsc.ar(270, SinOsc.ar(gen * 473)) * gen * 0.2
|
|
}.play
|
|
)
|
|
// EnvGen multichannel expands when passed a multichannel envelope
|
|
(
|
|
{
|
|
SinOsc.ar(
|
|
EnvGen.kr(
|
|
Env.circle([0, 1, 0, (2..4), 0, LFNoise1.kr(0.1 ! 5) * 10, 0], [0.01, 0.6])
|
|
)
|
|
* 240 + 300
|
|
).sum * 0.2
|
|
}.play;
|
|
)</textarea>
|
|
</div><h3><a class='anchor' name='Inherited%20class%20methods'>Inherited class methods</a></h3>
|
|
<div id='inheritedclassmets'></div><h2><a class='anchor' name='instancemethods'>Instance Methods</a></h2>
|
|
<h3><a class='anchor' name='Inherited%20instance%20methods'>Inherited instance methods</a></h3>
|
|
<div id='inheritedinstmets'></div><h3><a class='anchor' name='Undocumented%20instance%20methods'>Undocumented instance methods</a></h3>
|
|
<h3 class='method-code'><span class='method-prefix'>.</span><a class='method-name' name='-canFreeSynth' href='./../Overviews/Methods.html#canFreeSynth'>canFreeSynth</a></h3>
|
|
<div class='extmethod'>From extension in <a href='file:///Applications/SuperCollider.app/Contents/Resources/SCClassLibrary/Common/Audio/canFreeSynth.sc'>/Applications/SuperCollider.app/Contents/Resources/SCClassLibrary/Common/Audio/canFreeSynth.sc</a></div>
|
|
<h2><a class='anchor' name='examples'>Examples</a></h2>
|
|
<textarea class='editor'>// retriggered envelope by Dust
|
|
(
|
|
{
|
|
var env = Env([0.0, 0.5, 0.0, 1.0, 0.9, 0.0], [0.05, 0.1, 0.01, 1.0, 1.5], -4);
|
|
var envgen = EnvGen.ar(env, Dust.ar(1));
|
|
SinOsc.ar(
|
|
envgen * 1000 + 440
|
|
) * envgen * 0.1
|
|
}.play
|
|
);
|
|
|
|
// two channels
|
|
(
|
|
{
|
|
var env = Env([0.0, [-0.2, 0.5], 0.0, 1.0, [-0.4, 0.9], 0.0], [0.05, 0.1, 0.01, 1.0, 1.5], -4);
|
|
var envgen = EnvGen.ar(env, Dust.ar([1, 1]));
|
|
SinOsc.ar(
|
|
envgen * 440 + 550
|
|
) * envgen * 0.1
|
|
}.play
|
|
);
|
|
|
|
// an envelope in a SynthDef can be used to limit the synth's lifetime (doneAction: Done.freeSelf)
|
|
|
|
(
|
|
SynthDef(\env_help, { | out, gate = 0, freq = 440 |
|
|
var z;
|
|
z = EnvGen.kr(Env.perc, doneAction: Done.freeSelf) * SinOsc.ar(freq, 0, 0.1);
|
|
Out.ar(out, z)
|
|
}).add;
|
|
)
|
|
|
|
(
|
|
fork {
|
|
10.do {
|
|
Synth(\env_help);
|
|
0.2.rand.wait;
|
|
}
|
|
}
|
|
)
|
|
|
|
|
|
// using a gated envelope to gate a sound:
|
|
(
|
|
SynthDef(\env_help, { | out, gate = 0, freq = 440, doneAction = 0 |
|
|
var z = EnvGen.kr(Env.adsr, gate, doneAction: doneAction) * SinOsc.ar(freq, 0, 0.1);
|
|
Out.ar(out, z)
|
|
}).add;
|
|
)
|
|
|
|
a = Synth(\env_help);
|
|
|
|
|
|
// turn on
|
|
a.set(\gate, 1);
|
|
|
|
// turn off
|
|
a.set(\gate, 0);
|
|
|
|
// it does not matter to what value the gate is set, as long as it is > 0
|
|
a.set(\gate, 2);
|
|
|
|
a.set(\doneAction, 2, \gate, 0); // set doneAction to two to let the synth free itself
|
|
|
|
a.free; // alternatively, free it directly.</textarea>
|
|
<h3><a class='anchor' name='Specifying%20an%20envelope%20for%20each%20new%20synth'>Specifying an envelope for each new synth</a></h3>
|
|
<textarea class='editor'>(
|
|
SynthDef(\help_Env_newClear, { |out = 0|
|
|
var env, envctl;
|
|
// make an empty 4 segment envelope
|
|
env = Env.newClear(4);
|
|
// create a control argument array
|
|
envctl = \env.kr(env.asArray);
|
|
Out.ar(out,
|
|
SinOsc.ar(EnvGen.kr(envctl, \gate.tr), 0, 0.3) // the gate control is a trigger
|
|
);
|
|
}).add;
|
|
)
|
|
|
|
Synth(\help_Env_newClear, [\gate, 1, \env, Env([700,900,900,800], [1,1,1], \exp)]); // 3 segments
|
|
|
|
// reset then play again:
|
|
Synth(\help_Env_newClear, [\gate, 1, \env, Env({ rrand(60, 70).midicps } ! 4, [1,1,1], \exp)]);
|
|
|
|
// the same written as an event:
|
|
(instrument: \help_Env_newClear, gate: 1, env: Env({ rrand(60, 70).midicps } ! 4, [1,1,1], \exp)).play;</textarea>
|
|
<h3><a class='anchor' name='Forced%20release'>Forced release</a></h3>
|
|
|
|
<p>If the gate of an EnvGen is set to -1 or below, then the envelope will cutoff immediately. The time for it to cutoff is the amount less than -1, with -1 being as fast as possible, -1.5 being a cutoff in 0.5 seconds, etc. The cutoff shape and final value are read from the Env's last node.<textarea class='editor'>(
|
|
SynthDef(\stealMe, { |out, gate = 1|
|
|
Out.ar(out, {BrownNoise.ar}.dup * EnvGen.kr(Env.asr, gate, doneAction: Done.freeSelf))
|
|
}).add;
|
|
)
|
|
|
|
a = Synth(\stealMe);
|
|
a.release(3); // // cutoff in 3 seconds
|
|
|
|
// this is how the OSC data looks like:
|
|
s.sendMsg(\s_new, \stealMe, 1001, 1, 0);
|
|
s.sendMsg(\n_set, 1001, \gate, -1.1); // cutoff in 0.1 seconds</textarea>
|
|
|
|
<p>If the synthDef has an arg named "gate", the convenience method of Node can be used: <code>node.release(releaseTime)</code><textarea class='editor'>d = { arg gate=1; {BrownNoise.ar}.dup * EnvGen.kr(Env.asr, gate, doneAction: Done.freeSelf) }.play;
|
|
d.release(3);</textarea>
|
|
|
|
<p>Forced release ignores multi-node release stages, always performing a one-node release, reading curve and end value from the Env's last node, and overwriting its duration.<textarea class='editor'>(
|
|
// a Synth with a multi-node release stage
|
|
d = { arg gate=1;
|
|
var env = Env([0,1,0,0.5,0],0.5,-4,releaseNode:1);
|
|
{BrownNoise.ar}.dup * EnvGen.kr(env, gate, doneAction: Done.freeSelf)
|
|
}.play;
|
|
)
|
|
// forced release in 2 seconds:
|
|
// end value (0) and shape (-4) are read from the env's last node, nodes 2 and 3 are skipped
|
|
d.release(2);
|
|
|
|
// without releaseTime: normal release stage, as defined in env (3 nodes)
|
|
d.release();</textarea>
|
|
<h3><a class='anchor' name='Fast%20triggering%20tests'>Fast triggering tests</a></h3>
|
|
<textarea class='editor'>(
|
|
{
|
|
EnvGen.kr(
|
|
Env.new([ 0.001, 1, 0.5, 0 ], [ 0.01, 0.3, 1 ], -4, 2, nil),
|
|
Impulse.kr(10)
|
|
) * SinOsc.ar(440, 0, 0.1)
|
|
}.play;
|
|
)
|
|
|
|
(
|
|
{
|
|
EnvGen.kr(
|
|
Env.perc( 0.1, 0.0, 0.5, 1, \welch ),
|
|
Impulse.kr(100),
|
|
timeScale: 0.1
|
|
) * SinOsc.ar(440, 0, 0.3)
|
|
}.play;
|
|
)</textarea>
|
|
<h3><a class='anchor' name='Modulating%20the%20levelScale'>Modulating the levelScale</a></h3>
|
|
<textarea class='editor'>// no, it doesn't take a ugen in ...
|
|
(
|
|
{
|
|
EnvGen.kr(
|
|
Env.asr( 0.1, 1.0, 0.5, \welch ),
|
|
1.0,
|
|
FSinOsc.ar(1.0).range(0.0, 1.0),
|
|
timeScale: 0.1
|
|
) * SinOsc.ar(440, 0, 0.3)
|
|
}.play;
|
|
)
|
|
|
|
// ...but an .ir rate input, a float or an ir rate ugen like Rand would work
|
|
(
|
|
{
|
|
EnvGen.kr(
|
|
Env.asr( 0.1, 1.0, 0.5, \welch ),
|
|
1.0,
|
|
Rand(0.1, 1.0),
|
|
timeScale: 0.1
|
|
) * SinOsc.ar(440, 0, 0.3)
|
|
}.play;
|
|
)</textarea>
|
|
<h3><a class='anchor' name='More%20examples'>More examples</a></h3>
|
|
|
|
<p>For more information about the <em>control bus mapping</em> used in the line <code>a = Synth(\sine, [freq: f.asMap]);</code>, see <a href="./../Classes/Node.html#-map">Node: -map</a> and <a href="./../Classes/Bus.html#-asMap">Bus: -asMap</a>.<textarea class='editor'>// Changing an Env while playing
|
|
(
|
|
SynthDef(\env, { arg i_outbus=0;
|
|
var env, envctl;
|
|
|
|
// make a dummy 8 segment envelope
|
|
env = Env.newClear(8);
|
|
|
|
// create a control argument array
|
|
envctl = \env.kr( env.asArray );
|
|
|
|
ReplaceOut.kr(i_outbus, EnvGen.kr(envctl, doneAction: Done.freeSelf));
|
|
}).add;
|
|
)
|
|
|
|
(
|
|
SynthDef(\sine, { |out, freq = 440|
|
|
Out.ar(out, SinOsc.ar(freq, 0, 0.2));
|
|
}).add;
|
|
)
|
|
|
|
f = Bus.control(s, 1);
|
|
f.set(800);
|
|
|
|
// use f's control bus value for frequency
|
|
// i.e. *map* the control to read from the bus
|
|
a = Synth(\sine, [freq: f.asMap]);
|
|
|
|
Synth(\env, [i_outbus: f, env: Env([700, 900, 900, 800], [1, 1, 1]*0.4, \exp)]);
|
|
|
|
Synth(\env, [i_outbus: f, env: Env([1000, 1000, 800, 1000, 900, 1000], [1, 1, 1, 1, 1]*0.3, \step)]);
|
|
|
|
a.free;
|
|
f.free;</textarea>
|
|
|
|
<p><div class='doclink'>helpfile source: <a href='file:///Applications/SuperCollider.app/Contents/Resources/HelpSource/Classes/EnvGen.schelp'>/Applications/SuperCollider.app/Contents/Resources/HelpSource/Classes/EnvGen.schelp</a><br>link::Classes/EnvGen::<br></div></div><script src='./../editor.js' type='text/javascript'></script>
|
|
</body></html> |