scide: implement selectionLength for openDocument
[supercollider.git] / HelpSource / Classes / EnvGen.schelp
blobb4d28c016360a64153cf755f0b410726f3d4cacf
1 class:: EnvGen
2 summary:: Envelope generator
3 related:: Classes/Linen, Classes/Env
4 categories::  UGens>Envelopes
7 Description::
9 Plays back break point envelopes. The envelopes are instances of the
10 link::Classes/Env:: class. The envelope and the arguments for  code::levelScale:: ,
11 code::levelBias:: , and  code::timeScale::
12 are polled when the EnvGen is triggered and remain constant for the
13 duration of the envelope.
15 code::
16 { PinkNoise.ar(EnvGen.kr(Env.perc, doneAction: 2)) }.play
19 classmethods::
21 private::convertEnv
23 method::ar, kr
25 argument::envelope
27 An link::Classes/Env:: instance, or an Array of Controls.
28 (See link::Classes/Control::  and the example below for how to use
29 this.)
31 The envelope is polled when the EnvGen is triggered. The Env inputs can be other UGens.
34 argument::gate
36 This triggers the envelope and holds it open while > 0. If the
37 Env is fixed-length (e.g. Env.linen, Env.perc), the gate argument
38 is used as a simple trigger. If it is an sustaining envelope
39 (e.g. Env.adsr, Env.asr), the envelope is held open until the
40 gate becomes 0, at which point is released.
42 If strong::gate:: < 0, force release with time code:: -1.0 - gate ::, see link::#forced_release:: below.
44 argument::levelScale
46 Scales the levels of the breakpoints.
49 argument::levelBias
51 Offsets the levels of the breakpoints.
54 argument::timeScale
56 Scales the durations of the segments.
59 argument::doneAction
61 An integer representing an action to be executed when the env is
62 finished playing. This can be used to free the enclosing synth,
63 etc. See link::Reference/UGen-doneActions::  for more detail.
65 discussion::
66 note::
67 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.
70 code::
72 // as amplitude envelope
75         var env = Env([0, 1, 0.5, 1, 0], [0.01, 0.5, 0.02, 0.5]);
76         SinOsc.ar(470) * EnvGen.kr(env, doneAction: 2)
77 }.play
80 // as amplitude and modulation envelope
83         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]);
84         var gate = Impulse.kr(MouseX.kr(0.2, 3), 0.5);
85         var gen = EnvGen.kr(env, gate);
86         SinOsc.ar(270, SinOsc.ar(gen * 473)) * gen * 0.2
87 }.play
89 // EnvGen multichannel expands when passed a multichannel envelope
91
92         SinOsc.ar(
93                 EnvGen.kr(
94                         Env.circle([0, 1, 0, (2..4), 0, LFNoise1.kr(0.1 ! 5) * 10, 0], [0.01, 0.6])
95                 ) 
96                 * 240 + 300
97         ).sum * 0.2 
98 }.play; 
102 Examples::
104 code::
105 // retriggered envelope by Dust
108         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);
109         var envgen = EnvGen.ar(env, Dust.ar(1));
110         SinOsc.ar(
111                 envgen * 1000 + 440
112         ) * envgen * 0.1
113 }.play
116 // two channels
119         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);
120         var envgen = EnvGen.ar(env, Dust.ar([1, 1]));
121         SinOsc.ar(
122                 envgen * 440 + 550
123         ) * envgen * 0.1
124 }.play
127 // an envelope in a SynthDef can be used to limit the synth's lifetime (doneAction: 2)
130 SynthDef(\env_help, { | out, gate = 0, freq = 440 |
131     var z;
132     z = EnvGen.kr(Env.perc, doneAction: 2) * SinOsc.ar(freq, 0, 0.1);
133     Out.ar(out, z)
134 }).add;
138 fork {
139         10.do {
140                 Synth(\env_help);
141                 0.2.rand.wait;
142         }
147 // turn on
148 a.set(\gate, 1);
150 // turn off
151 a.set(\gate, 0);
153 // it does not matter to what value the gate is set, as long as it is > 0
154 a.set(\gate, 2);
156 a.free;
158 // using a gated envelope to gate a sound:
160 SynthDef(\env_help, { | out, gate = 0, freq = 440, doneAction = 0 |
161     var z = EnvGen.kr(Env.adsr, gate, doneAction: doneAction) * SinOsc.ar(freq, 0, 0.1);
162     Out.ar(out, z)
163 }).add;
166 a = Synth(\env_help);
169 // turn on
170 a.set(\gate, 1);
172 // turn off
173 a.set(\gate, 0);
175 // it does not matter to what value the gate is set, as long as it is > 0
176 a.set(\gate, 2);
178 a.set(\doneAction, 2, \gate, 0); // set doneAction to two to let the synth free itself
180 a.free; // alternatively, free it directly.
183 subsection:: Specifying an envelope for each new synth
184 code::
186 SynthDef(\help_Env_newClear, { |out = 0|
187         var env, envctl;
188         // make an empty 4 segment envelope
189         env = Env.newClear(4);
190         // create a control argument array
191         envctl = \env.kr(env.asArray);
192         Out.ar(out, 
193                 SinOsc.ar(EnvGen.kr(envctl, \gate.tr), 0, 0.3) // the gate control is a trigger
194         ); 
195 }).add;
198 Synth(\help_Env_newClear, [\gate, 1, \env, Env([700,900,900,800], [1,1,1], \exp)]); // 3 segments
200 // reset then play again:
201 Synth(\help_Env_newClear, [\gate, 1, \env, Env({ rrand(60, 70).midicps } ! 4, [1,1,1], \exp)]);
203 // the same written as an event:
204 (instrument: \help_Env_newClear, gate: 1, env: Env({ rrand(60, 70).midicps } ! 4, [1,1,1], \exp)).play;
208 subsection:: Forced release
209 If the gate of an EnvGen is set to -1 or below, then the envelope will cutoff immediately.
210 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.
211 The cutoff shape is linear.
212 code::
214 SynthDef(\stealMe, { |out, gate = 1|
215     Out.ar(out, {BrownNoise.ar}.dup * EnvGen.kr(Env.asr, gate, doneAction:2))
216 }).add;
219 a = Synth(\stealMe);
220 a.release(3); //  // cutoff in 3 seconds
222 // this is how the OSC data looks like:
223 s.sendMsg(\s_new, \stealMe, 1001, 1, 0);
224 s.sendMsg(\n_set, 1001, \gate, -1.1); // cutoff in 0.1 seconds
227 If the synthDef has an arg named "gate", the convenience method of Node can be used: code::node.release(releaseTime)::
228 code::
229 d = { arg gate=1; {BrownNoise.ar}.dup * EnvGen.kr(Env.asr, gate, doneAction:2) }.play;
230 d.release(3);
233 subsection:: Fast triggering tests
234 code::
237     EnvGen.kr(
238         Env.new([ 0.001, 1, 0.5, 0 ], [ 0.01, 0.3, 1 ], -4, 2, nil),
239         Impulse.kr(10)
240     ) * SinOsc.ar(440, 0, 0.1)
241 }.play;
246     EnvGen.kr(
247         Env.perc( 0.1, 0.0, 0.5, 1, \welch ),
248         Impulse.kr(100),
249         timeScale: 0.1
250     ) * SinOsc.ar(440, 0, 0.3)
251 }.play;
255 subsection:: Modulating the levelScale
256 code::
257 // no, it doesn't take a ugen in ...
260     EnvGen.kr(
261         Env.asr( 0.1, 1.0, 0.5, \welch ),
262         1.0,
263         FSinOsc.ar(1.0).range(0.0, 1.0),
264         timeScale: 0.1
265     ) * SinOsc.ar(440, 0, 0.3)
266 }.play;
269 // ...but an .ir rate input, a float or an ir rate ugen like Rand would work
272     EnvGen.kr(
273         Env.asr( 0.1, 1.0, 0.5, \welch ),
274         1.0,
275         Rand(0.1, 1.0),
276         timeScale: 0.1
277     ) * SinOsc.ar(440, 0, 0.3)
278 }.play;
282 subsection::More examples
284 For more information about the emphasis::control bus mapping:: used in the line code::a = Synth(\sine, [freq: f.asMap]);::, see link::Classes/Node#-map:: and link::Classes/Bus#-asMap::.
286 code::
288 // Changing an Env while playing
290 SynthDef(\env, { arg i_outbus=0;
291         var env, envctl;
292         
293         // make a dummy 8 segment envelope
294         env = Env.newClear(8);
295         
296         // create a control argument array
297         envctl = \env.kr( env.asArray );
298         
299         ReplaceOut.kr(i_outbus, EnvGen.kr(envctl, doneAction: 2));
300 }).add;
304 SynthDef(\sine, { |freq = 0|
305         Out.ar(0, SinOsc.ar(freq, 0, 0.2));
306 }).add;
309 f = Bus.control(s, 1);
310 f.set(800);
312 // use f's control bus value for frequency
313 // i.e. *map* the control to read from the bus
314 a = Synth(\sine, [freq: f.asMap]);
316 Synth(\env, [i_outbus: f, env: Env([700, 900, 900, 800], [1, 1, 1]*0.4, \exp)]);
318 Synth(\env, [i_outbus: f, env: Env([1000, 1000, 800, 1000, 900, 1000], [1, 1, 1, 1, 1]*0.3, \step)]);
320 a.free;
321 f.free;