File: Streams-Patterns-Events2.schelp

package info (click to toggle)
supercollider 1%3A3.13.0%2Brepack-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 80,292 kB
  • sloc: cpp: 476,363; lisp: 84,680; ansic: 77,685; sh: 25,509; python: 7,909; makefile: 3,440; perl: 1,964; javascript: 974; xml: 826; java: 677; yacc: 314; lex: 175; objc: 152; ruby: 136
file content (203 lines) | stat: -rw-r--r-- 5,888 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
title:: Understanding Streams, Patterns and Events - Part 2
summary:: Patterns Introduction
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
categories:: Tutorials>Streams-Patterns-Events

section::Patterns

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.

code::
(
a = 7.asStream;
a.postln;
a.next.postln;
)
::

section::Pattern and its subclasses

There is a class named link::Classes/Pattern:: that provides more functionality for the concept of a pattern.

A link::Classes/Pfunc:: is a Pattern that returns a link::Classes/FuncStream::. The same function arguments are supplied as are supplied to FuncStream.

code::
(
var a, b;
a = Pfunc.new({ #[1, 2, 3, 4].choose });
b = a.asStream;			// make a stream from the pattern
5.do({ b.next.postln; });	// print 5 values from the stream
)
::

A link::Classes/Prout:: is a Pattern that returns a link::Classes/Routine::. The same function argument is supplied as is supplied to Routine.

code::
(
var a, b, c;
a = Prout.new({
		3.do({ arg i; 3.rand.yield; })
	});
// make two streams from the pattern
b = a.asStream;
c = a.asStream;
4.do({ b.next.postln; });	// print 4 values from first stream
4.do({ c.next.postln; });	// print 4 values from second stream
)
::

A link::Classes/Pseries:: is a Pattern that generates an arithmetic series.

code::
(
var a, b;
a = Pseries.new(10, 3, 8);	// stream starts at 10, steps by 3 and has length 8
b = a.asStream;
9.do({ b.next.postln; });	// print 9 values from stream
)
::

link::Classes/Pgeom:: is a Pattern that generates a geometric series.

code::
(
var a, b;
a = Pgeom.new(10, 3, 8);	// stream starts at 10, steps by factor of 3 and has length 8
b = a.asStream;
9.do({ b.next.postln; });	// print 9 values from stream
)
::

section::Math operations on Patterns

Patterns also respond to math operators by returning patterns that respond to code::asStream:: with appropriately modified streams.

Applying a unary operator to a pattern

code::
(
var a, b, c;
a = Pseries.new(0,1,10);	// a is a pattern whose stream counts from 0 to 9
b = a.squared;			// pattern b is a square of the pattern a
c = b.asStream;
12.do({ c.next.postln; });
)
::

Using a binary operator on a pattern

code::
(
var a, b, c;
a = Pseries.new(0,1,10);	// a is a pattern whose stream counts from 0 to 9
b = a + 100;			// add a constant value to pattern a
c = b.asStream;
12.do({ c.next.postln; });
)
::

section::Filtering operations on patterns

Patterns also respond to the messages code::collect::, code::select::, and code::reject:: by returning a new link::Classes/Pattern::.

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.

code::
(
var a, b, c;
// a is a pattern whose stream counts from 0 to 9
a = Pseries.new(0,1,10);
// b is a pattern whose stream adds 100 to even values
b = a.collect({ arg item; if (item.even, { item + 100 },{ item }); });
c = b.asStream;
6.do({ c.next.postln; });
)
::

The code::select:: message creates a pattern whose stream passes only items that return true from a user supplied function.

code::
(
var a, b, c;
// a is a pattern whose stream counts from 0 to 9
a = Pseries.new(0,1,10);
// b is a pattern whose stream only returns the odd values
b = a.select({ arg item; item.odd; });
c = b.asStream;
6.do({ c.next.postln; });
)
::

The code::reject:: message creates a pattern whose stream passes only items that return false from a user supplied function.

code::
(
var a, b, c;
// a is a pattern whose stream counts from 0 to 9
a = Pseries.new(0,1,10);
// b is a pattern whose stream that only returns the non-odd values
b = a.reject({ arg item; item.odd; });
c = b.asStream;
6.do({ c.next.postln; });
)
::

section::Making Music with Patterns

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.

code::
(
	s = Server.local;
	SynthDef(\help_SPE2, { arg i_out=0, sustain=1, freq;
		var out;
		out = RLPF.ar(
			LFSaw.ar( freq ),
			LFNoise1.kr(1, 36, 110).midicps,
			0.1
		) * EnvGen.kr( Env.perc, levelScale: 0.3,
			timeScale: sustain, doneAction: Done.freeSelf );
		//out = [out, DelayN.ar(out, 0.04, 0.04) ];
		4.do({ out = AllpassN.ar(out, 0.05, [0.05.rand, 0.05.rand], 4) });
		Out.ar( i_out, out );
	}).send(s);
)
(
// streams as a sequence of pitches
	var pattern, streams, dur, durDiff;
	dur = 1/7;
	durDiff = 3;
	pattern = Prout.new({
		loop({
			if (0.5.coin, {
				#[ 24,31,36,43,48,55 ].do({ arg fifth; fifth.yield });
			});
			rrand(2,5).do({
				// varying arpeggio
				60.yield;
				#[63,65].choose.yield;
				67.yield;
				#[70,72,74].choose.yield;
			});
			// random high melody
			rrand(3,9).do({ #[74,75,77,79,81].choose.yield });
		});
	});
	streams = [
		(pattern - Pfunc.new({ #[12, 7, 7, 0].choose })).midicps.asStream,
		pattern.midicps.asStream
	];
	Routine({
		loop({
			Synth( \help_SPE2, [ \freq, streams.at(0).next, \sustain, dur * durDiff ] );
			durDiff.do({
				Synth( \help_SPE2, [ \freq, streams.at(1).next, \sustain, dur ] );
				dur.wait;
			});
		})
	}).play
)
::

To go to the next file:
link::Tutorials/Streams-Patterns-Events3::