class library: SynthDef - lazy implementation of removeUGen
[supercollider.git] / HelpSource / Classes / Env.schelp
blob279038d62d9e410706151946fedc0d9cba0286e9
1 class:: Env
2 summary:: Specification for a segmented envelope
3 related:: Classes/EnvGen, Classes/InterplEnv
4 categories:: Control, Envelopes
6 description::
7 An Env is a specification for a segmented envelope. Envs can be used both server-side, by an link::Classes/EnvGen:: within a link::Classes/SynthDef::, and clientside, with methods such as link::#-at:: and link::#-asStream::, below.
9 An Env can have any number of segments which can stop at a particular value or loop several segments when sustaining. It can have several shapes for its segments.
11 code::
12 Env.new([0,1,0.9,0], [0.1,0.5, 1],[-5,0,-5]).plot;
15 The envelope is conceived as a sequence of emphasis::nodes:: (not to be confused with a synthesis-Node) each of which has three parameters: a target level, a time duration from the previous node, and a shape. The three parameters for each node are kept in separate arrays as explained below.
17 note::
18 In some other computer music systems and situations we deal with control points or breakpoints. If these control points have associated x positions (say in an envelope GUI, see link::Classes/EnvelopeView::) they must be converted to time differences between points to be used as nodes in a Env object.
21 ClassMethods::
23 private::initClass
25 method::new
26 Create a new envelope specification.
28 argument::levels
29 an array of levels. The first level is the initial value of the envelope.
31 argument::times
32 an array of durations of segments in seconds. There should be one fewer duration than there are levels.
34 argument::curve
35 a link::Classes/Symbol::, link::Classes/Float::, or an link::Classes/Array:: of those. Determines the shape of the envelope segments.
37 The possible values are:
38 table::
39 ## code::\step:: || || flat segments
40 ## code::\linear:: || code::\lin:: || linear segments, the default
41 ## code::\exponential:: || code::\exp:: || natural exponential growth and decay. In this case, the levels must all be nonzero and the have the same sign.
42 ## code::\sine:: || code::\sin:: || sinusoidal S shaped segments.
43 ## code::\welch:: || code::\wel:: || sinusoidal segments shaped like the sides of a Welch window.
44 ## code::\squared::  || code::\sqr:: || squared segment
45 ## code::\cubed:: || code::\cub:: || cubed segment
46 ## a link::Classes/Float:: || || a curvature value for all segments. 0 means linear, positive and negative numbers curve the segment up and down.
47 ## an link::Classes/Array:: of symbols or floats || || curvature values for each segment.
50 argument::releaseNode
51 an link::Classes/Integer:: or nil. The envelope will sustain at the release node until released.
53 argument::loopNode
54 an link::Classes/Integer:: or nil. If not nil the output will loop through those nodes startign at the loop node to the node immediately preceeding the release node, before back to the loop node, and so on. Note that the envelope only transitions to the release node when released. Examples are below. The loop is escaped when a gate signal is sent, when the output transitions to the release node, as described below.
56 method::newClear
57 Creates a new envelope specification with strong::numSegments:: for filling in later.
58 discussion::
59 This can be useful when passing Env parameters as args to a link::Classes/Synth::. Note that the maximum number of segments is fixed and cannot be changed once embedded in a link::Classes/SynthDef::. Trying to set an Env with more segments than then this may result in other args being unexpectedly set. See link::#newClear:: example below.
61 subsection::Standard Shape Envelope Creation Methods
62 The following class methods create some frequently used envelope shapes based on supplied durations.
64 method::linen
65 Creates a new envelope specification which has a trapezoidal shape.
67 argument::attackTime
68 the duration of the attack portion.
70 argument::sustainTime
71 the duration of the sustain portion.
73 argument::releaseTime
74 the duration of the release portion.
76 argument::level
77 the level of the sustain portion.
79 argument::curve
80 the curvature of the envelope.
82 discussion::
83 code::
84 s.boot;
85 Env.linen(1, 2, 3, 0.6).test.plot;
86 Env.linen(0.1, 0.2, 0.1, 0.6).test.plot;
87 Env.linen(1, 2, 3, 0.6, 'sine').test.plot;
88 Env.linen(1, 2, 3, 0.6, 'welch').test.plot;
89 Env.linen(1, 2, 3, 0.6, -3).test.plot;
90 Env.linen(1, 2, 3, 0.6, -3).test.plot;
93 method::triangle
94 Creates a new envelope specification which has a triangle shape.
96 argument::duration
97 the duration of the envelope.
99 argument::level
100 the peak level of the envelope.
102 discussion::
103 code::
104 Env.triangle(1, 1).test.plot;
107 method::sine
108 Creates a new envelope specification which has a hanning window shape.
110 argument::duration
111 the duration of the envelope.
113 argument::level
114 the peak level of the envelope.
116 discussion::
117 code::
118 Env.sine(1, 1).test.plot;
121 method::perc
122 Creates a new envelope specification which (usually) has a percussive shape.
124 argument::attackTime
125 the duration of the attack portion.
127 argument::releaseTime
128 the duration of the release portion.
130 argument::peakLevel
131 the peak level of the envelope.
133 argument::curve
134 the curvature of the envelope.
136 discussion::
137 code::
138 Env.perc(0.05, 1, 1, -4).test.plot;
139 Env.perc(0.001, 1, 1, -4).test.plot;    // sharper attack
140 Env.perc(0.001, 1, 1, -8).test.plot;    // change curvature
141 Env.perc(1, 0.01, 1, 4).test.plot;      // reverse envelope
144 subsection::Sustained Envelope Creation Methods
145 The following methods create some frequently used envelope shapes which have a sustain segment.
147 method::adsr
148 Creates a new envelope specification which is shaped like traditional analog attack-decay-sustain-release (adsr) envelopes.
150 argument::attackTime
151 the duration of the attack portion.
153 argument::decayTime
154 the duration of the decay portion.
156 argument::sustainLevel
157 the level of the sustain portion as a ratio of the peak level.
159 argument::releaseTime
160 the duration of the release portion.
162 argument::peakLevel
163 the peak level of the envelope.
165 argument::curve
166 the curvature of the envelope.
168 discussion::
169 code::
170 Env.adsr(0.02, 0.2, 0.25, 1, 1, -4).test(2).plot;
171 Env.adsr(0.001, 0.2, 0.25, 1, 1, -4).test(2).plot;
172 Env.adsr(0.001, 0.2, 0.25, 1, 1, -4).test(0.45).plot;   //release after 0.45 sec
175 method::dadsr
176 As link::#*adsr:: above, but with it's onset delayed by strong::delayTime:: in seconds. The default delay is 0.1.
178 method::asr
179 Creates a new envelope specification which is shaped like traditional analog attack-sustain-release (asr) envelopes.
181 argument::attackTime
182 the duration of the attack portion.
184 argument::sustainLevel
185 the level of the sustain portion as a ratio of the peak level.
187 argument::releaseTime
188 the duration of the release portion.
190 argument::curve
191 the curvature of the envelope.
193 discussion::
194 code::
195 Env.asr(0.02, 0.5, 1, -4).test(2).plot;
196 Env.asr(0.001, 0.5, 1, -4).test(2).plot; // sharper attack
197 Env.asr(0.02, 0.5, 1, 'linear').test(2).plot; // linear segments
200 method::cutoff
201 Creates a new envelope specification which has no attack segment. It simply sustains at the peak level until released. Useful if you only need a fadeout, and more versatile than link::Classes/Line::.
203 argument::releaseTime
204 the duration of the release portion.
206 argument::level
207 the peak level of the envelope.
209 argument::curve
210 the curvature of the envelope.
212 discussion::
213 code::
214 Env.cutoff(1, 1).test(2).plot;
215 Env.cutoff(1, 1, 4).test(2).plot;
216 Env.cutoff(1, 1, 'sine').test(2).plot;
219 InstanceMethods::
221 private::prAsArray
223 method::blend
224 Blend two envelopes. Returns a new Env. See link::#blend:: example below.
226 argument::anotherEnv
227 an Env.
229 argument::blendFraction
230 a number from zero to one.
232 method::delay
233 Returns a new Env based on the receiver in which the start value will be held for strong::delay:: number of seconds.
235 argument::delay
236 The amount of time to delay the start of the envelope.
238 discussion::
239 code::
240 a = Env.perc(0.05, 1, 1, -4);
241 b = a.delay(2);
242 a.test.plot;
243 b.test.plot;
245 a = Env([0.5, 1, 0], [1, 1]).plot;
246 a.delay(1).plot;
249 method::circle
250 circle from end to beginning over the time specified, with the curve specified.
251 discussion::
252 code::
254 { SinOsc.ar(
255         EnvGen.kr(
256                 Env([6000, 700, 100], [1, 1], ['exp', 'lin']).circle.postcs)
257         ) * 0.1
258         + Impulse.ar(1) }.play;
262 { SinOsc.ar(
263         EnvGen.kr(
264                 Env([6000, 700, 100], [1, 1], ['exp', 'lin']).circle(1).postcs,
265                 MouseX.kr > 0.5)
266         ) * 0.1
267         + Impulse.ar(1) }.play;
271 method::test
272 Test the envelope on the default link::Classes/Server:: with a link::Classes/SinOsc::.
274 argument::releaseTime
275 If this is a sustaining envelope, it will be released after this much time in seconds. The default is 3 seconds.
277 method::plot
278 Plot this envelope's shape in a window.
280 argument::size
281 The size of the plot. The default is 400.
283 argument::bounds
284 the size of the plot window.
286 argument::minval
287 the minimum value in the plot. Defaults to the lowest value in the data.
289 argument::maxval
290 the maximum value in the plot. Defaults to the highest value in the data.
292 argument::parent
293 a window to place the plot in. If nil, one will be created for you.
295 method::asSignal
296 Returns a link::Classes/Signal:: of size strong::length:: created by sampling this Env at strong::length:: number of intervals.
298 method::asArray
299 Converts the Env to an link::Classes/Array:: in a specially ordered format. This allows for Env parameters to be settable arguments in a SynthDef. See example below under link::#newClear::.
301 method::isSustained
302 Returns true if this is a sustaining envelope, false otherwise.
304 method::range, exprange
305 Returns a copy of the Env whose levels have been mapped onto the given linear or exponential range.
306 discussion::
307 code::
308 a = Env.adsr;
309 a.levels;
310 a.range(42, 45).levels;
311 a.exprange(42, 45).levels;
314 // Mapping an Env to an exponential frequency range:
316         SinOsc.ar(EnvGen.ar(Env.perc(0.01, 0.2).exprange(40, 10000), doneAction: 2)
317                 , 0, 0.1).dup;
318 }.play(s)
322 subsection::Client-side Access and Stream Support
323 Sustain and loop settings have no effect in the methods below.
325 method::at
326 Returns the value of the Env at strong::time::.
327 discussion::
328 code::
329 Env.triangle(1, 1).at(0.5);
332 method::embedInStream
333 Embeds this Env within an enclosing link::Classes/Stream::. Timing is derived from code::thisThread.beats::.
335 method::asStream
336 Creates a Routine and embeds the Env in it. This allows the Env to function as a link::Classes/Stream::.
337 discussion::
338 code::
341 e = Env.sine.asStream;
342 5.do({
343         e.next.postln;
344         0.25.wait;
345 })}.fork
349 Examples::
351 code::
352 s.boot;         //.test below will run a synthesis example
353                 // to demonstrate the envelope, so the Server must be on
355 // different shaped segments: .plot graphs the Env
356 Env.new([0,1, 0.3, 0.8, 0], [2, 3, 1, 4],'linear').test.plot;
357 Env.new([0.001, 1, 0.3, 0.8, 0.001], [2, 3, 1, 4],'exponential').test.plot;
358 Env.new([0, 1, 0.3, 0.8, 0], [2, 3, 1, 4],'sine').test.plot;
359 Env.new([0.001, 1, 0.3, 0.8, 0.001],[2,3,1,4],'welch').test.plot;
360 Env.new([0, 1, 0.3, 0.8, 0], [2, 3, 1, 4],'step').test.plot;
361 Env.new([0, 1, 0.3, 0.8, 0], [2, 3, 1, 4], -2).test.plot;
362 Env.new([0, 1, 0.3, 0.8, 0], [2, 3, 1, 4], 2).test.plot;
363 Env.new([0, 1, 0.3, 0.8, 0], [2, 3, 1, 4], [0, 3, -3, -1]).test.plot;
366 If a release node is given, and the gate input of the EnvGen is set to zero, it outputs the nodes after the release node:
368 code::
369 // release node is node 1; takes 0.5 seconds to go from 0 to 1,
370 // sustains at level of 1, then released after three seconds
371 // (test causes the release after three seconds, given the argument 3),
372 // taking 2 seconds to finish
373 Env.new([0,1,0],[0.5,2],'linear',1).test(3).plot
375 // more complex examples
376 // release node is node 2; releases after 5 sec
377 Env.new([0.001,1,0.3,0.8,0.001],[2,3,1,4] * 0.2, 2, 2).test(5).plot;
378 Env.new([0.001,1,0.3,0.8,0.5,0.8,0],[2,3,1,2,2,1] * 0.2, 2, 2).test(5).plot;
380 // early release: goes straight onto the release node after 0.1 seconds
381 Env.new([0.001,1,0.3,0.8,0.5,0.8,0],[2,3,1,2,2,1] * 0.2, 2, 2).test(0.1).plot;
384 If a loop node is given, the EnvGen outputs the nodes between the loop node and the release node (not including the release node itself) until it is released:
386 code::
387 // release node is node 2, loop node is node 0: so loops around nodes 0 (lvl 1, dur 0.5)
388 // and 1 (lvl 0.1, dur 0.5)             //until released after 3.5 seconds
389 Env.new([0,1,0.1,0],[0.5,0.5,2], 'lin', 2, 0).test(3.5).plot;
391 // this just sustains at node 0, because there is no other node to loop around!
392 Env.new([0,1,0],[0.5,2], 'lin', 1, 0).test(3.5).plot;
394 // more complex example: release node is node 3, loop node is node 1
395 Env.new([0.001,1,0.3,0.8,0.5,0.8,0],[2,1,1,2,3,1] * 0.1, 'lin', 3, 1).test(3).plot;
398 note::
399 The starting level for an envelope segment is always the level you are at right now. For example when the gate is released and you jump to the release segment, the level does not jump to the level at the beginning of the release segment, it changes from whatever the current level is to the goal level of the release segment over the specified duration of the release segment.
401 There is an extra level at the beginning of the envelope to set the initial level. After that each node is a goal level and a duration, so node zero has duration equal to times[0] and goal level equal to levels[1].
403 The loop jumps back to the loop node. The endpoint of that segment is the goal level for that segment and the duration of that segment will be the time over which the level changed from the current level to the goal level.
406 subsection::newClear
407 code::
409 SynthDef(\help_Env_newClear, { |i_outbus=0, t_gate|
410         var env, envctl;
411         // make an empty 4 segment envelope
412         env = Env.newClear(4);
413         // create a control argument array
414         envctl = Control.names([\env]).kr( env.asArray );
415         Out.ar(i_outbus, SinOsc.ar(EnvGen.kr(envctl, t_gate), 0, 0.3));
416 }).send(s);
419 s.bind {
420         // must not have more segments than the env above
421         e = Env([700,900,900,800], [1,1,1], \exp); // 3 segments
422         x = Synth(\help_Env_newClear, [\t_gate, 1]);
423         x.setn(\env, e.asArray);
427 // reset then play again
428 e = Env([800,300,400,500,200], [1,1,1,1], \exp); // 4 segments
429 x.setn(\env, e.asArray);
430 x.set(\t_gate, 1);
432 x.free;
435 subsection::blend
436 code::
437 a = Env([0, 0.2, 1, 0.2, 0.2, 0], [0.5, 0.01, 0.01, 0.3, 0.2]).test.plot;
438 b = Env([0, 0.4, 1, 0.2, 0.5, 0], [0.05, 0.4, 0.01, 0.1, 0.4]).test.plot;
441 Task({
442         f = (0, 0.2 .. 1);
443         f.do { |u|
444                 blend(a, b, u).test.plot;
445                 2.wait;
446                 Window.allWindows.pop.close; // close last opened window
447         }
448 }).play(AppClock);
451 // blend in a SynthDef
453 SynthDef(\help_EnvBlend, { | fact = 0 |
454         Out.ar(0, EnvGen.kr(Env.perc.blend(Env.sine, fact), 1.0, doneAction: 2)
455                 * SinOsc.ar(440,0,0.1)
456         )
457 }).send(s));
461 f = (0, 0.1..1);
462 f.do({|fact| Synth(\help_EnvBlend, [\fact, fact.postln]); 1.wait;});
463 }.fork;)