supernova: fix for small audio vector sizes
[supercollider.git] / HelpSource / Tutorials / Streams-Patterns-Events2.schelp
blobc67bc33af2c20e25d4dac73b8790252bbc98c9b6
1 title:: Understanding Streams, Patterns and Events - Part 2
2 summary:: Patterns Introduction
3 related:: Tutorials/Streams-Patterns-Events1, 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 section::Patterns
8 Often one wants to be able to create multiple streams from a single stream specification. Patterns are just a way to make multiple Streams from a single specification, like a cookie cutter. A pattern can be any object that responds to the code::asStream:: message by creating a link::Classes/Stream::. Once again there is a default implementation in class link::Classes/Object:: of asStream that simply returns the receiver as its own stream. Thus any object is by default a pattern that returns itself as a stream when sent the asStream message.
10 code::
12 a = 7.asStream;
13 a.postln;
14 a.next.postln;
18 section::Pattern and its subclasses
20 There is a class named link::Classes/Pattern:: that provides more functionality for the concept of a pattern.
22 A link::Classes/Pfunc:: is a Pattern that returns a link::Classes/FuncStream::. The same function arguments are supplied as are supplied to FuncStream.
24 code::
26 var a, b;
27 a = Pfunc.new({ #[1, 2, 3, 4].choose });
28 b = a.asStream;                 // make a stream from the pattern
29 5.do({ b.next.postln; });       // print 5 values from the stream
33 A link::Classes/Prout:: is a Pattern that returns a link::Classes/Routine::. The same function argument is supplied as is supplied to Routine.
35 code::
37 var a, b, c;
38 a = Prout.new({
39                 3.do({ arg i; 3.rand.yield; })
40         });
41 // make two streams from the pattern
42 b = a.asStream;
43 c = a.asStream;
44 4.do({ b.next.postln; });       // print 4 values from first stream
45 4.do({ c.next.postln; });       // print 4 values from second stream
49 A link::Classes/Pseries:: is a Pattern that generates an arithmetic series.
51 code::
53 var a, b;
54 a = Pseries.new(10, 3, 8);      // stream starts at 10, steps by 3 and has length 8
55 b = a.asStream;
56 9.do({ b.next.postln; });       // print 9 values from stream
60 link::Classes/Pgeom:: is a Pattern that generates a geometric series.
62 code::
64 var a, b;
65 a = Pgeom.new(10, 3, 8);        // stream starts at 10, steps by factor of 3 and has length 8
66 b = a.asStream;
67 9.do({ b.next.postln; });       // print 9 values from stream
71 section::Math operations on Patterns
73 Patterns also respond to math operators by returning patterns that respond to code::asStream:: with appropriately modified streams.
75 Applying a unary operator to a pattern
77 code::
79 var a, b, c;
80 a = Pseries.new(0,1,10);        // a is a pattern whose stream counts from 0 to 9
81 b = a.squared;                  // pattern b is a square of the pattern a
82 c = b.asStream;
83 12.do({ c.next.postln; });
87 Using a binary operator on a pattern
89 code::
91 var a, b, c;
92 a = Pseries.new(0,1,10);        // a is a pattern whose stream counts from 0 to 9
93 b = a + 100;                    // add a constant value to pattern a
94 c = b.asStream;
95 12.do({ c.next.postln; });
99 section::Filtering operations on patterns
101 Patterns also respond to the messages code::collect::, code::select::, and code::reject:: by returning a new link::Classes/Pattern::.
103 The code::collect:: message returns a Pattern whose link::Classes/Stream:: is modified by a function in the same way as the collect message sent to a Collection returns a modified Collection.
105 code::
107 var a, b, c;
108 // a is a pattern whose stream counts from 0 to 9
109 a = Pseries.new(0,1,10);
110 // b is a pattern whose stream adds 100 to even values
111 b = a.collect({ arg item; if (item.even, { item + 100 },{ item }); });
112 c = b.asStream;
113 6.do({ c.next.postln; });
117 The code::select:: message creates a pattern whose stream passes only items that return true from a user supplied function.
119 code::
121 var a, b, c;
122 // a is a pattern whose stream counts from 0 to 9
123 a = Pseries.new(0,1,10);
124 // b is a pattern whose stream only returns the odd values
125 b = a.select({ arg item; item.odd; });
126 c = b.asStream;
127 6.do({ c.next.postln; });
131 The code::reject:: message creates a pattern whose stream passes only items that return false from a user supplied function.
133 code::
135 var a, b, c;
136 // a is a pattern whose stream counts from 0 to 9
137 a = Pseries.new(0,1,10);
138 // b is a pattern whose stream that only returns the non-odd values
139 b = a.reject({ arg item; item.odd; });
140 c = b.asStream;
141 6.do({ c.next.postln; });
145 section::Making Music with Patterns
147 Here is a variation of the example given in part 1 that uses a link::Classes/Pattern:: to create two instances of the random melody stream.
149 code::
151         s = Server.local;
152         SynthDef(\help_SPE2, { arg i_out=0, sustain=1, freq;
153                 var out;
154                 out = RLPF.ar(
155                         LFSaw.ar( freq ),
156                         LFNoise1.kr(1, 36, 110).midicps,
157                         0.1
158                 ) * EnvGen.kr( Env.perc, levelScale: 0.3,
159                         timeScale: sustain, doneAction: 2 );
160                 //out = [out, DelayN.ar(out, 0.04, 0.04) ];
161                 4.do({ out = AllpassN.ar(out, 0.05, [0.05.rand, 0.05.rand], 4) });
162                 Out.ar( i_out, out );
163         }).send(s);
166 // streams as a sequence of pitches
167         var pattern, streams, dur, durDiff;
168         dur = 1/7;
169         durDiff = 3;
170         pattern = Prout.new({
171                 loop({
172                         if (0.5.coin, {
173                                 #[ 24,31,36,43,48,55 ].do({ arg fifth; fifth.yield });
174                         });
175                         rrand(2,5).do({
176                                 // varying arpeggio
177                                 60.yield;
178                                 #[63,65].choose.yield;
179                                 67.yield;
180                                 #[70,72,74].choose.yield;
181                         });
182                         // random high melody
183                         rrand(3,9).do({ #[74,75,77,79,81].choose.yield });
184                 });
185         });
186         streams = [
187                 (pattern - Pfunc.new({ #[12, 7, 7, 0].choose })).midicps.asStream,
188                 pattern.midicps.asStream
189         ];
190         Routine({
191                 loop({
192                         Synth( \help_SPE2, [ \freq, streams.at(0).next, \sustain, dur * durDiff ] );
193                         durDiff.do({
194                                 Synth( \help_SPE2, [ \freq, streams.at(1).next, \sustain, dur ] );
195                                 dur.wait;
196                         });
197                 })
198         }).play
202 To go to the next file:
203 link::Tutorials/Streams-Patterns-Events3::