class library: quit internal server on class library compilation
[supercollider.git] / HelpSource / Tutorials / Streams-Patterns-Events1.schelp
blob83fa35ca975a70c0db87fc5682421d431319b285
1 title:: Understanding Streams, Patterns and Events - Part 1
2 summary:: Streams & Routines
3 related:: Tutorials/Streams-Patterns-Events2, Tutorials/Streams-Patterns-Events3, Tutorials/Streams-Patterns-Events4, Tutorials/Streams-Patterns-Events5, Tutorials/Streams-Patterns-Events6, Tutorials/Streams-Patterns-Events7
4 categories:: Streams-Patterns-Events>Understanding-Streams-Patterns-and-Events
6 The SuperCollider Pattern library provides a means of specifying dynamic structural transformations of musical processes. It provides similar capabilities as one finds in Nyquist, Elody, Siren, Kyma, HMSL, DMix, and Patchwork.
8 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 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.
10 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.
12 section::Streams
14 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.
16 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 link::Classes/Object:: defines next and reset for all objects. In Object, both next and reset are defined to return code::this::. Thus any object is by default a stream that represents an infinite sequence of itself.
18 code::
19 7.next.postln;  // 7 responds to next by returning itself
22 section::Stream and its subclasses
24 In addition to the default streams implemented by link::Classes/Object::, there is a class link::Classes/Stream:: that provides more functionality such as math operations on streams and filtering of streams.
26 A generally useful subclass of Stream is the class link::Classes/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:
28 code::
30 var a;
31 a = FuncStream.new({ #[1, 2, 3, 4].choose });
32 5.do({ a.next.postln; });       // print 5 values from the stream
36 Another useful subclass of Stream is link::Classes/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 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 link::Classes/Routine:: help file.
38 Here is a Routine that represents a finite sequence of values:
40 code::
42 var a;
43 a = Routine.new({
44                 3.do({ arg i; i.yield; })
45         });
46 4.do({ a.next.postln; });       // print 4 values from stream
50 and another:
52 code::
54 var a;
55 a = Routine.new({
56                 3.do({ arg i;
57                         (i+1).do({ arg j; j.yield; })
58                 })
59         });
60 8.do({ a.next.postln; });       // print 8 values from stream
64 section::Math operations on Streams
66 Stream is a subclass of link::Classes/AbstractFunction:: which means that one can do math operations on streams to produce other streams.
68 Applying a unary operator to a stream:
70 code::
72 var a, b;
73 // a is a stream that counts from 0 to 9
74 a = Routine.new({
75                 10.do({ arg i; i.yield; })
76         });
77 b = a.squared;  // stream b is a square of the stream a
78 12.do({ b.next.postln; });
82 Using a binary operator on a stream:
84 code::
86 var a, b;
87 // a is a stream that counts from 0 to 9
88 a = Routine.new({
89                 10.do({ arg i; i.yield; })
90         });
91 b = a + 100;    // add a constant value to stream a
92 12.do({ b.next.postln; });
96 Using a binary operator on two streams:
98 code::
100 var a, b, c;
101 // a is a stream that counts from 0 to 9
102 a = Routine.new({
103                 10.do({ arg i; i.yield; })
104         });
105 // b is a stream that counts from 100 to 280 by 20
106 b = Routine.new({
107                 forBy (100,280,20, { arg i; i.yield })
108         });
109 c = a + b;      // add streams a and b
110 12.do({ c.next.postln; });
114 section::Filtering operations on streams
116 Streams respond to the messages code::collect::, code::select::, and code::reject:: by returning a new link::Classes/Stream::.
118 The code::collect:: message returns a stream that is modified by a function in the same way as the collect message sent to a link::Classes/Collection:: returns a modified Collection.
120 code::
122 var a, b;
123 // a is a stream that counts from 0 to 9
124 a = Routine.new({
125                 10.do({ arg i; i.yield; })
126         });
127 // b is a stream that adds 100 to even values
128 b = a.collect({ arg item; if (item.even, { item + 100 },{ item }); });
129 6.do({ b.next.postln; });
133 The code::select:: message creates a stream that passes only items that return true from a user supplied function.
135 code::
137 var a, b;
138 // a is a stream that counts from 0 to 9
139 a = Routine.new({
140                 10.do({ arg i; i.yield; })
141         });
142 // b is a stream that only returns the odd values from stream a
143 b = a.select({ arg item; item.odd; });
144 6.do({ b.next.postln; });
148 The code::reject:: message creates a stream that passes only items that return false from a user supplied function.
150 code::
152 var a, b;
153 // a is a stream that counts from 0 to 9
154 a = Routine.new({
155                 10.do({ arg i; i.yield; })
156         });
157 // b is a stream that only returns the non-odd values from stream a
158 b = a.reject({ arg item; item.odd; });
159 6.do({ b.next.postln; });
163 section::Making Music with Streams
165 Here is a sound example to show how you might use Streams to generate musical material.
167 code::
169         s = Server.local;
170         SynthDef(\help_SPE1, { arg i_out=0, freq;
171                 var out;
172                 out = RLPF.ar(
173                         LFSaw.ar( freq, mul: EnvGen.kr( Env.perc, levelScale: 0.3, doneAction: 2 )),
174                         LFNoise1.kr(1, 36, 110).midicps,
175                         0.1
176                 );
177                 // out = [out, DelayN.ar(out, 0.04, 0.04) ];
178                 4.do({ out = AllpassN.ar(out, 0.05, [0.05.rand, 0.05.rand], 4) });
179                 Out.ar( i_out, out );
180         }).send(s);
183 // streams as a sequence of pitches
184         var stream, dur;
185         dur = 1/8;
186         stream = Routine.new({
187                 loop({
188                         if (0.5.coin, {
189                                 // run of fifths:
190                                 24.yield;
191                                 31.yield;
192                                 36.yield;
193                                 43.yield;
194                                 48.yield;
195                                 55.yield;
196                         });
197                         rrand(2,5).do({
198                                 // varying arpeggio
199                                 60.yield;
200                                 #[63,65].choose.yield;
201                                 67.yield;
202                                 #[70,72,74].choose.yield;
203                         });
204                         // random high melody
205                         rrand(3,9).do({ #[74,75,77,79,81].choose.yield });
206                 });
207         });
208         Routine({
209                 loop({
210                         Synth(\help_SPE1, [ \freq, stream.next.midicps ] );
211                         dur.wait; // synonym for yield, used by .play to schedule next occurence
212                 })
213         }).play
217 section::Optional:
218 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.
221 To go to the next file:
222 link::Tutorials/Streams-Patterns-Events2::