scel: install files to site-lisp/SuperCollider
[supercollider.git] / HelpSource / Tutorials / JITLib / recursive_phrasing.schelp
blob6437bb6fca6be1b5840ce4157d2c23553984accc
1 title:: recursive_phrasing
2 summary:: Recursive phrases and granular composite sounds
3 categories:: Libraries>JITLib>Tutorials
4 related:: Overviews/JITLib, Classes/Pdef, Classes/PlazyEnvir
6 Pdef can be used as a global storage for event patterns. Here a way is provided by which these definitions can be used as an instrument that consists of several events (a emphasis::phrase::), such as a cloud of short grains. Furthermore, this scheme can be applied recursively, so that structures like a cloud of clouds can be constructed.
8 When the event type code::\phrase:: is passed in, the event looks for a pattern in code::Pdef.all:: if it can find a definition.
9 list::
10 ## if it finds one it plays this pattern in the context of the outer pattern's event.
11 ## f there is no definition to be found there, it uses a link::Classes/SynthDef:: with this name, if present.
14 When passing a emphasis::function:: to Pdef it creates a PlazyEnvir internally. Its function is evaluated in the context of the outer environment (see link::Classes/PlazyEnvir::) which should return a pattern or a stream.
16 code::
18 s.boot;
20 SynthDef(\pgrain,
21         { arg out = 0, freq=800, sustain=0.001, amp=0.5, pan = 0;
22                 var window;
23                 window = Env.sine(sustain, amp * AmpCompA.kr(freq));
24                 Out.ar(out,
25                         Pan2.ar(
26                                 SinOsc.ar(freq),
27                                 pan
28                         ) * EnvGen.ar(window, doneAction:2)
29                 )
30         }
31 ).add;
33 SynthDef(\noiseGrain,
34         { arg out = 0, freq=800, sustain=0.001, amp=0.5, pan = 0;
35                 var window;
36                 window = Env.perc(0.002, sustain, amp * AmpCompA.kr(freq));
37                 Out.ar(out,
38                         Pan2.ar(
39                                 Ringz.ar(PinkNoise.ar(0.1), freq, 2.6),
40                                 pan
41                         ) * EnvGen.ar(window, doneAction:2)
42                 )
43         }
44 ).add;
48 Pdef(\sweep, { arg sustain=1, n=8, freq=440, ratio=0.1;
49         Pbind(
50                 \instrument, \pgrain,
51                 \dur, sustain.value / n,
52                 \freq, Pseq((1..n)) * ratio + 1 * freq.value // freq is a function, has to be evaluated
53         )
54 });
55 Pdef(\sweep2, { arg sustain=1, n=8, freq=440, ratio=0.1;
56         Pbind(
57                 \instrument, \noiseGrain,
58                 \dur, sustain.value / n, // sustain is also a function, has to be evaluated
59                 \freq, Pseq((1..n).scramble) * ratio + 1 * freq.value,
60                 \recursionLevel, 2
61         )
62 });
63 Pdef(\sweep3, { arg freq=440;
64         Pbind(
65                 \type, \phrase,
66                 \instrument, \sweep,
67                 \freq, Pfunc({ rrand(0.8, 1.3) }) * freq.value,
68                 \dur, 0.3,
69                 \legato, 1.3,
70                 \n, 5
71         )
72 });
78 // the pattern that is found in Pdef.all (or your own defined library) is truncated in time
79 // using the sustain provided by the outer pattern.
81 Pbind(
82         \type, \phrase, // phrase event from global library
83         \instrument, \sweep,
84         \n, 15,
85         \degree, Pseq([0, 4, 6, 3], inf),
86         \sustain, Pseq([1.3, 0.2, 0.4],inf)
87 ).play
90 // multichannel expansion is propagated into the subpatterns
92 Pbind(
93         \type, \phrase, // phrase event from global library
94         \instrument, \sweep,
95         \n, 15,
96         \degree, Pseq([0, 0, 6, 3], inf) + Prand([0, [0, 3], [0, 5], [0, 15]], inf),
97         \ratio, Prand([ 0.1, 0.1, [0.1, -0.1] ], inf)
98 ).play
101 // various instruments and synthdefs can be used on the same level
103 Pbind(
104         \type, \phrase,
105         \instrument, Pseq([\sweep, \default, \sweep2, \sweep3, \pgrain, \pgrain], inf),
106         \degree, Pseq([0, 3, 2], inf),
107         \dur, Pseq([1, 0.5], inf) * 0.7,
108         \n, Pseq([4, 6, 25, 10], inf),
109         \ratio, Prand([0.03, 0.1, 0.4, -0.1],inf) + Pseq([0, 0, [0, 0.02]], inf),
110         \legato, Pseq(#[0.5, 1, 0.5, 0.1, 0.1],inf)
111 ).play;
115 //////// of course also a patten can be used directly in a Pdef
118 Pdef(\sweep,
119         Pbind(
120                 \instrument, Pseq([\pgrain, \noiseGrain],inf),
121                 \dur, Pseq([1, 2, 1, 3, 1, 4, 1, 5]) * 0.05,
122                 \legato, Prand([0.5, 0.5, 3],inf)
123         )
127 // play directly, emebdded in stream (see Pdef.help)
129 Pn(Pdef(\sweep), 2).play;
130 Pdef(\sweep).fork; // play without changing player state (see Pdef.help)
133 // play within a pattern
135 Pbind(
136         \type, \phrase,
137         \instrument, \sweep,
138         \degree, Pseq([0, 1b, 4, 2, 3, 1b], inf),
139         \pan, Pfunc(#{ 1.0.rand2 })
140 ).play
145 //////// recursion examples //////////
147 // the given pattern can be recursively applied to itself
148 // resulting in selfsimilar sound structures, like lindenmeyer systems (see also Prewrite)
149 // special care is taken so that no infinite loops can happen.
150 // just like with non recursive phrasing, new values override old values,
151 // any values that are not provided within the pattern definition
152 // are passed in from the outer event.
157 Pdef(\sweep, { arg dur=1, n=4, freq=440, ratio=0.3;
158         Pbind(
159                 \instrument, \pgrain,
160                 \dur, dur.value / n,    // now dur is dependant on outer dur.
161                 \freq, Pseries(1, 1, inf) * ratio + 1 * freq.value % 17000
162         )
167 // no recursion
169         Pbind(
170                 \type, \phrase,
171                 \instrument, \sweep,
172                 \degree, Pseq((0..5),inf)
173         ).play;
176 // no recursion, with legato > 1.0 and varying notes
177 // note how subpatterns are truncated to note length
178 // provided by outer pattern (in this case determined by legato)
180         Pbind(
181                 \type, \phrase,
182                 \instrument, \sweep,
183                 \degree, Pseq((0..5),inf),
184                 \legato, Pseq([1.2, 2.8, 0.3], inf)
185         ).play;
188 // to block the proliferation of \legato into the phrase, set \transparency to 0
190         Pbind(
191                 \type, \phrase,
192                 \instrument, \sweep,
193                 \transparency, 0,
194                 \degree, Pseq((0..5),inf),
195                 \legato, Pseq([1.2, 2.8, 0.3], inf)
196         ).play;
200 // recursion over one level
202         Pbind(
203                 \type, \phrase,
204                 \instrument, \sweep,
205                 \degree, Pseq([0, 1, 2, 3], inf),
206                 \recursionLevel, 1
207         ).play
210 // recursion over one level: legato is recursively applied
212         Pbind(
213                 \type, \phrase,
214                 \instrument, \sweep,
215                 \degree, Pseq([0, 1, 2, 3], inf),
216                 \legato, Pseq([0.5, 1, 1.5, 1.8], inf),
217                 \recursionLevel, 1
218         ).play
221 // to block the proliferation of properties such as \legato and \degree
222 // into the phrase, set \transparency to 0.
224         Pbind(
225                 \type, \phrase,
226                 \instrument, \sweep,
227                 \degree, Pseq([0, 1, 2, 3], inf),
228                 \legato, Pseq([0.5, 1, 1.5, 1.8], inf),
229                 \recursionLevel, 1,
230                 \transparency, 0
231         ).play
234 // recursion over 3 levels: legato is recursively applied
236         Pbind(
237                 \type, \phrase,
238                 \instrument, \sweep,
239                 \degree, 1,
240                 \legato, Pseq([0.5, 1, 1.3], inf),
241                 \recursionLevel, 3,
242                 \n, 3
243         ).play
246 // to block the proliferation of \legato into the phrase, set \transparency to a level at which
247 // to stop passing the value.
249         Pbind(
250                 \type, \phrase,
251                 \instrument, \sweep,
252                 \degree, 1,
253                 \legato, Pseq([0.5, 1, 2.3], inf),
254                 \recursionLevel, 3,
255                 \n, 3,
256                 \transparency, Pstutter(8, Prand([0, 1, 2], inf))
257         ).play
262 // to modify this recursion, assign values explicitly:
264 Pdef(\sweep, { arg dur=1, n=4, ratio=0.5, freq=440;
265         var legato;
266         freq = freq.value;
267         legato = freq % 200 / 200 * 3 + 0.2;
268         Pbind(
269                 \instrument, \pgrain,
270                 \dur, dur.value / n,
271                 \legato, legato,
272                 \freq, Pseq((1..n) * ratio + 1 * freq)
273         )
277 // recursion over one level: degree is assigned to each phrase,
278 // because freq is calculated internally and overrides degree on the second level
280         Pbind(
281                 \type, \phrase,
282                 \instrument, \sweep,
283                 \degree, Pseq((0..10),inf),
284                 \recursionLevel, 1
285         ).play
290 // recursion over two levels
292 Pbind(
293         \type, \phrase,
294         \instrument, \sweep,
295         \degree, 0,
296         \recursionLevel, 2
297 ).play
300 // recursion over three levels with variable number of grains
302 Pbind(
303         \type, \phrase,
304         \instrument, \sweep,
305         \degree, -5,
306         \n, Pseq([1, 2, 3],inf),
307         \recursionLevel, 3
308 ).play
312 // "zoom" in
313 TempoClock.default.tempo = 0.2;
314 TempoClock.default.tempo = 1.0;
317 // recursion over variable levels
319 Pbind(
320         \type, \phrase,
321         \instrument, \sweep,
322         \n, Prand([2, 7, 3], inf),
323         \degree, -5,
324         \recursionLevel, Prand([0, 1, 2],inf)
325 ).play
330 // replace the frequency based pattern with a degree based pattern
332 Pdef(\sweep, { arg sustain=1, n=8, degree=0, ratio=1;
333         Pbind(
334                 \instrument, \pgrain,
335                 \dur, sustain.value / n,
336                 \degree, Pseq((1..n)) * ratio + 1 + degree.value
337         )
342 // drunken master
344 Pbind(
345         \type, \phrase,
346         \instrument, \sweep,
347         \n, Prand([2, 4, 3, 8], inf),
348         \degree, Pseq([-5, 0, -2], inf),
349         \legato, Pseq([1.4, 0.5, 2], inf),
350         \scale, #[0, 2, 5, 7, 10],
351         \recursionLevel, Prand([0, 1, 2],inf)
352 ).play
357 Pbind(
358         \type, \phrase,
359         \instrument, \sweep,
360         \synthDef, Prand([\pgrain, \default, \noiseGrain],inf),
361         \n, Prand([2, 4, 3, 8], inf),
362         \degree, Pseq([-5, 0, -2], inf),
363         \recursionLevel, Prand([0, 1],inf)
364 ).play
368 // use a different parent event in the inner pattern
370 e = Event.default;
371 e.use { ~sustain = { 2.0.exprand(0.05) } };
372 Pdef(\sweep, { arg sustain=1, n=8, degree=0, ratio=1;
373         Pbind(
374                 \parent, e, // replace by some other event
375                 \instrument, \pgrain,
376                 \dur, sustain.value / n,
377                 \degree, Pseq((1..n)) * ratio + 1 + degree.value
378         )
384 Pbind(
385         \type, \phrase,
386         \instrument, \sweep,
387         \n, Prand([2, 4, 3, 8], inf),
388         \degree, Pseq([-5, 0, -2], inf),
389         \recursionLevel, Prand([0, 1],inf)
390 ).play
394 // pass in a pattern from outside
397 Pdef(\sweep, { arg sustain=1, n=8, degree=0, ratio=1;
398         n = n.value;
399         Pbind(
400                 \instrument, \pgrain,
401                 \dur, sustain.value / n,
402                 \degree, Pseq([ 1, 2, 3, 4, 5 ] * ratio + 1 + degree.value) )
408 Pbind(
409         \type, \phrase,
410         \instrument, \sweep,
411         \n, { Pshuf([2, 4, 3, 8, 16, 32], inf) }, // use a function to insulate from embedInStream
412         \degree, Pseq([-5, 0, -2], inf),
413         \recursionLevel, Prand([0, 1],inf)
414 ).play
420 // recursion inside the pattern definition
423 Pdef(\sweep2, { arg sustain=1, n=2, degree=0, ratio=1;
424         Pbind(
425                 \type, \phrase,
426                 \instrument, \sweep,
427                 \dur, sustain.value / n,
428                 \degree, Pseq((1..5).scramble * ratio + 1 + degree.value),
429                 \recursionLevel, 2
430         )
435 Pbind(
436         \type, \phrase,
437         \instrument, \sweep2,
438         \n, 3,
439         \degree, Pseq([-5, 0, -2], inf)
440 ).play
444 // instruments do not crossfade while they play (to make phrasing more efficient).
448 Pbind(
449         \type, \phrase,
450         \instrument, \sweep,
451         \n, 3,
452         \degree, Pseq([0, 2b, 3, 4], inf),
453         \dur, 2,
454         \legato, 2
455 ).play
458 // change pattern definition while playing:
460 Pdef(\sweep,
461         Pbind(
462                 \instrument, \pgrain,
463                 \dur, exprand(0.01, 0.1),
464                 \legato, rrand(0.01, 2.0),
465                 \octave, rrand(5, 7)
466         )
471 // koch "snowflake"
473 Pdef(\koch, { arg dur=1, freq=440;
474         Pbind(
475                 \dur, dur.value / 3,
476                 \freq, freq.value * Pseq([1, 1.2, 1])
477         )
482         Pbind(
483                 \type, \phrase,
484                 \instrument, \koch,
485                 \synthDef, \pgrain,
486                 \dur, 9,
487                 \recursionLevel, 2,
488                 \legato, 1.1
489         ).play
493         Pbind(
494                 \type, \phrase,
495                 \instrument, \koch,
496                 \synthDef, \pgrain,
497                 \dur, 9,
498                 \recursionLevel, 4,
499                 \legato, 1.1
500         ).play
504 Pdef(\koch, { arg dur=1, degree=0;
505         Pbind(
506                 \dur, dur.value / 3,
507                 \degree, degree + Pseq([0, 2, 0])
508         )
516 // soundfile example
520 SynthDef(\play_from_to, { arg out, bufnum, from=0.0, to=1.0, sustain=1.0;
521         var env;
522         env = EnvGen.ar(Env.linen(0.01, sustain, 0.01), 1, doneAction:2);
523         Out.ar(out,
524                 BufRd.ar(1, bufnum,
525                         Line.ar(from, to, sustain) * BufFrames.kr(bufnum)
526                 ) * env
527         )
530 }).add;
533 b = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav")
536 Pdef(\poch, { arg sustain=1.0, from=0.0, to=1.0, n=3;
537                 var step;
538                 sustain = sustain.value;
539                 step = (to - from) / n;
540                 Pbind(
541                         \instrument, \play_from_to,
542                         \from, Pseries(from, step, n),
543                         \to, Pseries(from, step, n) + step,
544                         \legato, 1.0,
545                         \dur, sustain / n
546                 )
550 // this plays it straight
552 Pbind(
553         \type, \phrase,
554         \instrument, \poch,
555         \recursionLevel, 3,
556         \from, 0,
557         \to, 1,
558         \dur, 3,
559         \bufnum, b
560 ).play
563 // now turn round every middle part of every middle part
565 Pdef(\poch, { arg sustain=1.0, from=0.0, to=1.0, n=3;
566         var step, f, t, i;
567         sustain = sustain.value;
568         step = (to - from) / n;
569         f = Array.series(n, from, step) +.t [0.0, step];
570         i = n div: 2;
571         f[i] = f[i].reverse;
572         Pbind(
573                 \instrument, \play_from_to,
574                 [\from, \to], Pseq(f),
575                 \legato, 1.0,
576                 \dur, sustain / n
577         )
582 // varying recursion
584 Pbind(
585         \type, \phrase,
586         \instrument, \poch,
587         \recursionLevel, Prand([0, 1, 2, 3], inf),
588         \from, 0,
589         \to, Prand([-1, 1], inf),
590         \dur, 3,
591         \n, Prand([1, 2, 3], inf),
592         \bufnum, b,
593         \amp, 0.2
594 ).play