This file is indexed.

/usr/share/SuperCollider/HelpSource/Guides/Spawning.schelp is in supercollider-common 1:3.6.3~repack-5.

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
title:: "Spawning" and "TSpawning"
summary:: The lack of the Spawn and TSpawn UGens and their various convienence classes
categories:: SC3 vs SC2

In SC2, Spawn and TSpawn were two of the most powerful and commonly used UGens. In SC3 the idea of a top level Synth in which everything is spawned is no longer valid. Synthesis is always running (at least as long as a server is) and new Synths can be created on the fly. This arrangement results in even greater flexibility than in SC2, but requires a slightly different approach.

In SC3 one can create Synths at any time simply by executing blocks of code.

code::
// do this
(
x = SynthDef("Help-SynthDef", { arg out = 0;
	Out.ar(out, PinkNoise.ar(0.1))
}).play; // SynthDef-play returns a Synth object.
)

// then do this
(
SynthDef("help-Rand", { arg out = 0;
	Out.ar(
		out,
		FSinOsc.ar(
			Rand(200.0, 400.0), // frequency between 200 and 400 Hz
			0, Line.kr(0.2, 0, 1, doneAction:2) // frees itself
		)
	)
}).play(s);
)

x.free;
::

Clocks, such as link::Classes/SystemClock::, provide a way to schedule things at arbitrary points in the future. This is similar to code::Synth.sched:: in SC2.

code::
(
SystemClock.sched(2.0, {
	"2.0 seconds later".postln; // this could be any code, including Synth creation
	nil // this means don't repeat
});
)
::

In SC3 time-based sequences of events can be implemented using Routines. A link::Classes/Routine:: which yields a number can be scheduled using a clock:

code::
(
var w, r;

w = Window.new("trem", Rect(512, 256, 360, 130));
w.front;

r = Routine({ arg time;
	60.do({ arg i;
		0.05.yield; // wait for 0.05 seconds
		{
			w.bounds = w.bounds.moveBy(10.rand2, 10.rand2);
			w.alpha = cos(i*0.1pi)*0.5+0.5;
		}.defer;
	});
	1.yield; // wait for 1 second before closing w
	w.close;
});

SystemClock.play(r);
)
::

Note that this implementation avoids one of the stranger aspects of the SC2 approach: The need to start a Synth to schedule time-based behavior, even if no audio is involved.

Both link::Classes/SystemClock:: and link::Classes/AppClock:: (a less accurate version which can call Cocoa primitives) have only class methods. Thus one does not create instances of them. If you need to have an individual clock to manipulate (for instance to manipulate the tempi of different sequences of events) you can use link::Classes/TempoClock::.

A simple SC2 Spawn example is shown below, followed by its translation into SC3 style code.

code::
// This will not execute in SC3
(
Synth.play({
	Spawn.ar(
		{ EnvGen.ar(Env.perc) * SinOsc.ar(440,0,0.1) },
		1, // one channels
		1 // new event every second
	)
})
)

// The same example in SC3 (will execute)
(
s = Server.default;
s.boot;
)

(
SynthDef("help-EnvGen",{ arg out = 0;
	Out.ar(
		out,
		EnvGen.kr(Env.perc,1.0,doneAction: 2) * SinOsc.ar(440,0,0.1)
	)
}).send(s);
)

(
r = Routine.new({ { Synth.new("help-EnvGen"); 1.yield; }.loop }); // loop every one second
SystemClock.play(r);
)
::

Note that the above example uses a precompiled link::Classes/SynthDef::. This results in a lower CPU spike when Synths are created than SC2-style Spawning. It is possible to create SynthDefs on the fly, if this is necessary, but a great deal of variation can be achieved with arguments, or with UGens such as link::Classes/Rand:: and link::Classes/TRand::. See the section link::Overviews/SC3vsSC2#SynthDefsVsSynths:: for more detail.

code::
// SynthDefs on the fly
(
s = Server.default;
s.boot;
)

(
t = TempoClock.new;
r = Routine.new({
	10.do({
		// could be done with an argument instead of a new def, but proves the point
		SynthDef("help-EnvGen" ++ i, { arg out = 0;
			Out.ar(
				out,
				EnvGen.kr(Env.perc, 1.0, doneAction: 2)
				* SinOsc.ar(100 + (100 * t.elapsedBeats), 0, 0.1)
			)
		}).play(s);
		1.yield;
	});
}).play(t); // Note the alternative syntax: Routine.play(aClock)
)
::

Note the alternative syntax for playing a Routine. code::aClock.play(aRoutine):: and code::aRoutine.play(aClock):: are functionally equivalent. The two make different things more or less convenient, like sending messages to the link::Classes/Routine:: or link::Classes/Clock::. (See the play helpfile for a more detailed discussion.) For instance:

code::
(
// this, that and the other
r = Routine.new({var i = 0; { ("this: " ++ i).postln; i = i + 1; 1.yield; }.loop });
q = Routine.new({var i = 0; { ("that: " ++ i).postln; i = i + 1; 1.yield; }.loop });
t = Routine.new({var i = 0; { ("the other: " ++ i).postln; i = i + 1; 1.yield; }.loop });
)

SystemClock.play(r);	// start this
SystemClock.play(q);	// start that
SystemClock.play(t);	// start the other

r.stop;			// stop this but not that or the other
q.reset;		// reset that while playing

c = TempoClock.new;	// make a TempoClock
r.reset;		// have to reset this because it's stopped
c.play(r);		// play this in the new clock; starts from the beginning
c.tempo = 16;		// increase the tempo of this

SystemClock.clear;	// clear EVERYTHING scheduled in the SystemClock; so that and the other
			// but not this

c.clear;		// clear everything scheduled in c, i.e. this
c.play(r);		// since it wasn't stopped, we don't have to reset this
			// and it picks up where it left off

c.stop;			// stop c, destroy its scheduler, and release its OS thread
::

For convenience pauseable scheduling can be implemented with a link::Classes/Task::. code::Task.new:: takes two arguments, a function and a clock, and creates it's own link::Classes/Routine::. If you don't specify a clock, it will create a link::Classes/TempoClock:: for you. Since you don't have to explicitly create a link::Classes/Clock:: or link::Classes/Routine::, use of link::Classes/Task:: can result in code that is a little more compact.

code::
(
t = Task.new({
	inf.do({ arg i;
		i.postln;
		0.5.wait
	});
});
)

t.start;		// Start it
t.stop;			// Stop it
t.start;		// Start again from the beginning
t.reset;		// Reset on the fly
t.stop;			// Stop again
t.resume;		// Restart from where you left off
t.clock.tempo = 0.25;	// Get the Task's clock and change the tempo. This works since the
			// default is a TempoClock.
t.pause;		// Same as t.stop
::

TSpawn's functionality can be replicated with link::Classes/SendTrig:: and link::Classes/OSCFunc::. See their individual helpfiles for details on their arguments and functionality.

code::
(
s = Server.default;
s.boot;
)

(
// this Synth will send a trigger to the client app
SynthDef("help-SendTrig", {
	SendTrig.kr(
		Dust.kr(1.0), // trigger could be anything, e.g. Amplitude.kr(SoundIn.ar(0) > 0.5)
		0, 0.9
	);
}).send(s);
)

(
// this receives the trigger on the client side and 'Spawns' a new Synth on the server
OSCFunc({
	SynthDef("help-EnvGen", { arg out = 0;
		Out.ar(
			out,
			EnvGen.kr(Env.perc, 1.0, doneAction: 2)
			* SinOsc.ar(440, 0, 0.1)
		)
	}).play(s);
}, '/tr', s.addr);

// Start 'spawning'
Synth("help-SendTrig");
)
::