1title:: Pattern Guide 02: Basic Vocabulary
2summary:: Common patterns to generate streams of single values
3related:: Tutorials/A-Practical-Guide/PG_01_Introduction, Tutorials/A-Practical-Guide/PG_03_What_Is_Pbind
4categories:: Streams-Patterns-Events>A-Practical-Guide
5
6section::Basic Vocabulary: Generating values
7
8Before getting to the really cool things patterns can do, we need to build up a basic vocabulary. We'll start with some words, then move into phrases in the next tutorial.
9
10Some of the patterns will be demonstrated with a Pbind construct. This is a taste of things to come -- sequencing sonic events using patterns. Don't worry about how Pbind works just yet... all in good time.
11
12Let's start with a very quick reference of some basic patterns. More complete descriptions follow this list. The list might seem long at first, but concentrate your attention on patterns marked with a star. Those are the most basic, and commonly used. Again, the purpose is to start learning the vocabulary of patterns -- like learning new words when studying a human language.
13
14This document describes a lot of patterns, but what I call "primary patterns" are the most important. If you are new to patterns, concentrate on these first. You can always come back and look at the rest later.
15
16For more information on any of these patterns, select the class name and use the help key for your editor to open its help file.
17
18section::Quick reference
19
20subsection::Primary Patterns
21
22definitionList::
23## code::Pseq(list, repeats, offset):: || Play through the entire list code::repeats:: times. Like code::list.do::.
24## code::Prand(list, repeats):: || Choose items from the list randomly (same as code::list.choose::).
25## code::Pxrand(list, repeats):: || Choose randomly, but never repeat the same item twice in immediate succession.
26## code::Pshuf(list, repeats):: || Shuffle the list in random order, and use the same random order code::repeats:: times. Like code::list.scramble::.
27## code::Pwrand(list, weights, repeats):: || Choose randomly, according to weighted probabilities (same as code::list.wchoose(weights)::).
28
29## code::Pseries(start, step, length):: || Arithmetic series (addition).
30## code::Pgeom(start, grow, length):: || Geometric series (multiplication).
31
32## code::Pwhite(lo, hi, length):: || Random numbers, equal distribution ("white noise"). Like code::rrand(lo, hi):: .
33## code::Pexprand(lo, hi, length):: || Random numbers, exponential distribution. Like code::exprand(lo, hi):: .
34## code::Pbrown(lo, hi, step, length):: || Brownian motion, arithmetic scale (addition).
35
36## code::Pfunc(nextFunc, resetFunc):: || Get the stream values from a user-supplied function.
37## code::Pfuncn(func, repeats):: || Get values from the function, but stop after code::repeats:: items.
38## code::Prout(routineFunc):: || Use the function like a routine. The function should return values using code::.yield:: or code::.embedInStream::.
39::
40
41subsection::Additional List Patterns
42
43definitionList::
44## code::Pser(list, repeats, offset):: || Play through the list as many times as needed, but output only code::repeats:: items.
45## code::Pslide(list, repeats, len, step, start, wrapAtEnd):: || Play overlapping segments from the list.
46
47## code::Pwalk(list, stepPattern, directionPattern, startPos):: || Random walk over the list.
48
49## code::Place(list, repeats, offset):: || Interlace any arrays found in the main list.
50## code::Ppatlace(list, repeats, offset):: || Interlace any patterns found in the main list.
51## code::Ptuple(list, repeats):: || Collect the list items into an array as the return value.
52::
53
54subsection::Additional Random Number Generators
55
56definitionList::
57## code::Pgbrown(lo, hi, step, length):: || Brownian motion, geometric scale (multiplication).
58
59## code::Pbeta(lo, hi, prob1, prob2, length):: || Beta distribution, where code::prob1 = α :: (alpha) and code::prob2 = β :: (beta).
60## code::Pcauchy(mean, spread, length):: || Cauchy distribution.
61## code::Pgauss(mean, dev, length):: || Guassian (normal) distribution.
62## code::Phprand(lo, hi, length):: || Returns the greater of two equal-distribution random numbers.
63## code::Plprand(lo, hi, length):: || Returns the lesser of two equal-distribution random numbers.
64## code::Pmeanrand(lo, hi, length):: || Returns the average of two equal-distribution random numbers, i.e., code::(x + y) / 2 ::.
65## code::Ppoisson(mean, length):: || Poisson distribution.
66
67## code::Pprob(distribution, lo, hi, length, tableSize):: || Arbitrary distribution, based on a probability table.
68::
69
70section::Functional descriptions of patterns
71
72subsection::List Patterns
73
74The most obvious thing one would want to do with a pattern is to give it a list of values and have it read them out in order. You have a couple of choices, which differ in their handling of the code::repeats:: parameter.
75
76definitionList::
77## code::Pseq(list, repeats, offset):: || Play through the entire list code::repeats:: times.
78## code::Pser(list, repeats, offset):: || Play through the list as many times as needed, but output only code::repeats:: items.
79
80code::
81Pseq(#[1, 2, 3], 4).asStream.all;	// 12 items = 4 repeats * 3 items
82Pser(#[1, 2, 3], 4).asStream.all;	// 4 items only
83::
84
85link::Classes/Pseq:: is an obvious choice for streaming out known pitch and rhythm values.
86
87Before playing a Pbind pattern such as this, make sure the server is booted.
88
89code::
90s.boot;
91
92(
93p = Pbind(
94	\degree, Pseq(#[0, 0, 4, 4, 5, 5, 4], 1),
95	\dur, Pseq(#[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1], 1)
96).play;
97)
98::
99
100To stop the examples in this file, use the "stop" keyboard shortcut (cmd-. on macOS, alt-. on Windows, check documentation for other editors). Or:
101
102code::
103p.stop;
104::
105
106A variation, link::Classes/Pslide::, plays overlapping segments of the input list.
107
108## code::Pslide(list, repeats, len, step, start, wrapAtEnd):: || Play overlapping segments from the list.
109definitionList::
110## code::repeats:: || number of segments
111## code::len:: || length of each segment
112## code::step:: || is how far to step the start of each segment from previous.
113## code::start:: || what index to start at.
114## code::wrapAtEnd:: || if true (default), indexing wraps around if goes past beginning or end. If false, the pattern stops if it hits a nil element or goes outside the list bounds.
115::
116
117If code::step == 1 ::, then the first segment is at code::start::, the second at code::start + 1 ::, and so on.
118
119code::
120Pslide(#[1, 2, 3, 4, 5, 6, 7, 8], 10, 3, 1, 0, false).asStream.all;
121
122// or, to show the segments as separate arrays
123Pslide(#[1, 2, 3, 4, 5, 6, 7, 8], 10, 3, 1, 0, false).clump(3).asStream.all;
124
125// Flock of Seagulls!
126(
127p = Pbind(
128	\degree, Pslide((-6, -4 .. 12), 8, 3, 1, 0),
129	\dur, Pseq(#[0.1, 0.1, 0.2], inf),
130	\sustain, 0.15
131).play;
132)
133::
134::
135
136subsection::Random-order list patterns
137
138definitionList::
139## code::Prand(list, repeats):: || Choose items from the list randomly (same as code::list.choose::).
140
141code::
142// Prand: given scale degrees (pentatonic) with equal probability of each
143(
144p = Pbind(
145	\degree, Prand([0, 1, 2, 4, 5], inf),
146	\dur, 0.25
147).play;
148)
149::
150
151## code::Pxrand(list, repeats):: || Choose randomly, but never repeat the same item twice in immediate succession.
152
153code::
154// Pxrand: same as above but never repeats a pitch twice in a row
155(
156p = Pbind(
157	\degree, Pxrand([0, 1, 2, 4, 5], inf),
158	\dur, 0.25
159).play;
160)
161::
162
163## code::Pshuf(list, repeats):: || Shuffle the list in random order, and use the same random order code::repeats:: times. Like code::list.scramble::.
164
165code::
166// Pshuf: randomly ordered once and repeated
167(
168p = Pbind(
169	\degree, Pshuf([0, 1, 2, 4, 5], inf),
170	\dur, 0.25
171).play;
172)
173::
174
175## code::Pwrand(list, weights, repeats):: || Choose randomly, according to weighted probabilities (same as code::list.wchoose(weights)::).
176
177code::
178// Pwrand: these probabilities favor triadic notes from scale degrees
179(
180p = Pbind(
181	\degree, Pwrand((0..7), [4, 1, 3, 1, 3, 2, 1].normalizeSum, inf),
182	\dur, 0.25
183).play;
184)
185::
186
187## code::Pwalk(list, stepPattern, directionPattern, startPos):: || Random walk over the list. This pattern is a bit more complicated; see its link::Classes/Pwalk##help:: file for details.
188::
189
190subsection::Interlacing values and making arrays
191
192These are opposing operations: interlacing means splitting arrays and merging them into a stream of single values, and arrays can be made out of single-value streams as well.
193
194definitionList::
195## code::Place(list, repeats, offset):: || Take one from each item in the main array item in succession. Hard to explain, easier to see:
196
197code::
198Place([0, [1, 2], [3, 4, 5]], 3).asStream.all;
199--> [ 0, 1, 3, 0, 2, 4, 0, 1, 5 ]
200::
201
202If we turn this into a matrix and read vertically, the original arrays are clearly visible:
203
204code::
205Place([0, [1, 2], [3, 4, 5]], 3).clump(3).do(_.postln);
206
207[ 0, 1, 3 ]	// leftmost column: 0 from first Place item
208[ 0, 2, 4 ]	// second column: alternates between 1 and 2, from second Place item
209[ 0, 1, 5 ]	// third column: 3, 4, 5 from third Place item
210::
211
212## code::Ppatlace(list, repeats, offset):: || Take one value from each sub-pattern in order.
213
214code::
215// Hanon exercise
216(
217p = Pbind(
218	\degree, Ppatlace([
219		Pseries(0, 1, 8),	// first, third etc. notes
220		Pseries(2, 1, 7)	// second, fourth etc. notes
221	], inf),
222	\dur, 0.25
223).play;
224)
225::
226
227That's also a taste of things to come: Patterns can be nested.
228
229## code::Ptuple(list, repeats):: || Get one value from each item in the array, and return all of them as an array of values.
230
231code::
232// Chords
233// \degree receives [7, 9, 4], then [6, 7, 4] successively, expanded to chords on the server
234(
235p = Pbind(
236	\degree, Ptuple([
237		Pseries(7, -1, 8),
238		Pseq([9, 7, 7, 7, 4, 4, 2, 2], 1),
239		Pseq([4, 4, 4, 2, 2, 0, 0, -3], 1)
240	], 1),
241	\dur, 1
242).play;
243)
244::
245::
246
247subsection::Arithmetic and geometric series
248
249Now, let's move to patterns that produce values mathematically, without using a predefined list.
250
251definitionList::
252## code::Pseries(start, step, length):: || Arithmetic series, successively adding code::step:: to the starting value, returning a total of code::length:: items.
253## code::Pgeom(start, grow, length):: || Geometric series, successively multiplying the current value by code::grow::.
254
255code::
256// Use Pseries for a scale and Pgeom for an accelerando
257(
258p = Pbind(
259	\degree, Pseries(-7, 1, 15),
260	\dur, Pgeom(0.5, 0.89140193218427, 15)
261).play;
262)
263::
264
265strong::Third-party extension alert:: : If you want an arithmetic or geometric series to start at one number and end at another specific number, the step size/multiplier must be calculated from the endpoints and the number of items desired. The strong::ddwPatterns:: quark includes a convenience method, code::fromEndpoints::, for both Pseries and Pgeom that performs this calculation. It's necessary to give an exact number of repeats, at least two and less than infinity.
266
267code::
268p = Pgeom.fromEndpoints(0.5, 0.1, 15);	// error if ddwPatterns not installed
269p.postcs;
270::
271
272Prints:
273
274code::
275Pgeom(0.5, 0.89140193218427, 15)
276::
277::
278
279subsection::Random numbers and probability distributions
280
281definitionList::
282## code::Pwhite(lo, hi, length):: || Produces code::length:: random numbers with equal distribution ('white' refers to white noise).
283## code::Pexprand(lo, hi, length):: || Same, but the random numbers have an exponential distribution, favoring lower numbers. This is good for frequencies, and also durations (because you need more notes with a shorter duration to balance the weight of longer notes).
284## code::Pbrown(lo, hi, step, length):: || Brownian motion. Each value adds a random code::step:: to the previous value, where the code::step:: has an equal distribution between code::-step:: and code::+step::.
285## code::Pgbrown(lo, hi, step, length):: || Brownian motion on a geometric scale. Each value multiplies a random code::step:: factor to the previous value.
286
287## code::Pbeta(lo, hi, prob1, prob2, length):: || Beta distribution, where code::prob1 = α :: (alpha) and code::prob2 = β :: (beta).
288## code::Pcauchy(mean, spread, length):: || Cauchy distribution.
289## code::Pgauss(mean, dev, length):: || Gaussian (normal) distribution.
290## code::Phprand(lo, hi, length):: || Returns the greater of two equal-distribution random numbers.
291## code::Plprand(lo, hi, length):: || Returns the lesser of two equal-distribution random numbers.
292## code::Pmeanrand(lo, hi, length):: || Returns the average of two equal-distribution random numbers, i.e., code::(x + y) / 2 ::.
293## code::Ppoisson(mean, length):: || Poisson distribution.
294
295## code::Pprob(distribution, lo, hi, length, tableSize):: || Given an array of relative probabilities across the desired range (a histogram) representing an arbitrary distribution, generates random numbers corresponding to that distribution.
296::
297
298To see a distribution, make a histogram out of it.
299
300code::
301Pmeanrand(0.0, 1.0, inf).asStream.nextN(10000).histo(200, 0.0, 1.0).plot;
302::
303
304subsection::Catchall Patterns
305
306Not everything is pre-written as a pattern class. These patterns let you embed custom logic.
307
308definitionList::
309## code::Pfunc(nextFunc, resetFunc):: || The next value is the return value from evaluating code::nextFunc::. If code::.reset:: is called on a stream made from this pattern, code::resetFunc:: is evaluated. The stream will run indefinitely until code::nextFunc:: returns code::nil::.
310
311## code::Pfuncn(func, repeats):: || Like Pfunc, output values come from evaluating the function. Pfuncn, however, returns exactly code::repeats:: values and then stops. The default number of repeats is 1.
312
313## code::Prout(routineFunc):: || Use the code::routineFunc:: in a routine. The stream's output values are whatever this function code::.yield::s. Prout ends when it yields code::nil::.
314::
315
316Next, we'll look at the central pattern for audio sequencing: link::Classes/Pbind::.
317
318Previous:	link::Tutorials/A-Practical-Guide/PG_01_Introduction::
319
320Next:		link::Tutorials/A-Practical-Guide/PG_03_What_Is_Pbind::
321