1 <!DOCTYPE html PUBLIC
"-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
4 <meta http-equiv=
"Content-Type" content=
"text/html; charset=UTF-8">
5 <meta http-equiv=
"Content-Style-Type" content=
"text/css">
7 <meta name=
"Generator" content=
"Cocoa HTML Writer">
8 <meta name=
"CocoaVersion" content=
"824.44">
9 <style type=
"text/css">
10 p
.p1
{margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica
}
11 p
.p2
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
; min-height: 14.0px}
12 p
.p3
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
}
13 p
.p4
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #902a19}
14 p
.p5
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #902a19; min-height: 12.0px}
15 p
.p6
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
}
16 p
.p7
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; min-height: 12.0px}
17 p
.p8
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #606060}
18 span
.s1
{font: 12.0px Helvetica
}
19 span
.s2
{color: #091fb1}
20 span
.s3
{color: #000000}
21 span
.s4
{color: #606060}
22 span
.s5
{font: 9.0px Monaco
; color: #091fb1}
23 span
.s6
{font: 9.0px Monaco
}
24 span
.s7
{color: #456c20}
25 span
.s8
{color: #902a19}
26 span
.s9
{font: 12.0px Helvetica
; color: #000000}
27 span
.Apple-tab-span
{white-space:pre
}
31 <p class=
"p1"><b>Synchronous and Asynchronous Execution
</b></p>
32 <p class=
"p2"><br></p>
33 <p class=
"p3">Using a program such as SuperCollider introduces a number of issues regarding timing and order of execution. Realtime audio synthesis requires that samples are calculated and played back at a certain rate and on a certain schedule, in order to avoid dropouts, glitches, etc. Other tasks, such as loading a sample into memory, might take arbitrary amounts of time, and may not be needed within a definite timeframe. This is the difference between synchronous and asynchronous tasks.
</p>
34 <p class=
"p2"><br></p>
35 <p class=
"p3">Problems can arise when synchronous tasks are dependent upon the completion of asynchronous ones. For instance trying to play a sample that may or may not have been completely loaded yet.
</p>
36 <p class=
"p2"><br></p>
37 <p class=
"p3">In SC2 this was relatively simple to handle. One scheduled synchronous tasks during synthesis, i.e. within the scope of a Synth.play. Asynchronous tasks were executed in order, outside of synthesis. Thus one would first create buffers, load samples into them, and then start synthesis and play them back. The interpreter made sure that each step was only done when the necessary previous step had been completed.
</p>
38 <p class=
"p2"><br></p>
39 <p class=
"p3">In SC3 the separation of language and synth apps creates a problem: How does one side know that the other has completed necessary tasks, or in other words, how does the left hand know if the right is finished? The flexibility gained by the new architecture introduces another layer of complexity, and an additional demand on the user.
</p>
40 <p class=
"p2"><br></p>
41 <p class=
"p3">A simple way to deal with this is to execute code in blocks. In the following code, for instance, each block or line of code is dependent upon the previous one being completed.
</p>
42 <p class=
"p2"><br></p>
43 <p class=
"p4">// Execute these one at a time
</p>
44 <p class=
"p5"><br></p>
45 <p class=
"p4">// Boot the local Server
</p>
46 <p class=
"p6"><span class=
"s1"><span class=
"Apple-tab-span"> </span></span>(
</p>
47 <p class=
"p6"><span class=
"Apple-tab-span"> </span>s =
<span class=
"s2">Server
</span>.local;
</p>
48 <p class=
"p6"><span class=
"Apple-tab-span"> </span>s.boot;
</p>
49 <p class=
"p6"><span class=
"Apple-tab-span"> </span>)
</p>
50 <p class=
"p7"><br></p>
51 <p class=
"p4">// Compile a SynthDef and write it to disk
</p>
52 <p class=
"p6"><span class=
"Apple-tab-span"> </span>(
</p>
53 <p class=
"p8"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span><span class=
"s2">SynthDef
</span><span class=
"s3">(
</span>"Help-SynthDef"<span class=
"s3">,
<span class=
"Apple-converted-space"> </span></span></p>
54 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>{
<span class=
"s2">arg
</span> out=
0;
</p>
55 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span> <span class=
"s2">Out
</span>.ar(out,
<span class=
"s2">PinkNoise
</span>.ar(
0.1))
</p>
56 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>}).writeDefFile;
</p>
57 <p class=
"p6"><span class=
"Apple-tab-span"> </span>)
</p>
58 <p class=
"p7"><br></p>
59 <p class=
"p4">// Load it into the server
</p>
60 <p class=
"p6"><span class=
"Apple-tab-span"> </span>s.loadSynthDef(
<span class=
"s4">"Help-SynthDef"</span>);
</p>
61 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
62 <p class=
"p4">// Create a Synth with it
</p>
63 <p class=
"p6"><span class=
"Apple-tab-span"> </span>x =
<span class=
"s2">Synth
</span>.new(
<span class=
"s4">"Help-SynthDef"</span>, s);
</p>
64 <p class=
"p7"><br></p>
65 <p class=
"p4">// Free the node on the server
</p>
66 <p class=
"p6"><span class=
"Apple-tab-span"> </span>x.free;
</p>
67 <p class=
"p7"><br></p>
68 <p class=
"p4">// Allow the client-side Synth object to be garbage collected
</p>
69 <p class=
"p6"><span class=
"Apple-tab-span"> </span>x =
<span class=
"s2">nil
</span>;
<span class=
"s1"><span class=
"Apple-converted-space"> </span></span></p>
70 <p class=
"p2"><br></p>
71 <p class=
"p3">In the previous example it was necessary to use interpreter variables (the variables a-z, which are declared at compile time) in order to refer to previously created objects in later blocks or lines of code. If one had declared a variable within a block of code (i.e.
<span class=
"s2"> </span><span class=
"s5">va
</span><span class=
"s6">r mySynth;
</span>) than it would have only persisted within that scope. (See the helpfile
<b>Scope
</b> for more detail.)
</p>
72 <p class=
"p2"><br></p>
73 <p class=
"p3">This style of working, executing lines or blocks of code one at a time, can be very dynamic and flexible, and can be quite useful in a performance situation, especially when improvising. But it does raise the issues of scope and persistence. Another way around this that allows for more descriptive variable names is to use environment variables (i.e. names that begin with ~, so ~mysynth; see the
<b>Environment
</b> helpfile for details). However, in both methods you become responsible for making sure that objects and nodes do not persist when you no longer need them.
<span class=
"Apple-converted-space"> </span></p>
74 <p class=
"p7"><br></p>
75 <p class=
"p6"><span class=
"Apple-tab-span"> </span>(
</p>
76 <p class=
"p8"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span><span class=
"s2">SynthDef
</span><span class=
"s3">(
</span>"Help-SynthDef"<span class=
"s3">,
<span class=
"Apple-converted-space"> </span></span></p>
77 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>{
<span class=
"s2">arg
</span> out=
0;
</p>
78 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span> <span class=
"s2">Out
</span>.ar(out,
<span class=
"s2">PinkNoise
</span>.ar(
0.1))
</p>
79 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>}).send(s);
</p>
80 <p class=
"p6"><span class=
"Apple-tab-span"> </span>)
</p>
81 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
82 <p class=
"p4"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span>// make a Synth and assign it to an environment variable
</p>
83 <p class=
"p6"><span class=
"Apple-tab-span"> </span>~mysynth =
<span class=
"s2">Synth
</span>.new(
<span class=
"s4">"Help-SynthDef"</span>, s);
</p>
84 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
85 <p class=
"p4"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span>// free the synth
</p>
86 <p class=
"p6"><span class=
"Apple-tab-span"> </span>~mysynth.free;
</p>
87 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
88 <p class=
"p4"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span>// but you've still got a Synth object
</p>
89 <p class=
"p6"><span class=
"Apple-tab-span"> </span>~mysynth.postln;
</p>
90 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
91 <p class=
"p4"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span>// so remove it from the Environment so that the Synth will be garbage collected
</p>
92 <p class=
"p6"><span class=
"Apple-tab-span"> </span>currentEnvironment.removeAt(
<span class=
"s7">\mysynth
</span>);
</p>
93 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
94 <p class=
"p3">But what if you want to have one block of code which contains a number of synchronous and asynchronous tasks. The following will cause an error, as the SynthDef that the server needs has not yet been received.
</p>
95 <p class=
"p2"><br></p>
96 <p class=
"p4">// Doing this all at once produces the error
"FAILURE /s_new SynthDef not found"</p>
97 <p class=
"p6"><span class=
"Apple-tab-span"> </span>(
</p>
98 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"s2">var
</span> name;
</p>
99 <p class=
"p4"><span class=
"s3"><span class=
"Apple-tab-span"> </span>name =
</span><span class=
"s4">"Rand-SynthDef"</span><span class=
"s3"> ++
400.0.rand;
</span>// use a random name to ensure it's not already loaded
</p>
100 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"s2">SynthDef
</span>(name,
<span class=
"Apple-converted-space"> </span></p>
101 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>{
<span class=
"s2">arg
</span> out=
0;
</p>
102 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span> <span class=
"s2">Out
</span>.ar(out,
<span class=
"s2">PinkNoise
</span>.ar(
0.1))
</p>
103 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>}).send(s);
</p>
104 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
105 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"s2">Synth
</span>.new(name, s);
</p>
106 <p class=
"p6"><span class=
"Apple-tab-span"> </span>)
</p>
107 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
108 <p class=
"p3">A crude solution would be to schedule the dependant code for execution after a seemingly sufficient delay using a clock.
</p>
109 <p class=
"p2"><br></p>
110 <p class=
"p4">// This one works since the def gets to the server app first
</p>
111 <p class=
"p6"><span class=
"Apple-tab-span"> </span>(
</p>
112 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"s2">var
</span> name;
</p>
113 <p class=
"p6"><span class=
"Apple-tab-span"> </span>name =
<span class=
"s4">"Rand-SynthDef"</span> ++
400.0.rand;
</p>
114 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"s2">SynthDef
</span>(name,
<span class=
"Apple-converted-space"> </span></p>
115 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>{
<span class=
"s2">arg
</span> out=
0;
</p>
116 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span> <span class=
"s2">Out
</span>.ar(out,
<span class=
"s2">PinkNoise
</span>.ar(
0.1))
</p>
117 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>}).send(s);
</p>
118 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
119 <p class=
"p6"><span class=
"Apple-tab-span"> </span>SystemClock.sched(
0.05, {
<span class=
"s2">Synth
</span>.new(name, s);}); // create a Synth after
0.05 seconds
</p>
120 <p class=
"p6"><span class=
"Apple-tab-span"> </span>)
</p>
121 <p class=
"p2"><br></p>
122 <p class=
"p3">Although this works, it's not very elegant or efficient. What would be better would be to have the next thing execute immediately upon the previous thing's completion. To explore this, we'll look at an example which is already implemented.
</p>
123 <p class=
"p2"><br></p>
124 <p class=
"p3">You may have realized that first example above was needlessly complex. SynthDef-play will do all of this compilation, sending, and Synth creation in one stroke of the enter key.
</p>
125 <p class=
"p2"><br></p>
126 <p class=
"p4">// All at once
</p>
127 <p class=
"p6"><span class=
"Apple-tab-span"> </span>(
</p>
128 <p class=
"p8"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span><span class=
"s2">SynthDef
</span><span class=
"s3">(
</span>"Help-SynthDef"<span class=
"s3">,
<span class=
"Apple-converted-space"> </span></span></p>
129 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>{
<span class=
"s2">arg
</span> out=
0;
</p>
130 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span> <span class=
"s2">Out
</span>.ar(out,
<span class=
"s2">PinkNoise
</span>.ar(
0.1))
</p>
131 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>}).play(s);
</p>
132 <p class=
"p6"><span class=
"Apple-tab-span"> </span>)
</p>
133 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
134 <p class=
"p3">Let's take a look at the method definition for SynthDef-play and see what it does.
</p>
135 <p class=
"p2"><br></p>
136 <p class=
"p6"><span class=
"Apple-tab-span"> </span>play {
<span class=
"s2">arg
</span> target,args,addAction=
<span class=
"s7">\addToTail
</span>;
</p>
137 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s2">var
</span> synth, msg;
</p>
138 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>target = target.asTarget;
</p>
139 <p class=
"p7"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
140 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>synth =
<span class=
"s2">Synth
</span>.basicNew(name,target.server);
<span class=
"s8">// create a Synth, but not a synth node
<span class=
"Apple-converted-space"> </span></span></p>
141 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>msg = synth.newMsg(target, addAction, args);
<span class=
"s8">// make a message that will add a synth node
<span class=
"Apple-converted-space"> </span></span></p>
142 <p class=
"p4"><span class=
"s3"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span><span class=
"s2">this
</span><span class=
"s3">.send(target.server, msg);
</span>// ** send the def, and the message as a completion message
</p>
143 <p class=
"p4"><span class=
"s3"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>^synth
</span>// return the Synth object
</p>
144 <p class=
"p6"><span class=
"Apple-tab-span"> </span>}
</p>
145 <p class=
"p2"><br></p>
146 <p class=
"p3">This might seem a little complicated if you're not used to mucking about in class definitions, but the important part is the second argument to
<span class=
"s5">this
</span><span class=
"s6">.send(target.server, msg);
</span>. This argument is a completion message, it is a message that the server will execute when the send action is complete. In this case it says create a synth node on the server which corresponds to the
<b>Synth
</b> object I've already created, when and only when the def has been sent to the server app.
<span class=
"Apple-converted-space"> </span>(See the helpfile
<b>Server-Command-Reference
</b>for details on messaging.)
</p>
147 <p class=
"p2"><br></p>
148 <p class=
"p3">Many methods in SC have the option to include completion messages. Here we can use SynthDef-send to accomplish the same thing as SynthDef-play:
</p>
149 <p class=
"p2"><br></p>
150 <p class=
"p4">// Compile, send, and start playing
</p>
151 <p class=
"p6"><span class=
"Apple-tab-span"> </span>(
</p>
152 <p class=
"p8"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span><span class=
"s2">SynthDef
</span><span class=
"s3">(
</span>"Help-SynthDef"<span class=
"s3">,
<span class=
"Apple-converted-space"> </span></span></p>
153 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>{
<span class=
"s2">arg
</span> out=
0;
</p>
154 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span> <span class=
"s2">Out
</span>.ar(out,
<span class=
"s2">PinkNoise
</span>.ar(
0.1))
</p>
155 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>}).send(s, [
<span class=
"s4">"s_new"</span>,
<span class=
"s4">"Help-SynthDef"</span>, x = s.nextNodeID]);
<span class=
"Apple-converted-space"> </span></p>
156 <p class=
"p4"><span class=
"s3"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// this is 'messaging' style, see below
</p>
157 <p class=
"p6"><span class=
"Apple-tab-span"> </span>)
</p>
158 <p class=
"p6"><span class=
"Apple-tab-span"> </span>s.sendMsg(
<span class=
"s4">"n_free"</span>, x);
</p>
159 <p class=
"p2"><span class=
"Apple-tab-span"> </span></p>
160 <p class=
"p3">The completion message needs to be an OSC message, but it can also be some code which when evaluated
<span class=
"Apple-converted-space"> </span>returns one:
</p>
161 <p class=
"p2"><br></p>
162 <p class=
"p4">// Interpret some code to return a completion message. The .value is needed.
</p>
163 <p class=
"p4">// This and the preceding example are essentially the same as SynthDef.play
</p>
164 <p class=
"p3"><span class=
"Apple-tab-span"> </span><span class=
"s6">(
</span></p>
165 <p class=
"p8"><span class=
"s9"><span class=
"Apple-tab-span"> </span></span><span class=
"s2">SynthDef
</span><span class=
"s3">(
</span>"Help-SynthDef"<span class=
"s3">,
<span class=
"Apple-converted-space"> </span></span></p>
166 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>{
<span class=
"s2">arg
</span> out=
0;
</p>
167 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span> <span class=
"s2">Out
</span>.ar(out,
<span class=
"s2">PinkNoise
</span>.ar(
0.1))
</p>
168 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>}).send(s, {x =
<span class=
"s2">Synth
</span>.basicNew(
<span class=
"s4">"Help-SynthDef"</span>); x.newMsg; }.value);
<span class=
"s8">// 'object' style
</span></p>
169 <p class=
"p6"><span class=
"Apple-tab-span"> </span>)
</p>
170 <p class=
"p6"><span class=
"Apple-tab-span"> </span>x.free;
</p>
171 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
172 <p class=
"p3">If you prefer to work in 'messaging' style, this is pretty simple. If you prefer to work in 'object' style, you can use the commands like newMsg, setMsg, etc. with objects to create appropriate server messages. The two proceeding examples show the difference. See the
<b>NodeMessaging
</b> helpfile for more detail.
</p>
173 <p class=
"p2"><br></p>
174 <p class=
"p3">In the case of
<b>Buffer
</b> objects a function can be used as a completion message. It will be evaluated and passed the
<b>Buffer
</b> object as an argument. This will happen after the Buffer object is created, but before the message is sent to the server. It can also return a valid OSC message for the server to execute upon completion.
</p>
175 <p class=
"p2"><br></p>
176 <p class=
"p6"><span class=
"Apple-tab-span"> </span>(
</p>
177 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"s2">SynthDef
</span>(
<span class=
"s4">"help-Buffer"</span>,{
<span class=
"s2">arg
</span> out=
0,bufnum;
</p>
178 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s2">Out
</span>.ar( out,
</p>
179 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s2">PlayBuf
</span>.ar(
1,bufnum,
<span class=
"s2">BufRateScale
</span>.kr(bufnum))
</p>
180 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>)
</p>
181 <p class=
"p6"><span class=
"Apple-tab-span"> </span>}).load(s);
</p>
182 <p class=
"p7"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></p>
183 <p class=
"p6"><span class=
"Apple-tab-span"> </span>y =
<span class=
"s2">Synth
</span>.basicNew(
<span class=
"s4">"help-Buffer"</span>);
<span class=
"s8">// not sent yet
</span></p>
184 <p class=
"p8"><span class=
"s3"><span class=
"Apple-tab-span"> </span>b =
</span><span class=
"s2">Buffer
</span><span class=
"s3">.read(s,
</span>"sounds/a11wlk01.wav"<span class=
"s3">,
<span class=
"Apple-converted-space"> </span></span></p>
185 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>completionMessage: {
<span class=
"s2">arg
</span> buffer;
<span class=
"Apple-converted-space"> </span></p>
186 <p class=
"p4"><span class=
"s3"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// synth add its s_new msg to follow
<span class=
"Apple-converted-space"> </span></p>
187 <p class=
"p4"><span class=
"s3"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// after the buffer read completes
</p>
188 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>y.newMsg(s,
<span class=
"s7">\addToTail
</span>,[
<span class=
"s7">\bufnum
</span>,buffer])
</p>
189 <p class=
"p4"><span class=
"s3"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>});
</span>// .value NOT needed, unlike in the previous example
</p>
190 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
191 <p class=
"p6"><span class=
"Apple-tab-span"> </span>)
</p>
192 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
193 <p class=
"p4"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span>// when done...
</p>
194 <p class=
"p6"><span class=
"Apple-tab-span"> </span>y.free;
</p>
195 <p class=
"p6"><span class=
"Apple-tab-span"> </span>b.free;
</p>
196 <p class=
"p7"><span class=
"Apple-tab-span"> </span></p>
197 <p class=
"p3">The main purpose of completion messages is to provide OSC messages for the server to execute immediately upon completion. In the case of Buffer there is essentially no difference between the following:
</p>
198 <p class=
"p2"><br></p>
199 <p class=
"p6"><span class=
"Apple-tab-span"> </span>(
</p>
200 <p class=
"p6"><span class=
"Apple-tab-span"> </span>b =
<span class=
"s2">Buffer
</span>.alloc(s,
44100,
<span class=
"Apple-converted-space"> </span></p>
201 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>completionMessage: {
<span class=
"s2">arg
</span> buffer; (
<span class=
"s4">"bufnum:"</span> + buffer).postln; });
</p>
202 <p class=
"p6"><span class=
"Apple-tab-span"> </span>)
</p>
203 <p class=
"p4"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span>// this is equivalent to the above
</p>
204 <p class=
"p6"><span class=
"Apple-tab-span"> </span>(
</p>
205 <p class=
"p6"><span class=
"Apple-tab-span"> </span>b =
<span class=
"s2">Buffer
</span>.alloc;
</p>
206 <p class=
"p6"><span class=
"Apple-tab-span"> </span>(
<span class=
"s4">"bufnum:"</span> + b).postln;
</p>
207 <p class=
"p6"><span class=
"Apple-tab-span"> </span>)
</p>
208 <p class=
"p2"><br></p>
209 <p class=
"p3">One can also evaluate a function in response to a 'done' message, or indeed any other one, using an
<b>OSCresponder
</b> or an
<b>OSCresponderNode
</b>. The main difference between the two is that the former allows only a single responder per command, where as the latter allows multiple responders. See their respective helpfiles for details.
</p>
210 <p class=
"p2"><br></p>
212 <p class=
"p8"><span class=
"s2">SynthDef
</span><span class=
"s3">(
</span>"help-SendTrig"<span class=
"s3">,{
</span></p>
213 <p class=
"p6"><span class=
"Apple-tab-span"> </span><span class=
"s2">SendTrig
</span>.kr(
<span class=
"s2">Dust
</span>.kr(
1.0),
0,
0.9);
</p>
214 <p class=
"p6">}).send(s);
</p>
215 <p class=
"p7"><br></p>
216 <p class=
"p4">// register to receive this message
</p>
217 <p class=
"p6"><span class=
"s2">a = OSCresponderNode
</span>(s.addr,
<span class=
"s7">'/done'
</span>, {
<span class=
"s2">arg
</span> time, responder, msg;
</p>
218 <p class=
"p6"><span class=
"Apple-tab-span"> </span>(
"This is the done message for the SynthDef.send:" + [time, responder, msg]).postln;
</p>
219 <p class=
"p4"><span class=
"s3">}).add.removeWhenDone;
</span>// remove me automatically when done
</p>
220 <p class=
"p6"><span class=
"s2">b = OSCresponderNode
</span>(s.addr,
<span class=
"s7">'/tr'
</span>, {
<span class=
"s2">arg
</span> time, responder, msg;
</p>
221 <p class=
"p6"><span class=
"Apple-tab-span"> </span>[time, responder, msg].postln;
</p>
222 <p class=
"p6">}).add;
</p>
223 <p class=
"p6"><span class=
"s2">c = OSCresponderNode
</span>(s.addr,
<span class=
"s7">'/tr'
</span>, {
<span class=
"s2">arg
</span> time, responder, msg;
</p>
224 <p class=
"p6"><span class=
"Apple-tab-span"> </span>"this is another call".postln;
</p>
225 <p class=
"p6">}).add;
</p>
227 <p class=
"p7"><br></p>
228 <p class=
"p7"><br></p>
229 <p class=
"p8"><span class=
"s2">x = Synth
</span><span class=
"s3">.new(
</span>"help-SendTrig"<span class=
"s3">);
</span></p>
230 <p class=
"p6">b.remove;
</p>
231 <p class=
"p6">c.remove;
</p>
232 <p class=
"p6">x.free;
</p>