Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / HelpSource / Tutorials / Streams-Patterns-Events6.schelp
blob16ee7b65fc6a772b02d6e97a6b263ef2d1327b2a
1 title:: Understanding Streams, Patterns and Events - Part 6
2 summary:: Parallel Patterns
3 related:: Tutorials/Streams-Patterns-Events1, Tutorials/Streams-Patterns-Events2, Tutorials/Streams-Patterns-Events3, Tutorials/Streams-Patterns-Events4, Tutorials/Streams-Patterns-Events5, Tutorials/Streams-Patterns-Events7
4 categories:: Streams-Patterns-Events>Understanding-Streams-Patterns-and-Events
6 section::Parallel Patterns
8 subsection::Ppar
10 The link::Classes/Ppar:: pattern allows you to merge multiple event streams to play in parallel.
12 Ppar is a link::Classes/ListPattern:: and so like most ListPatterns it takes two arguments, a strong::list:: of event patterns to play in parallel and a strong::repeats:: count.
14 Ppar's child patterns must be event patterns. Using value patterns in a Ppar is an error because value patterns contain no duration data.
16 A Ppar is done when all of its subpatterns are done.
18 code::
20 Ppar([
21         Pbind(\dur, 0.2, \midinote, Pseq([62, 65, 69, 72], inf)),
22         Pbind(\dur, 0.4, \midinote, Pseq([50, 45], inf))
23 ]).play
28 // Ppars can be nested
29 Ppar([
30         Pbind(
31                 \dur, Prand([0.2, 0.4, 0.6], inf),
32                 \midinote, Prand([72, 74, 76, 77, 79, 81], inf),
33                 \db, -26,
34                 \legato, 1.1
35         ),
36         Pseq([
37                 Pbind(\dur, 3.2, \freq, Pseq([\rest]) ),
38                 Prand([
39                         Ppar([
40                                 Pbind(\dur, 0.2, \pan,  0.5, \midinote, Pseq([60, 64, 67, 64])),
41                                 Pbind(\dur, 0.4, \pan, -0.5, \midinote, Pseq([48, 43]))
42                         ]),
43                         Ppar([
44                                 Pbind(\dur, 0.2, \pan,  0.5, \midinote, Pseq([62, 65, 69, 65])),
45                                 Pbind(\dur, 0.4, \pan, -0.5, \midinote, Pseq([50, 45]))
46                         ]),
47                         Ppar([
48                                 Pbind(\dur, 0.2, \pan,  0.5, \midinote, Pseq([64, 67, 71, 67])),
49                                 Pbind(\dur, 0.4, \pan, -0.5, \midinote, Pseq([52, 47]))
50                         ])
51                 ], 12)
52         ], inf)
53 ], inf).play;
57 subsection::Ptpar
59 The link::Classes/Ppar:: pattern starts all of its subpatterns at the same time.
61 A link::Classes/Ptpar:: pattern includes a start time parameter before each subpattern which allow the subpatterns to be started at some time delay within the pattern. The start time is given in beats.
63 code::
65 var makePattern, durpat;
67 durpat = Pseq([ Pgeom(0.05, 1.1, 24), Pgeom(0.5, 0.909, 24) ], 2);
69 makePattern = { arg note, db, pan;
70         Pbind( \dur, durpat, \db, db, \pan, pan, \midinote, Pseq([note, note-4], inf) );
73 Ptpar([
74         0.0, makePattern.value(53, -20, -0.9),
75         2.0, makePattern.value(60, -23, -0.3),
76         4.0, makePattern.value(67, -26,  0.3),
77         6.0, makePattern.value(74, -29,  0.9)
78 ], inf).play;
82 The time arguments are sent the code::value:: message when the Ptpar pattern is started, so you may use functions to specify the times.
84 code::
86 var makePattern, durpat;
88 durpat = Pseq([ Pgeom(0.05, 1.1, 24), Pgeom(0.5, 0.909, 24) ], 2);
90 makePattern = { arg note, db, pan;
91         Pbind( \dur, durpat, \db, db, \pan, pan, \midinote, Pseq([note, note-4], inf) );
94 Ptpar([
95         { 0.0 }, makePattern.value(53, -20, -0.9),
96         { 8.0.rand }, makePattern.value(60, -23, -0.3),
97         { 8.0.rand }, makePattern.value(67, -26,  0.3),
98         { 8.0.rand }, makePattern.value(74, -29,  0.9)
99 ], inf).play;
103 section::FilterPatterns and transformation
105 FilterPatterns take an existing pattern and apply some modification to its properties.
107 subsection::Padd, Pmul, Pset, Pstretch
109 There is a simpler way to write the modal transposition example given in part 5. In fact the earlier examples are setting the values of code::mtranspose:: and code::ctranspose:: which is not the best way to change those variables, because it wipes out any modifications to them by parent patterns. It is better to take the current value of those properties and add a value to them.
111 The link::Classes/Padd:: filter takes the current value of a property and adds a value to it.
113 code::
115 // modal transposition
116 var pattern;
118 // define the basic pattern
119 pattern = Pbind(
120         \dur, 0.15,
121         \degree, Pseq([ Pshuf(#[-7,-3,0,2,4,7], 4), Pseq([0,1,2,3,4,5,6,7]) ], 1)
124 Pseq([
125         pattern,                // untransposed
126         Padd(\mtranspose, 1, pattern),  // modal transpose up 1 degree
127         Padd(\mtranspose, 2, pattern)   // modal transpose up 2 degrees
128 ], inf).play
132 Similarly, link::Classes/Pmul:: multiplies the current value of a property by a value. link::Classes/Pset:: sets the property to a value.
134 In order to process duration correctly link::Classes/Pstretch:: should be used.
136 code::
138 // beat stretching using Pstretch
139 var pattern;
141 // define the basic pattern
142 pattern = Pbind(
143         \dur, 0.15,
144         \degree, Pseq([ Pshuf(#[-7,-3,0,2,4,7], 4), Pseq([0,1,2,3,4,5,6,7]) ], 1)
147 Pseq([
148         pattern,                // normal
149         Pstretch(0.5, pattern), // stretch durations by a factor of 1/2
150         Pstretch(2.0, pattern)  // stretch durations by a factor of 2
151 ], inf).play
155 subsection::Paddp, Pmulp, Psetp, Pstretchp
157 In fact there is an even shorter version of the modal transposition example. link::Classes/Paddp:: reads one pattern to get values for adding to a property and plays the second pattern once through modified with each new value.
159 code::
161 // modal transposition
162 var pattern;
164 // define the basic pattern
165 pattern = Pbind(
166         \dur, 0.15,
167         \degree, Pseq([ Pshuf(#[-7,-3,0,2,4,7], 4), Pseq([0,1,2,3,4,5,6,7]) ], 1)
170 Paddp(
171         \mtranspose,            // property to be modified
172         Pseq([0,1,2], inf),     // a value pattern as a source of values for adding to mtranspose
173         pattern                 // the pattern to be modified
174 ).play
178 Nested modifications:
180 code::
182 // modal transposition
183 var pat1, pat2;
185 // define the basic pattern
186 pat1 = Pbind(
187         \dur, 0.15,
188         \degree, Pseq([ Pshuf(#[-7,-3,0,2,4,7], 4), Pseq([0,1,2,3,4,5,6,7]) ], 1)
191 pat2 = Paddp(
192         \mtranspose,    // property to be modified
193         Pseq([0,1,2]),  // a value pattern as a source of values for adding to mtranspose
194         Ppar([
195                 pat1,
196                 Padd(\mtranspose, -3, pat1),    // down a 4th
197                 Padd(\mtranspose, 2, pat1)      // up a 3rd
198         ])
201 Pseq([
202         pat1,   // unmodified pattern
203         pat2,   // parallel sequence
204         Pstretch(1.5, pat2)     // parallel sequence stretched by 3/2
205 ], inf).play
209 Another example using Paddp:
211 code::
213 var chord;
214 chord = Prand([[53, 58, 64],[53, 60, 64],[57,60,65]]);
215 Paddp(\ctranspose, Prand([-1,0,2,4,5], inf),
216         Ppar([
217                 Pbind(  // melody part
218                         \dur, Prand([0.2, 0.4, 0.6], inf),
219                         \midinote, Pxrand([71, 72, 74, 76, 77, 79], 10),
220                         \db, -26,
221                         \legato, 1.1
222                 ),
223                 Pbind(  // harmony part
224                         \pan, 0.4,
225                         \dur, Pseq([0.1, 0.5, 0.4, 0.6], 4),
226                         \midinote, Pseq([chord,\rest,chord,\rest], 4)
227                 ),
228                 Pbind(  // bass part
229                         \pan, -0.4,
230                         \dur, 0.4,
231                         \midinote, Pseq([38, 45, 38, 36], 4)
232                 )
233         ])
234 ).play
239 // chromatic transposition
240 var pattern;
242 // define the basic pattern
243 pattern = Pbind(
244         \dur, 0.1,
245         \degree, Pseq([0,1,2,3,4,5,6,7])
248 Paddp(
249         \ctranspose,            // property to be modified
250         Pseries(0,1,12),        // a value pattern as a source of values for multiplying with ctranspose
251         pattern                 // the pattern to be modified
252 ).play
257 // beat time stretching
258 var pattern;
260 // define the basic pattern
261 pattern = Pbind(
262         \dur, 0.1,
263         \degree, Pseq([0,1,2,3,4,5,6,7])
266 Pstretchp(
267         Pseq([1,2,3], inf),     // a value pattern as a source of values for multiplying with stretch
268         pattern                 // the pattern to be modified
269 ).play
273 subsection::Pbindf
275 link::Classes/Pbindf:: is like link::Classes/Pbind:: except that it merges all the bound symbols into events that it gets from a subpattern. It takes the same initial arguments in pairs as Pbind does, with an additional pattern to be modified as the last argument.
277 code::
279 var pattern;
280 pattern = Pbind( \midinote, Pseq(#[60, 62, 64, 65, 67, 69, 71, 72]) );
282 Pseq([
283         Pbindf(pattern, \legato, 0.1, \dur, 0.2),
284         Pbindf(pattern, \legato, 1.0, \dur, 0.125),
285         Pbindf(pattern, \legato, 2.0, \dur, 0.3)
286 ], inf).play
290 Patterns can be used as the arguments to Pbindf.
292 code::
294 var pattern;
295 pattern = Pbind( \midinote, Pseq(#[60, 62, 64, 65, 67, 69, 71, 72, 74, 76, 77, 79]) );
297 Pseq([
298         Pbindf(pattern,\legato, 0.1, \dur, Pgeom(0.3, 0.85, inf)),
299         Pbindf(pattern,\legato, 1.0, \dur, Pseq([0.3, 0.15], inf)),
300         Pbindf(pattern,\legato, 2.0, \dur, Pseq([0.2, 0.2, 0.4], inf))
301 ], inf).play
305 To go to the next file:
306 link::Tutorials/Streams-Patterns-Events7::