Patterns provide a facility for easily exploring generative music/algorithmic composition. Rather than making single synthesis events, we're looking much more at how we schedule lots of events over time.

We'll work backwards! We'll start with what seems magical then explain some of how it works.

To fully understand how Patterns do what they do requires some effort; some of the detail is hidden 'below the surface' in SuperCollider's own libraries, but the good news is that you can use theirpower without needing to go very far into the implementation.

In the following, all the names beginning with capital P are examples of Patterns.

// run this line

a = Pbind.new.play(quant:1.0);

a.stop;// Or stop it with cmd+period;

// now run this line

Pbind(\freq, 440).play(quant:1.0);

// run this, go back and run some of the others at the same time

(

Pbind(

\dur,0.125,

\midinote, Pseq([0, 4, 0, 7, 4, 0, 0] + 60,inf),

\amp, Prand([0.125, 0.2, 0.25],inf)

).play(quant:1.0)

)

The quant parameter allows the delay of scheduling to the next beat, so that patterns started up at different times lock in to each other.

(

Pbind(

\freq, 770// try changing me to another number!

).play;

)

The Pbind class allows you to match properties of a sound event (like \freq) to your provided parameter values. Now compare this:

(

Pbind(

\freq, Pseq([100,200,300],inf) // try a different list

).play;

)

The Pseq is an example of a Pattern, which can be thought of as generating a sequence of values

100, 200, 300, 100, 200, 300, ...

returning the next one in the sequence each time it is evaluated

There are many useful types of Pattern class to try. Here are some specific examples:

// loops through the sequence of the array, perpetually:

Pseq([0,1,2,3],inf)

// next value is a random member of the array, after 5 times stop:

Prand([0,1,2,3],5)

// next value is a random member of the array

// except you can't repeat the previous value:

Pxrand([0,1,2,3],inf)

// next value is a weighted choice from the first array

// using the weights given in the second argument.

// After returning one value, stop:

Pwrand([0,1,2,3], [0.5,0.3,0.1,0.1], 1)

// next value is the result of evaluating the

// given function, in this case 4.rand:

Pfunc({ 4.rand })

To explore more Pattern types, a good starting point is the following help file:

[Streams]// select the text within the box then cmd+d

Patterns are generators for Streams. An example of a Stream is the Routine (see Scheduling)

To demonstrate how a Pattern turns into a Stream, ".asStream" is used:

//run this one line at a time, observing the Post window

a = Pseq([1, 3, 400],1);//make Pattern, a Pseq

x = a.asStream;//turn this Pattern into a specific Stream

x.next;//ask for the next value in the Stream

x.next;//and so on ...

x.next;

x.next;

y=a.asStream

y.next

// this means that from one pattern one can generate many independent streams:

Pbindf is a filter Pbind - this means it operates on the Pattern b, adjusting the current properties

of the environment - in this case \octave and \stretch

Note how this allows a slow version of b in the bass and a faster version higher up coming in after 4 seconds

Note that you can use normal Patterns without Pbind and they are often extremely useful for quickly generating sequences of values for algorithmic composition. This example is parallel to the Scheduling tutorial.

Synth(\pulsepan,[\freq,p.next]); // get next frequency value from pattern

0.1.wait;

});

}.play;

)

A little more detail about SynthDescLib:

Note that since SC 3.4, we .add SynthDefs, and this makes sure they're ready for Patterns library use.

The SynthDescLib facility supports using your own SynthDefs with patterns and bind to the SynthDef arguments.

The command

SynthDescLib.global.read

will prepare a library of SynthDesc objects - SynthDef descriptions - from all the synthdefs in your synthdefs folder.

This then allows those SynthDefs to be used in Pbind as an \instrument target, and for the properties of the Event to be passed through to the spawned Synths that use that definition.

To make a new SynthDef and make sure it is ready for use with Pbind you can just use .add.

Note though that if you want to put this on disk as well, you need to use .store rather than .load. This will save a SynthDef file on disk, read it into the SynthDescLib and send it to the active Server.

(

SynthDef(\nickinstr, { arg out=0, freq=440, amp=0.1, pan=0, gate=1;

var z;

z = LPF.ar(

Mix.ar(LFSaw.ar(freq*[0.99,1,1.01],0.0,amp)),

XLine.kr(5000, 1000, 1.5))

* EnvGen.kr(Env.new([0,1,0],[0.01,0.01],\lin,1), gate, doneAction:2);

Out.ar(out, Pan2.ar(z, pan));

}).store;

)

You can supply the \out and \gate arguments for controlling the target audio bus and the release of the Synth after a given duration. Whether you use gate or not, you should use a doneAction to release the enclosing Synth at some point to prevent build up of Synths and eventual overload of the Server.