This file is indexed.

/usr/share/SuperCollider/HelpSource/Classes/Pdef.schelp is in supercollider-common 1:3.8.0~repack-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
class:: Pdef
summary:: stream reference definition
categories:: Libraries>JITLib>Patterns
related:: Classes/Pdefn, Classes/PdefGui

description::
Pdef is a class that provides an interface to its superclass link::Classes/EventPatternProxy::, keeping a reference to a stream that can be replaced while playing. One pattern may be used in many streams in different places. A change in the pattern definition propagates through all streams.

Pdef and Pdefn use separate global collections.

code::
Pdef(key)	//returns the instance
Pdef(key, pat)	//stores the pattern and returns the instance, like Tdef and Ndef.
::

It can be used to store event Patterns globally. Changes in this global library have immediate effect.

For strong::non-event patterns:: link::Classes/Pdefn:: is used instead. For another use of Pdef see also link::Tutorials/JITLib/recursive_phrasing::. Graphical overview over all current Pdefs: link::Classes/PdefAllGui::. Overview: link::Overviews/JITLib::.

subsection::First Example

code::
s.boot;

Pdef(\x, Pbind(\note, Pbrown(0, 6, 0.1, inf)));
Pdef(\x).quant = 0; // no waiting.
Pbindf(Pdef(\x), \dur, 0.03).play;
Pbindf(Pdef(\x), \dur, 0.1, \ctranspose, 15).play;
Pbindf(Pdef(\x), \dur, 0.3, \ctranspose, 2).play;
// now change the definition
Pdef(\x, Pbind(\note, Pseq([0, 3, 5, 7, 9, 11], inf)));
Pdef(\x, Pbind(\freq, Pseq([1000, 1923, 245.2, 1718] / 1.2 + 0.1, inf)));
::

ClassMethods::

private::initClass

subsection::Creation

method::new
Store the pattern in a global dictionary under key, replacing its pattern with the new one. If the pattern is a strong::function::, Pdef creates a link::Classes/PlazyEnvir:: internally that dynamically creates the pattern returned from the function, applying the arguments from the inevent.

Using strong::*new(key):: you can access the pattern at that key (if none is given, a default silent event is created)

code::

(
SynthDef(\Pdefhelp, { arg out, freq, sustain=1, amp=1, pan;
    var env = EnvGen.kr(Env.perc(0.01, sustain), 1, doneAction:2);
    Out.ar(out, Pan2.ar(SinOsc.ar(freq, 0.5pi, amp * env), pan));
}).add;
)

// event pattern as an argument
Pdef(\x, Pbind(\instrument, \Pdefhelp, \note, Pbrown(0, 6, 0.1, inf), \dur, 0.2));
Pdef(\x); // omitting the second argument, we can access the proxy
Pdef(\x).play; // ... play one event stream
Pdef(\x).source.postcs; // ... and inspect the event pattern itself.


// function as an argument, create a new pattern each time it is called
Pdef(\x, { Pbind(\note, Pseries(10.rand, 5.rand, 8.rand + 1), \dur, 1 / (8.rand + 1)) });
Pn(Pdef(\x)).play;

// the function is called in the incoming event as current environment, so parameters can be passed:
Pdef(\stut, { Pstutter(~stutter ? 1, ~pattern) });
Pdef(\x, Pbind(\instrument, \Pdefhelp, \note, Pseq([0, 4, 7, 3, 0, 1, 0], inf)));
Pdef(\y, Pdef(\stut) <> (pattern: Pdef(\x), stutter: Pseq([2, 2, 4, 3], inf)) <> (dur: 0.1, legato: 0.2)).play;

::



method::default
Default source, if none is given. The default is an Event.silent of 1.0 beat duration.

method::removeAll
Remove all proxies from the global dictionary ( link::#*all:: )

method::clear
Clear all proxies, setting their source to silence.

method::all
Set or return the environment ( link::Classes/IdentityDictionary:: ) that stores all Pdefs.

method::defaultQuant
Set the default quantisation for new instances (default: 1.0). This can be an array [quant, phase, timingOffset, outset]

InstanceMethods::

subsection::Changing the definition / setting the source

One pattern may have many streams in different places. A change in the pattern definition Pdef propagates through all streams. The change does not have to be immediate - there is a scheme to schedule when the change becomes effective: a strong::quant:: and strong::clock:: (like elsewhere) and a strong::condition::.

method::quant
Set the quantisation time for beat accurate scheduling.

argument::val
can be an array strong::[quant, phase, timingOffset, outset] ::, or just strong::[quant, phase]:: etc.

method::condition
Provide a condition under which the pattern is switched when a new one is inserted. The stream value and a count value is passed into the function.

method::count
Create and update condition that simply counts up to n and switches the pattern then

method::reset
Switch the pattern immediately (stuck conditions can be subverted by this).

method::fadeTime
When the synthdefs that are used contain an code::\amp:: control, the patterns are replaced by crossfading the previous with the new over this time (in beats)

method::envir
Set the event for the Pdef. It is used to filter the incoming stream before it is passed to the source pattern. This is similar to link::Classes/NodeProxy#-nodeMap::. When set for the first time, the pattern is rebuilt.

method::set
Set arguments in the default event. If there is none, it is created and the pattern is rebuilt.

method::map
Map Pdefn to the keys in the event.

method::clear
Set the source to nil

method::endless
Returns a link::Classes/Prout:: that plays the proxy endlessly, replacing strong::nil:: with a strong::default:: value (silent event). This allows to create streams that idle on until a new pattern is inserted.

subsection::Pdef as stream reference

A single Pdef may serve as a definition for multiple streams. These methods show how to fork off separate streams from one instance. Even if they run in different contexts, their definition may still be changed.

method::fork
Play an independent stream in parallel.

argument::argClock
The clock to run the substream on.

argument::quant
can be an array of [quant, phase, offset], or a link::Classes/Quant:: value.

argument::protoEvent
An link::Classes/Event:: to pass in that is used by the substream

returns:: an link::Classes/EventStreamPlayer::.


method::embed
Pass a value (typically an link::Classes/Event::) into the pattern inval, and embed the Pdef in the stream.

embedInStream
just like any pattern, embeds itself in stream

subsection::Pdef as EventStreamPlayer

For live coding, each Pdef also may control one instance that plays one stream off it. This is an link::Classes/EventStreamPlayer::, accessible in the instance variable link::#-player::.

method::play
Starts the Pdef and creates a player. (See: link::Classes/EventPatternProxy#-play::)

method::stop
Stops the player

method::player
Return the current player (if the Pdef is simply used in other streams this is nil)

method::pause, resume, reset
Perform this method on the player.

method::isPlaying
Returns true if player is running. If a Pdef is playing and its stream ends, it will schedule a stream for playing strong::as soon as a new one is assigned to it::. If it is stopped by strong::stop::, it won't.

Examples::

subsection::Pdef as stream reference

code::
(
SynthDef("Pdefhelp", { arg out, freq, sustain=1, amp=1, pan;
	var env, u=1;
	env = EnvGen.kr(Env.perc(0.03, sustain), 1, doneAction:2);
	3.do { var d; d = exprand(0.01, 1); u = SinOsc.ar(d * 300, u, rrand(0.1,1.2) * d, 1) };
	Out.ar(out, Pan2.ar(SinOsc.ar(u + 1 * freq, 0, amp * env), pan));

}).add;
)
s.boot;

Pdef(\metronom, Pbind(\instrument, \Pdefhelp, \dur, 1, \degree, 16, \legato, 0.1)).play;

x = Pseq([Pdef(\a), Pdef(\b), Pdef(\c)], inf).play;

Pdef(\a, Pbind(\instrument, \Pdefhelp, \dur, 0.25, \degree, Pseq(#[0, 5, 4, 3])));
Pdef(\b, Pbind(\instrument, \Pdefhelp, \dur, 0.125, \degree, Pseq(#[7, 8, 7, 8])));
Pdef(\c, Pbind(\instrument, \Pdefhelp, \dur, 0.25, \degree, Pseq(#[0, 1, 2], 2)));




Pdef(\c, Pbind(\instrument, \Pdefhelp, \dur, 0.25, \degree, Pseq(#[4, 3, 1, 2]*3)));


// infinite loops are scheduled (to ths clock's next beat by default) and released:

Pdef(\a, Pbind(\instrument, \Pdefhelp, \dur, 0.753, \degree, Pseq(#[0, 5, 4, 3, 2], inf)));
Pdef(\a, Pbind(\instrument, \Pdefhelp, \dur, 0.125, \degree, Pseq(#[0, 5, 4, 3] + 1, 1)));
Pdef(\a, Pbind(\instrument, \Pdefhelp, \dur, 0.25, \degree, Pseq(#[0, 5, 4, 3] - 4, 1)));

Pdef(\a, Pbind(\instrument, \Pdefhelp, \dur, 0.125, \degree, Pseq(#[0, 5] - 1, 1)));
Pdef(\a, Pbind(\instrument, \Pdefhelp, \dur, 0.753, \degree, Pshuf(#[0, 5, 4, 3, 2], inf)));

x.stop;
Pdef(\metronom).stop;

// Pdef can be used in multiple patterns:

(
x = Ppar([
	Pbindf(Pn(Pdef(\a), inf),
		\gtranspose, Pstutter(8, Pseq(#[0, 2, 0, 3],inf))
	),
	Pbindf(Pn(Pdef(\a), inf),
		\gtranspose, Pstutter(8, Pseq(#[7, 4, 0, 3],inf)),
		\dur, 0.6
	),
	Pbindf(Pn(Pdef(\a), inf),
		\degree, Pseq(#[0, 5, 4, 3, 2, 3, 2], 1)
	)
]).play;
)

Pdef(\a, Pbind(\instrument, \Pdefhelp, \dur, 0.1, \degree, Pseq(#[0, 1, 0, 1, 2], inf)));

Pdef(\a, Pbind(\instrument, \Pdefhelp, \dur, 0.2, \degree, Pseq([0, 4], inf)));

Pdef(\a, Pbind(\instrument, \Pdefhelp, \dur, 1, \degree, Pseq([0, 4], inf)));

Pdef(\a, Pbind(\instrument, \Pdefhelp, \dur, 0.2, \degree, Pseq([0, 4, Prand([6, 8b],2)], inf)));

Pdef(\a, Pbind(\instrument, \Pdefhelp, \dur, 0.1, \degree, Pseq(#[0, 1b, 1, 2b, 2, 3, 4b, 4, 5], inf)));

// using a fade time, the above changes are crossfaded
Pdef(\a).fadeTime = 2;

Pdef(\a, Pbind(\instrument, \Pdefhelp, \dur, 0.2, \degree, Pseq([0, 4, Prand([6, 8b],2)], inf)));

// ...

Pdef(\a).set(\detune, -50); // set environment
Pdef(\a).set(\detune, 0);

x.stop;
::

subsection::Pdef as EventStreamPlayer

code::
(
// load a synthdef
s.boot;
SynthDef("gpdef",
	{ arg out=0, freq=440, sustain=0.05, amp=0.1, pan;
		var env;
		env = EnvGen.kr(Env.perc(0.01, sustain), doneAction:2) * amp;
		Out.ar(out, Pan2.ar(SinOsc.ar(freq, 0, env), pan))
	}).add;
)


Pdef(\x); // creates a Pdef with a default pattern.


Pdef(\x).play; // play it. A silent resting pattern is used.
Pdef(\y).play; // play a second one (automatically instantiated)


// assign various patterns to it:

Pdef(\x, Pbind(\dur, 0.25, \instrument, \gpdef));
Pdef(\x, Pbind(\dur, 0.25, \degree, Pseq([3, 4, 5b, 6], inf), \instrument, \gpdef));
Pdef(\x, Pbind(\dur, 0.25, \degree, Pseq([3, 4, 5b, 6]+1, inf), \instrument, \gpdef));
Pdef(\y, Pbind(\dur, 0.25, \degree, Pseq([3, 4, 5b, 6]-1, inf), \instrument, \gpdef));
Pdef(\y, Pbind(\dur, 0.25, \degree, Pseq([3, 4, 5b]-2, inf), \instrument, \gpdef));

// using fadeTime:

Pdef(\y).fadeTime = 8.0;
Pdef(\y, Pbind(\dur, 0.125, \degree, Pseq([3, 4, 5b, 6]+4.rand, inf), \instrument, \gpdef));
Pdef(\y, Pbind(\dur, 0.25, \degree, Pseq([3, 4, 5b, 6]-2, inf), \instrument, \gpdef));

(
Pdef(\x, Pbind(
		\dur, 1 / 6,
		\degree, Pseq([3, 4, Prand([8, 2, 3, 9, 10],1) - 5, 6]+1, inf),
		\instrument, \gpdef
		)
	);
)
(
Pdef(\x, Pbind(
		\dur, 0.25,
		\degree, Pseq([3, 4, Prand([8, 2, 3, 9, 10],1), 6], inf),
		\instrument, \gpdef)
	);
)
Pdef(\x).stop;

Pdef(\x).play;

// tempo change
TempoClock.default.tempo = 1.3;
Pdef(\y, Pbind(\dur, 0.25, \degree, Pseq([3, 4, 5, 6]+1, inf), \instrument, \gpdef));

// drop in ending patterns

Pdef(\x, Pbind(\dur, 0.25, \degree, Pseq([3, [7,4], 5, 6]-2), \instrument, \gpdef));
Pdef(\x, Pbind(\dur, 0.125, \degree, Pseq([3, [7,4], 5, 4]-3), \instrument, \gpdef));
Pdef(\x, Pbind(\dur, 0.35, \degree, Pseq([3, [7,4], 5, 4, 3]-3), \instrument, \gpdef));
Pdef(\x, Pbind(\dur, 0.25, \degree, Pshuf([3, [7,4], 5, 6]-2), \instrument, \gpdef));


// clear all.
Pdef(\x).clear;
Pdef(\y).clear;
TempoClock.default.tempo = 1.0;


// GUI example: see also
PdefAllGui(18);
::

subsection::Recursion

Pdefs can be used recursively under the condition that the stream call structure allows it. a structure like the following works:

code::
Pdef(\x, Pseq([Pbind(\instrument, \gpdef), Pdef(\x)], inf));
Pdef(\x).play;
::

but the following would crash, because code::.embedInStream:: is called recursively with no limit:

code::
// Pdef(\y, Pseq([Pdef(\y), Pbind(\instrument, \gpdef)], inf));
::

subsection::Quantizing and outset

When quantizing to a larger number of beats, the changes become very slow if one has to wait for the next beat. Providing an strong::outset:: quant value is a way to make the change so that it appears as if it had been done at the previous grid point already. The stream is fast forwarded to the current position relative to the quant grid. Providing a number larger than zero, the next possible quant point is used as outset.

For example, if quant is 32, and one has just missed the first beat when changing the pattern,
one has to wait for 32 beats until the change happens. Using an outset of 1, it is assumed that you had already
changed the pattern at the first beat, the stream is fast forwarded to the time it would be at now if you had done so. The new pattern is inserted at the next beat (outset=1).

quant can be: strong::[quant, phase, timingOffset, outset]::

note::
This fast forwarding might create a cpu peak if the pattern is very complex/fast or quant is very long. This is hard to avoid, so it simply has to be taken into account.
::

code::
(
Pdef(\x).quant_([8, 0, 0, 1]);
Pdef(\y).quant_([8, 0.5, 0, 1]); // phase: half a beat
Pdef(\x).play;
Pdef(\y).play;
)

Pdef(\x, Pbind(\degree, Pseq((0..7)+2, inf)));
Pdef(\y, Pbind(\degree, Pseq((0..7)-2, inf)));
Pdef(\x, Pbind(\degree, Pseq((0..7)+2, inf), \dur, 0.5));
Pdef(\y, Pbind(\degree, Pseq((0..7).scramble-2, inf), \dur, 0.25, \legato, 0.3));
Pdef(\x, Pbind(\degree, Pseq((0..7), inf)));

Pdef(\x, Pbind(\degree, Pseq([ 1, 5, 6, 7, 0, 3, 2, 4 ], inf), \dur, 1));
Pdef(\x, Pbind(\degree, Pseq([ 0, 2, 2, 4, 0, 4, 0, 4 ], inf), \dur, 1));

Pdef(\x).quant_([8, 1/3, 0, 1]); // phase: 1/6 beat relative to y
Pdef(\x, Pbind(\degree, Pseq([ 1, 1, 1, 7, 0, 2, 2, 4 ], inf), \legato, 0.1));
Pdef(\x, Pbind(\degree, Pseq([ 3, 3, 3, 4b ], inf), \legato, 0.1));
Pdef(\y, Pbind(\degree, Pseq((0..7).scramble-4, inf), \dur, 0.25, \legato, 0.3));




// some testing
(
var quant = #[8, 0, 0, 1]; // quantise to 8 beats, no phase, insert quant to 1 beat
Pdef(\x).quant_(quant);
Pdef(\x).play;
Routine { loop { 8.do { |i| ("uhr:"+i).postln; 1.wait } } }.play(quant:quant);
Pbind(\degree, Pseq((0..7), inf)).play(quant:quant);
)

Pdef(\x, Pbind(\degree, Pseq((0..7)+2, inf)).trace(\degree));
Pdef(\x, Pbind(\degree, Pseq((0..7), inf) + [0, 3]).trace(\degree));
Pdef(\x, Pbind(\degree, Pseq((0..7), inf) + [0, 6], \dur, 0.5).trace(\degree));


Pdef(\x).fadeTime = 8;

Pdef(\x, Pbind(\degree, Pseq((0..7), inf)).trace(\degree));
Pdef(\x, Pbind(\degree, Pseq((0..7).reverse, inf) + [0, 6], \dur, 0.5));

Pdef(\x).fadeTime = nil;
Pdef(\x).quant = 1;

Pdef(\x, Pbind(\degree, Pseq((0..7), inf)).trace(\degree));

Pdef(\x).quant = 8;
Pdef(\x, Pbind(\degree, Pseq((0..7), inf)).trace(\degree));
::

subsection::Update condition

In order to be able to switch to a new pattern under a certain link::#-condition::, the instance variable condition can be set to a function that returns a boolean. Value and a count index are passed to the function. The condition is always valid for the strong::next pattern:: inserted. For stuck conditions, the link::#-reset:: message can be used.

As counting up (such as emphasis::"every nth event, a swap can happen"::) is a common task, there is a method for this, called link::#-count::(n).

code::
Pdef(\x).play;
Pdef(\x).quant = 0; // we don't want quant here.
Pdef(\x, Pbind(\degree, Pseq((0..5), inf), \dur, 0.3)).condition_({ |val, i| i.postln % 6 == 0 });
Pdef(\x, Pbind(\degree, Pseq((0..7) + 5.rand, inf), \dur, 0.3)).condition_({ |val, i| (i % 8).postln == 0 });

// the above is equivalent to:
Pdef(\x, Pbind(\degree, Pseq((0..7) + 5.rand, inf), \dur, 0.3)).count(8);

// the value that is sent in is the event, so decisions can be made dependent on the event's fields
::

subsection::reset

code::
// reset to change immediately:
Pdef(\x).reset;
::