This file is indexed.

/usr/share/SuperCollider/HelpSource/Classes/Stream.schelp is in supercollider-common 1:3.8.0~repack-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
class:: Stream
summary:: Stream is the base class for classes that define streams
related:: Classes/Routine, Classes/FuncStream, Classes/EventStreamPlayer
categories:: Streams-Patterns-Events

description::

Stream is an abstract class that is not used directly. The following attempts to document some aspects of the use of Streams for music generation.

subsection::Overview

A Stream represents a sequence of values that are obtained incrementally by repeated strong::next:: messages. A Stream can be restarted with a strong::reset:: message. (Not all streams actually implement reset semantics.)

The class link::Classes/Object:: defines strong::next:: to return the object itself. Thus every object can be viewed as a stream and most simply stream themselves.

In SuperCollider, Streams are primarily used for handling text and for generating music.

subsection::FuncStream(nextFunction, resetFunction)

A link::Classes/Function:: defines a stream consisting of the Function itself, a link::Classes/FuncStream:: defines a stream that consists of emphasis::evaluations:: of its nextFunction.

code::
// Example 1: a Function vs. a FuncStream
(
	f = { 33.rand };
	x = FuncStream(f);
	10.do({ [f.next, x.next].postln });
)
::

code::
// Example 2: the reset function
(
	f = { 33.rand };
	x = FuncStream(f, {thisThread.randSeed_(345)});
	x.reset;
	10.do({ [f.next, x.next].postln });
	x.reset;
	10.do({ [f.next, x.next].postln });
)
::

subsection::Routine(nextFunction, stacksize)

In a link::Classes/FuncStream::, the nextFunction runs through to completion for each element of the stream. In a link::Classes/Routine::, the nextFunction returns values with strong::yield:: and resumes execution (when it receives a strong::next:: message) at the expression following the yield. This allows a sequence of expressions in the function definition to represent a sequence of distinct events, like a musical score.

code::
// example
(
	x = Routine({
		1.yield;
		2.yield;
		3.yield;
	});
	4.do({ x.next.postln });
)
::

Once the nextFunction completes execution, the Routine simply yields nil repeatedly. Control structures (such as strong::do:: or strong::while::) can be used within the nextFunction in a manner analogous to repeat marks in a score.

code::
// example
(
	x = Routine({
		4.do({
			[1,2,3,4].do({ arg i; i.yield; });
		});
	});
	17.do({ x.next.postln });
)
::

subsection::Playing streams

Because streams respond like functions to the value message, they can be used as a scheduling task.

code::
// compare:
// a function, returning 0.5
(
SystemClock.sched(0.0,
	{ "***".postln; 0.5 }
);
)

// a stream, returning 0.5 and 0.1
(
SystemClock.sched(0.0,
	Routine({ loop {
		"***".postln; 0.5.yield;
		"_*_".postln; 0.1.yield;
	} });
);
)

// this is the reason why 'wait' works the same (for numbers) like 'yield'
(
SystemClock.sched(0.0,
	Routine({ loop {
		"***".postln; 0.5.wait;
		"_*_".postln; 0.1.wait;
	} });
);
)
::

Streams that return strong::numbers:: can be played directly with the strong::play:: message.

code::
// play at the next beat, with offset 0.4
(
Routine({ loop {
	"***".postln; 0.5.wait;
	"_*_".postln; 0.1.wait;
} }).play(quant:[1, 0.4]);
)
::

Streams that return strong::Events:: need to be wrapped in an link::Classes/EventStreamPlayer::. The Event's strong::delta:: (can also be set by strong::dur::) is used as a scheduling beats value:

code::
// play at the next beat, with offset 0.4
(
Routine({ loop {
	"///".postln; (delta:0.5).yield;
	"_/_".postln; (delta: 0.1).wait;
} }).asEventStreamPlayer.play;
)
::

subsection::Iteration

The method link::#-do:: effectively 'plays' a stream by iterating all of its contents.

And the following messages create a stream by filtering another stream in some way: link::#-collect::, link::#-reject::, link::#-select::, link::#-dot::, link::#-interlace::, link::#-appendStream::, link::#-embedInStream::, link::#-trace::.

subsection::Composite Streams

Routines can be strong::embedded:: in each other, using link::#-embedInStream:: :

code::
// example
(
x = Routine({
	2.do({
		[1,2,3,4].do({ arg i; i.yield; });
	});
});
y = Routine({
	100.yield;
	30.yield;
	x.embedInStream;
	440.yield;
	1910.yield;
});
17.do({ y.next.postln });
)
::

Routines can be strong::concatenated:: just like Streams:

code::
(
x = Routine({
	2.do({
		[1,2,3,4].do({ arg i; i.yield; });
	});
});
y = Routine({
	100.yield;
	30.yield;
});
z = x ++ y;
17.do({ z.next.postln });
)
::

Routines can be strong::combined:: with the composition operator <>

code::
(
x = Routine({ arg inval;
	2.do({
		[1,2,3,4].do({ arg i;
			if(inval.isNil) { nil.alwaysYield };
			inval = (i * inval).yield;
		});
	});
});
y = Routine({
	100.yield;
	30.yield;
	4.do { 1.0.rand.yield };
});
z = x <> y;
17.do({ z.value.postln }); // call .value here, as this is a function.
)
::

Composite Streams can be defined as combinations of Streams using the unary and binary messages.

subsection::Unary messages

Streams support most of the unary messages defined in link::Classes/AbstractFunction:: :

code::
(
a = Routine({ 20.do({ 33.rand.yield }) });
b = Routine({ [-100,00,300,400].do({ arg v; v.yield}) });

c = b.neg; // define a composite stream

// enumerate and perform all of the unary messages:
[
	\neg, \reciprocal, \bitNot, \abs, \asFloat, \asInteger, \ceil,
	\floor, \frac, \sign, \squared, \cubed, \sqrt, \exp, \midicps,
	\cpsmidi, \midiratio, \ratiomidi, \ampdb, \dbamp, \octcps,
	\cpsoct, \log, \log2, \log10, \sin, \cos, \tan, \asin, \acos, \atan,
	\sinh, \cosh, \tanh, \rand, \rand2, \linrand, \bilinrand, \sum3rand,
	\distort, \softclip, \coin, \even, \odd, \isPositive, \isNegative,
	\isStrictlyPositive
]
.do({ arg msg;
	postf("\n msg: % \n", msg);
	b.reset.perform(msg).do({arg v; v.post; " ".post;});
});
nil;
)
::

subsection::Binary messages

Streams support the following binary messages defined in link::Classes/AbstractFunction:: :

code::
(
a = Routine({ 20.do({ 33.rand.yield }) });
b = Routine({ [-100,00,300,400].do({ arg v; v.yield}) });
[
	'+' , '-' , '*', '/', \div, '%', '**', \min, \max, '<', '<=', '>', '>=', '&', '|',
	\bitXor, \lcm, \gcd, \round, \trunc, \atan2,
	\hypot, '>>', '+>>', \ring1, \ring2, \ring3, \ring4,
	\difsqr, \sumsqr, \sqrdif, \absdif, \amclip,
	\scaleneg, \clip2, \excess, '<!', \rrand, \exprand
]
.do({ arg msg;
	postf("\n msg: % \n", msg);
	b.reset.perform(msg).do({ arg v; v.post; " ".post; });
});
nil;
)
::

InstanceMethods::

method::play
Streams that return strong::numbers:: can be played directly with the strong::play:: message. Streams that return strong::events:: need to be wrapped in an link::Classes/EventStreamPlayer::. See link::#-asEventStreamPlayer::.

argument::clock
a clock. link::Classes/TempoClock:: by default.

argument::quant
either a number strong::n:: (quantize to strong::n:: beats), or an array strong::[n, m]:: (quantize to n beats, with offset m).

method::do
iterate until a nil is encountered.
warning::
Applying do to an endless stream will lock up the interpreter!
::

method::collect
iterate indefinitely.

method::reject
return only those elements for which function.value(element) is false.

method::select
return only those elements for which function.value(element) is true.

method::dot
return function.value(this.next, stream.next) for each element.

method::interlace
iterate all of stream for each element of this. Combine the values using function.

method::appendStream
append stream after this returns nil. The same like ++

method::embedInStream
iterate all of this from within whatever Stream definition it is called.

method::trace
print out the results of a stream while returning the original values.

argument::key
when streaming events, post only this key.

argument::printStream
printOn this stream (default: link::Classes/Post::).

argument::prefix
string added to the printout to separate different streams.