class library: Quarks Qt GUI - simplify quarks view action
[supercollider.git] / Help / Streams-Patterns-Events / Streams-Patterns-Events1.html
blob7c5100a71f5c3c4e5556069d21528ed41842e9f3
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5 <meta http-equiv="Content-Style-Type" content="text/css">
6 <title></title>
7 <meta name="Generator" content="Cocoa HTML Writer">
8 <meta name="CocoaVersion" content="949.43">
9 <style type="text/css">
10 p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Helvetica; min-height: 19.0px}
11 p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Helvetica}
12 p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}
13 p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
14 p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #ad140d}
15 p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; min-height: 16.0px}
16 p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}
17 p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #bf0000}
18 p.p9 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #000000}
19 p.p10 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #0000bf}
20 p.p11 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #0021e7}
21 span.s1 {color: #001bb9}
22 span.s2 {color: #000000}
23 span.s3 {color: #2c7014}
24 span.s4 {color: #0000bf}
25 span.s5 {color: #007300}
26 span.s6 {text-decoration: underline}
27 span.Apple-tab-span {white-space:pre}
28 </style>
29 </head>
30 <body>
31 <p class="p1"><br></p>
32 <p class="p2"><b>Understanding Streams, Patterns and Events - Part 1</b></p>
33 <p class="p3"><br></p>
34 <p class="p4">The SuperCollider Pattern library<span class="Apple-converted-space">  </span>provides a means of specifying dynamic structural transformations of musical processes. It<span class="Apple-converted-space">  </span>provides similar capabilities as one finds in Nyquist, Elody, Siren, Kyma, HMSL, DMix, and Patchwork.<span class="Apple-converted-space"> </span></p>
35 <p class="p3"><br></p>
36 <p class="p4">By using coroutines and streams rather than eager functional methods it is able to work in a lazy event by event method instead of the all-at-once method of Elody and Siren. It<span class="Apple-converted-space">  </span>provides the kind of dynamic live control found in HMSL but with the more general event models of the others. In Nyquist and Siren certain transformation like Stretch and Transpose are specially coded into the framework. In SuperCollider Patterns, any parameter may have transformations applied to it. The only one treated specially is time, so that parallel streams can be merged.</p>
37 <p class="p3"><br></p>
38 <p class="p4">In order to understand the framework, a number of concepts must be covered. These concepts are embodied in the classes for Streams, Patterns, and Events. You should learn these concepts in the order presented. The framework is built up in layers. If you skip ahead to get to the cool stuff first, you will have missed some important points.</p>
39 <p class="p3"><br></p>
40 <p class="p4"><b>Streams</b></p>
41 <p class="p3"><br></p>
42 <p class="p4">A stream represents a lazy sequence of values. The next value in the sequence is obtained by sending the message next to the stream object. The sequence can be restarted from the beginning by sending the message reset to the stream object. A stream can be of finite or infinite length. When a finite length stream has reached the end, it returns nil.</p>
43 <p class="p3"><br></p>
44 <p class="p4">A stream can be any object that responds to the next and reset messages. Any object that responds to these messages can act as a stream. It happens that the class Object defines next and reset for all objects. In Object, both next and reset are defined to return <span class="s1">'this</span>'. Thus any object is by default a stream that represents an infinite sequence of itself.</p>
45 <p class="p3"><br></p>
46 <p class="p5"><span class="s2">7.next.postln;<span class="Apple-tab-span"> </span></span>// 7 responds to next by returning itself</p>
47 <p class="p3"><br></p>
48 <p class="p4"><b>Stream and its subclasses</b></p>
49 <p class="p3"><br></p>
50 <p class="p4">In addition to the default streams implemented by Object, there is a class Stream that provides more functionality such as math operations on streams and filtering of streams.</p>
51 <p class="p3"><br></p>
52 <p class="p4">A generally useful subclass of Stream is the class FuncStream which allows the user to provide functions to execute in response to next and reset. Here is a FuncStream that represents an infinite random sequence:</p>
53 <p class="p6"><br></p>
54 <p class="p7">(</p>
55 <p class="p7"><span class="s1">var</span> a;</p>
56 <p class="p7">a = <span class="s1">FuncStream</span>.new({ #[1, 2, 3, 4].choose });</p>
57 <p class="p5"><span class="s2">5.do({ a.next.postln; });<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// print 5 values from the stream</p>
58 <p class="p7">)</p>
59 <p class="p3"><br></p>
60 <p class="p4">Another useful subclass of Stream is Routine which is a special kind of function that can act like a Stream. Routines are functions that can return a value from the middle and then be resumed<span class="Apple-converted-space">  </span>from that point when called again. The yield message returns a value from the Routine. The next time the Routine is called it begins by returning from the yield and continues from that point. See the Routine help file.</p>
61 <p class="p3"><br></p>
62 <p class="p4">Here is a Routine that represents a finite sequence of values:</p>
63 <p class="p3"><br></p>
64 <p class="p7">(</p>
65 <p class="p7"><span class="s1">var</span> a;</p>
66 <p class="p7">a = <span class="s1">Routine</span>.new({<span class="Apple-converted-space"> </span></p>
67 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>3.do({ <span class="s1">arg</span> i; i.yield; })<span class="Apple-converted-space"> </span></p>
68 <p class="p7"><span class="Apple-tab-span"> </span>});</p>
69 <p class="p5"><span class="s2">4.do({ a.next.postln; });<span class="Apple-tab-span"> </span></span>// print 4 values from stream</p>
70 <p class="p7">)</p>
71 <p class="p3"><br></p>
72 <p class="p4">and another:</p>
73 <p class="p6"><br></p>
74 <p class="p7">(</p>
75 <p class="p7"><span class="s1">var</span> a;</p>
76 <p class="p7">a = <span class="s1">Routine</span>.new({<span class="Apple-converted-space"> </span></p>
77 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>3.do({ <span class="s1">arg</span> i;<span class="Apple-converted-space"> </span></p>
78 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>(i+1).do({ <span class="s1">arg</span> j; j.yield; })<span class="Apple-converted-space"> </span></p>
79 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>})<span class="Apple-converted-space"> </span></p>
80 <p class="p7"><span class="Apple-tab-span"> </span>});</p>
81 <p class="p5"><span class="s2">8.do({ a.next.postln; });<span class="Apple-tab-span"> </span></span>// print 8 values from stream</p>
82 <p class="p7">)</p>
83 <p class="p3"><br></p>
84 <p class="p3"><br></p>
85 <p class="p4"><b>Math operations on Streams</b></p>
86 <p class="p3"><br></p>
87 <p class="p4">Stream is a subclass of AbstractFunction which means that one can do math operations on streams to produce other streams.</p>
88 <p class="p3"><br></p>
89 <p class="p4">Applying a unary operator to a stream:</p>
90 <p class="p6"><br></p>
91 <p class="p7">(</p>
92 <p class="p7"><span class="s1">var</span> a, b;</p>
93 <p class="p5">// a is a stream that counts from 0 to 9</p>
94 <p class="p7">a = <span class="s1">Routine</span>.new({<span class="Apple-converted-space"> </span></p>
95 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>10.do({ <span class="s1">arg</span> i; i.yield; })<span class="Apple-converted-space"> </span></p>
96 <p class="p7"><span class="Apple-tab-span"> </span>});</p>
97 <p class="p5"><span class="s2">b = a.squared;<span class="Apple-tab-span"> </span></span>// stream b is a square of the stream a</p>
98 <p class="p7">12.do({ b.next.postln; });</p>
99 <p class="p7">)</p>
100 <p class="p3"><br></p>
101 <p class="p4">Using a binary operator on a stream:</p>
102 <p class="p6"><br></p>
103 <p class="p7">(</p>
104 <p class="p7"><span class="s1">var</span> a, b;</p>
105 <p class="p5">// a is a stream that counts from 0 to 9</p>
106 <p class="p7">a = <span class="s1">Routine</span>.new({<span class="Apple-converted-space"> </span></p>
107 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>10.do({ <span class="s1">arg</span> i; i.yield; })<span class="Apple-converted-space"> </span></p>
108 <p class="p7"><span class="Apple-tab-span"> </span>});</p>
109 <p class="p5"><span class="s2">b = a + 100;<span class="Apple-tab-span"> </span></span>// add a constant value to stream a</p>
110 <p class="p7">12.do({ b.next.postln; });</p>
111 <p class="p7">)</p>
112 <p class="p3"><br></p>
113 <p class="p4">Using a binary operator on two streams:</p>
114 <p class="p3"><br></p>
115 <p class="p7">(</p>
116 <p class="p7"><span class="s1">var</span> a, b, c;</p>
117 <p class="p5">// a is a stream that counts from 0 to 9</p>
118 <p class="p7">a = <span class="s1">Routine</span>.new({<span class="Apple-converted-space"> </span></p>
119 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>10.do({ <span class="s1">arg</span> i; i.yield; })<span class="Apple-converted-space"> </span></p>
120 <p class="p7"><span class="Apple-tab-span"> </span>});</p>
121 <p class="p5">// b is a stream that counts from 100 to 280 by 20</p>
122 <p class="p7">b = <span class="s1">Routine</span>.new({<span class="Apple-converted-space"> </span></p>
123 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>forBy (100,280,20, { <span class="s1">arg</span> i; i.yield })<span class="Apple-converted-space"> </span></p>
124 <p class="p7"><span class="Apple-tab-span"> </span>});</p>
125 <p class="p5"><span class="s2">c = a + b;<span class="Apple-tab-span"> </span></span>// add streams a and b</p>
126 <p class="p7">12.do({ c.next.postln; });</p>
127 <p class="p7">)</p>
128 <p class="p3"><br></p>
129 <p class="p4"><b>Filtering operations on streams</b></p>
130 <p class="p3"><br></p>
131 <p class="p4">Streams respond to the messages collect, select, and reject by returning a new Stream.</p>
132 <p class="p3"><br></p>
133 <p class="p4">The collect message returns a stream that is modified by a function in the same way as the collect message sent to a Collection returns a modified Collection.</p>
134 <p class="p3"><br></p>
135 <p class="p7">(</p>
136 <p class="p7"><span class="s1">var</span> a, b;</p>
137 <p class="p5">// a is a stream that counts from 0 to 9</p>
138 <p class="p7">a = <span class="s1">Routine</span>.new({<span class="Apple-converted-space"> </span></p>
139 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>10.do({ <span class="s1">arg</span> i; i.yield; })<span class="Apple-converted-space"> </span></p>
140 <p class="p7"><span class="Apple-tab-span"> </span>});</p>
141 <p class="p5">// b is a stream that adds 100 to even values</p>
142 <p class="p7">b = a.collect({ <span class="s1">arg</span> item; if (item.even, { item + 100 },{ item }); });</p>
143 <p class="p7">6.do({ b.next.postln; });</p>
144 <p class="p7">)</p>
145 <p class="p3"><br></p>
146 <p class="p4">The select message creates a stream that passes only items that return true from a user supplied function.</p>
147 <p class="p3"><br></p>
148 <p class="p7">(</p>
149 <p class="p7"><span class="s1">var</span> a, b;</p>
150 <p class="p5">// a is a stream that counts from 0 to 9</p>
151 <p class="p7">a = <span class="s1">Routine</span>.new({<span class="Apple-converted-space"> </span></p>
152 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>10.do({ <span class="s1">arg</span> i; i.yield; })<span class="Apple-converted-space"> </span></p>
153 <p class="p7"><span class="Apple-tab-span"> </span>});</p>
154 <p class="p5">// b is a stream that only returns the odd values from stream a</p>
155 <p class="p7">b = a.select({ <span class="s1">arg</span> item; item.odd; });</p>
156 <p class="p7">6.do({ b.next.postln; });</p>
157 <p class="p7">)</p>
158 <p class="p3"><br></p>
159 <p class="p4">The reject message creates a stream that passes only items that return false from a user supplied function.</p>
160 <p class="p3"><br></p>
161 <p class="p7">(</p>
162 <p class="p7"><span class="s1">var</span> a, b;</p>
163 <p class="p5">// a is a stream that counts from 0 to 9</p>
164 <p class="p7">a = <span class="s1">Routine</span>.new({<span class="Apple-converted-space"> </span></p>
165 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>10.do({ <span class="s1">arg</span> i; i.yield; })<span class="Apple-converted-space"> </span></p>
166 <p class="p7"><span class="Apple-tab-span"> </span>});</p>
167 <p class="p5">// b is a stream that only returns the non-odd values from stream a</p>
168 <p class="p7">b = a.reject({ <span class="s1">arg</span> item; item.odd; });</p>
169 <p class="p7">6.do({ b.next.postln; });</p>
170 <p class="p7">)</p>
171 <p class="p3"><br></p>
172 <p class="p3"><br></p>
173 <p class="p3"><br></p>
174 <p class="p4"><b>Making Music with Streams</b></p>
175 <p class="p3"><br></p>
176 <p class="p4">Here is a sound example to show how you might use Streams to generate musical material.</p>
177 <p class="p6"><br></p>
178 <p class="p7">(</p>
179 <p class="p7"><span class="Apple-tab-span"> </span>s = <span class="s1">Server</span>.local;</p>
180 <p class="p7"><span class="Apple-tab-span"> </span><span class="s1">SynthDef</span>(<span class="s3">\help_SPE1</span>, { <span class="s1">arg</span> i_out=0, freq;</p>
181 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">var</span> out;</p>
182 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>out = <span class="s1">RLPF</span>.ar(</p>
183 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">LFSaw</span>.ar( freq, mul: <span class="s1">EnvGen</span>.kr( <span class="s1">Env</span>.perc, levelScale: 0.3, doneAction: 2 )),</p>
184 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">LFNoise1</span>.kr(1, 36, 110).midicps,</p>
185 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>0.1</p>
186 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>);</p>
187 <p class="p5"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// out = [out, DelayN.ar(out, 0.04, 0.04) ];</p>
188 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>4.do({ out = <span class="s1">AllpassN</span>.ar(out, 0.05, [0.05.rand, 0.05.rand], 4) });</p>
189 <p class="p7"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">Out</span>.ar( i_out, out );</p>
190 <p class="p7"><span class="Apple-tab-span"> </span>}).send(s);</p>
191 <p class="p7">)</p>
192 <p class="p7">(</p>
193 <p class="p8">// streams as a sequence of pitches</p>
194 <p class="p9"><span class="Apple-tab-span"> </span><span class="s4">var</span> stream, dur;</p>
195 <p class="p9"><span class="Apple-tab-span"> </span>dur = 1/8;</p>
196 <p class="p9"><span class="Apple-tab-span"> </span>stream = <span class="s4">Routine</span>.new({</p>
197 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>loop({</p>
198 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>if (0.5.coin, {</p>
199 <p class="p8"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// run of fifths:<span class="Apple-converted-space"> </span></p>
200 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>24.yield;<span class="Apple-converted-space"> </span></p>
201 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>31.yield;<span class="Apple-converted-space"> </span></p>
202 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>36.yield;<span class="Apple-converted-space"> </span></p>
203 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>43.yield;<span class="Apple-converted-space"> </span></p>
204 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>48.yield;<span class="Apple-converted-space"> </span></p>
205 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>55.yield;<span class="Apple-converted-space"> </span></p>
206 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>});</p>
207 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>rrand(2,5).do({</p>
208 <p class="p8"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// varying arpeggio</p>
209 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>60.yield;</p>
210 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>#[63,65].choose.yield;</p>
211 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>67.yield;</p>
212 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>#[70,72,74].choose.yield;</p>
213 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>});</p>
214 <p class="p8"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// random high melody</p>
215 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>rrand(3,9).do({<span class="Apple-converted-space">  </span>#[74,75,77,79,81].choose.yield });</p>
216 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>});</p>
217 <p class="p9"><span class="Apple-tab-span"> </span>});</p>
218 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span></span>Routine<span class="s2">({</span></p>
219 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>loop({</p>
220 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s4">Synth</span>(<span class="s5">\help_SPE1</span>, [ <span class="s5">\freq</span>, stream.next.midicps ] );</p>
221 <p class="p8"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>dur.wait; </span>// synonym for yield, used by .play to schedule next occurence</p>
222 <p class="p9"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>})</p>
223 <p class="p9"><span class="Apple-tab-span"> </span>}).play</p>
224 <p class="p7">)</p>
225 <p class="p6"><br></p>
226 <p class="p3"><br></p>
227 <p class="p4"><b>Optional:</b></p>
228 <p class="p4">More about Streams can be learned from the book A Little Smalltalk by Timothy Budd. He calls them Generators and shows how they can be used to solve problems like the "eight queens" problem etc.</p>
229 <p class="p3"><br></p>
230 <p class="p3"><br></p>
231 <p class="p4">To go to the next file:</p>
232 <p class="p11"><span class="s6"><a href="Streams-Patterns-Events2.html">Streams-Patterns-Events2</a></span></p>
233 <p class="p3"><br></p>
234 <p class="p3"><br></p>
235 </body>
236 </html>