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.
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.
21 { arg out = 0, freq=800, sustain=0.001, amp=0.5, pan = 0;
23 window = Env.sine(sustain, amp * AmpCompA.kr(freq));
28 ) * EnvGen.ar(window, doneAction:2)
34 { arg out = 0, freq=800, sustain=0.001, amp=0.5, pan = 0;
36 window = Env.perc(0.002, sustain, amp * AmpCompA.kr(freq));
39 Ringz.ar(PinkNoise.ar(0.1), freq, 2.6),
41 ) * EnvGen.ar(window, doneAction:2)
48 Pdef(\sweep, { arg sustain=1, n=8, freq=440, ratio=0.1;
51 \dur, sustain.value / n,
52 \freq, Pseq((1..n)) * ratio + 1 * freq.value // freq is a function, has to be evaluated
55 Pdef(\sweep2, { arg sustain=1, n=8, freq=440, ratio=0.1;
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,
63 Pdef(\sweep3, { arg freq=440;
67 \freq, Pfunc({ rrand(0.8, 1.3) }) * freq.value,
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.
82 \type, \phrase, // phrase event from global library
85 \degree, Pseq([0, 4, 6, 3], inf),
86 \sustain, Pseq([1.3, 0.2, 0.4],inf)
90 // multichannel expansion is propagated into the subpatterns
93 \type, \phrase, // phrase event from global library
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)
101 // various instruments and synthdefs can be used on the same level
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)
115 //////// of course also a patten can be used directly in a Pdef
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)
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
138 \degree, Pseq([0, 1b, 4, 2, 3, 1b], inf),
139 \pan, Pfunc(#{ 1.0.rand2 })
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;
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
172 \degree, Pseq((0..5),inf)
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)
183 \degree, Pseq((0..5),inf),
184 \legato, Pseq([1.2, 2.8, 0.3], inf)
188 // to block the proliferation of \legato into the phrase, set \transparency to 0
194 \degree, Pseq((0..5),inf),
195 \legato, Pseq([1.2, 2.8, 0.3], inf)
200 // recursion over one level
205 \degree, Pseq([0, 1, 2, 3], inf),
210 // recursion over one level: legato is recursively applied
215 \degree, Pseq([0, 1, 2, 3], inf),
216 \legato, Pseq([0.5, 1, 1.5, 1.8], inf),
221 // to block the proliferation of properties such as \legato and \degree
222 // into the phrase, set \transparency to 0.
227 \degree, Pseq([0, 1, 2, 3], inf),
228 \legato, Pseq([0.5, 1, 1.5, 1.8], inf),
234 // recursion over 3 levels: legato is recursively applied
240 \legato, Pseq([0.5, 1, 1.3], inf),
246 // to block the proliferation of \legato into the phrase, set \transparency to a level at which
247 // to stop passing the value.
253 \legato, Pseq([0.5, 1, 2.3], inf),
256 \transparency, Pstutter(8, Prand([0, 1, 2], inf))
262 // to modify this recursion, assign values explicitly:
264 Pdef(\sweep, { arg dur=1, n=4, ratio=0.5, freq=440;
267 legato = freq % 200 / 200 * 3 + 0.2;
269 \instrument, \pgrain,
272 \freq, Pseq((1..n) * ratio + 1 * freq)
277 // recursion over one level: degree is assigned to each phrase,
278 // because freq is calculated internally and overrides degree on the second level
283 \degree, Pseq((0..10),inf),
290 // recursion over two levels
300 // recursion over three levels with variable number of grains
306 \n, Pseq([1, 2, 3],inf),
313 TempoClock.default.tempo = 0.2;
314 TempoClock.default.tempo = 1.0;
317 // recursion over variable levels
322 \n, Prand([2, 7, 3], inf),
324 \recursionLevel, Prand([0, 1, 2],inf)
330 // replace the frequency based pattern with a degree based pattern
332 Pdef(\sweep, { arg sustain=1, n=8, degree=0, ratio=1;
334 \instrument, \pgrain,
335 \dur, sustain.value / n,
336 \degree, Pseq((1..n)) * ratio + 1 + degree.value
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)
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)
368 // use a different parent event in the inner pattern
371 e.use { ~sustain = { 2.0.exprand(0.05) } };
372 Pdef(\sweep, { arg sustain=1, n=8, degree=0, ratio=1;
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
387 \n, Prand([2, 4, 3, 8], inf),
388 \degree, Pseq([-5, 0, -2], inf),
389 \recursionLevel, Prand([0, 1],inf)
394 // pass in a pattern from outside
397 Pdef(\sweep, { arg sustain=1, n=8, degree=0, ratio=1;
400 \instrument, \pgrain,
401 \dur, sustain.value / n,
402 \degree, Pseq([ 1, 2, 3, 4, 5 ] * ratio + 1 + degree.value) )
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)
420 // recursion inside the pattern definition
423 Pdef(\sweep2, { arg sustain=1, n=2, degree=0, ratio=1;
427 \dur, sustain.value / n,
428 \degree, Pseq((1..5).scramble * ratio + 1 + degree.value),
437 \instrument, \sweep2,
439 \degree, Pseq([-5, 0, -2], inf)
444 // instruments do not crossfade while they play (to make phrasing more efficient).
452 \degree, Pseq([0, 2b, 3, 4], inf),
458 // change pattern definition while playing:
462 \instrument, \pgrain,
463 \dur, exprand(0.01, 0.1),
464 \legato, rrand(0.01, 2.0),
473 Pdef(\koch, { arg dur=1, freq=440;
476 \freq, freq.value * Pseq([1, 1.2, 1])
504 Pdef(\koch, { arg dur=1, degree=0;
507 \degree, degree + Pseq([0, 2, 0])
520 SynthDef(\play_from_to, { arg out, bufnum, from=0.0, to=1.0, sustain=1.0;
522 env = EnvGen.ar(Env.linen(0.01, sustain, 0.01), 1, doneAction:2);
525 Line.ar(from, to, sustain) * BufFrames.kr(bufnum)
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;
538 sustain = sustain.value;
539 step = (to - from) / n;
541 \instrument, \play_from_to,
542 \from, Pseries(from, step, n),
543 \to, Pseries(from, step, n) + step,
550 // this plays it straight
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;
567 sustain = sustain.value;
568 step = (to - from) / n;
569 f = Array.series(n, from, step) +.t [0.0, step];
573 \instrument, \play_from_to,
574 [\from, \to], Pseq(f),
587 \recursionLevel, Prand([0, 1, 2, 3], inf),
589 \to, Prand([-1, 1], inf),
591 \n, Prand([1, 2, 3], inf),