SCDoc: Use proper static string constants instead of comparing string literals.
[supercollider.git] / Help / Language / Debugging-tips.html
blob05e68df35d37bd1b77ea26471b6cc13b42b78068
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5 <meta http-equiv="Content-Style-Type" content="text/css">
6 <title></title>
7 <meta name="Generator" content="Cocoa HTML Writer">
8 <meta name="CocoaVersion" content="824.42">
9 <style type="text/css">
10 p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 20.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: 14.0px Helvetica}
13 p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
14 p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}
15 p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #a71e12}
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: #0019b7}
18 p.p9 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #0022f5}
19 p.p10 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #906739}
20 p.p11 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #a71e12}
21 p.p12 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #326f17}
22 p.p13 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #606060}
23 span.s1 {color: #0019b7}
24 span.s2 {color: #326f17}
25 span.s3 {color: #000000}
26 span.s4 {color: #a71e12}
27 span.s5 {color: #df2818}
28 span.s6 {color: #6ff634}
29 span.s7 {color: #dd37f7}
30 span.s8 {color: #e98425}
31 span.s9 {color: #0022f5}
32 span.s10 {color: #906739}
33 span.s11 {text-decoration: underline}
34 span.s12 {color: #606060}
35 span.s13 {color: #0000ff}
36 span.Apple-tab-span {white-space:pre}
37 </style>
38 </head>
39 <body>
40 <p class="p1"><b>Debugging tips<span class="Apple-converted-space"> </span></b></p>
41 <p class="p2"><br></p>
42 <p class="p3"><b>Debugging synthdefs<span class="Apple-converted-space"> </span></b></p>
43 <p class="p3"><b>Debugging client-to-server communication</b></p>
44 <p class="p3"><b>Debugging client code<span class="Apple-converted-space"> </span></b></p>
45 <p class="p2"><br></p>
46 <p class="p3"><b>Debugging synthdefs<span class="Apple-converted-space"> </span></b></p>
47 <p class="p2"><br></p>
48 <p class="p4">The challenge in debugging synthdefs is the invisibility of the server's operations. There are a handful of techniques to expose the output of various UGens.<span class="Apple-converted-space"> </span></p>
49 <p class="p2"><br></p>
50 <p class="p4"><b>SendTrig / OSCresponderNode<span class="Apple-converted-space"> </span></b></p>
51 <p class="p2"><br></p>
52 <p class="p4">SendTrig is originally intended to send a trigger message back to the client, so the client can take further action on the server. However, it can be used to send any numeric value back to the client, which can then be printed out.<span class="Apple-converted-space"> </span></p>
53 <p class="p2"><br></p>
54 <p class="p4">To print out the values, you need to create an OSCresponderNode as follows:</p>
55 <p class="p2"><br></p>
56 <p class="p5">o = <span class="s1">OSCresponderNode</span>(myServer.addr, <span class="s2">'/tr'</span>, { <span class="s1">|time, resp, msg|</span> msg.postln }).add;<span class="Apple-converted-space"> </span></p>
57 <p class="p2"><br></p>
58 <p class="p4">Each line of output is an array with four values: ['/tr', defNode, id (from SendTrig), value (from SendTrig)].<span class="Apple-converted-space"> </span></p>
59 <p class="p2"><br></p>
60 <p class="p5">{<span class="Apple-tab-span"> </span><span class="s1">var</span><span class="Apple-tab-span"> </span>freq;</p>
61 <p class="p5"><span class="Apple-tab-span"> </span>freq = <span class="s1">LFNoise1</span>.kr(2, 600, 800);</p>
62 <p class="p6"><span class="s3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// Impulse is needed to trigger the /tr message to be sent</p>
63 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">SendTrig</span>.kr(<span class="s1">Impulse</span>.kr(4), 0, freq);</p>
64 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">SinOsc</span>.ar(freq, 0, 0.3) ! 2</p>
65 <p class="p5">}.play;</p>
66 <p class="p5">[ /tr, 1000, 0, 1340.8098144531 ]</p>
67 <p class="p5">[ /tr, 1000, 0, 1153.9201660156 ]</p>
68 <p class="p5">[ /tr, 1000, 0, 966.35247802734 ]</p>
69 <p class="p5">[ /tr, 1000, 0, 629.31628417969 ]</p>
70 <p class="p7"><br></p>
71 <p class="p6"><span class="s3">o.remove;<span class="Apple-converted-space">  </span></span>// when done, you need to clean up the OSCresponderNode</p>
72 <p class="p2"><br></p>
73 <p class="p4">If you need to track multiple values, you can store them in a collection of arrays and differentiate them by assigning different IDs in the SendTrig UGen.<span class="Apple-converted-space"> </span></p>
74 <p class="p2"><br></p>
75 <p class="p5">l = { <span class="s1">List</span>.new } ! 2;</p>
76 <p class="p8"><span class="s3">o = </span>OSCresponderNode<span class="s3">(myServer.addr, </span><span class="s2">'/tr'</span><span class="s3">, { </span>|time, resp, msg|</p>
77 <p class="p6"><span class="s3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// msg[2] is the index</p>
78 <p class="p5"><span class="Apple-tab-span"> </span>l[msg[2]].add(msg[3]);</p>
79 <p class="p5">}).add;<span class="Apple-converted-space"> </span></p>
80 <p class="p7"><br></p>
81 <p class="p5">{<span class="Apple-tab-span"> </span><span class="s1">var</span><span class="Apple-tab-span"> </span>freq, amp;</p>
82 <p class="p5"><span class="Apple-tab-span"> </span>freq = <span class="s1">LFNoise0</span>.kr(8, 600, 800);</p>
83 <p class="p5"><span class="Apple-tab-span"> </span>amp = <span class="s1">LFNoise1</span>.kr(10, 0.5, 0.5);</p>
84 <p class="p6"><span class="s3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// Impulse is needed to trigger the /tr message to be sent</p>
85 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">SendTrig</span>.kr(<span class="s1">Impulse</span>.kr(4), 0, freq);</p>
86 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">SendTrig</span>.kr(<span class="s1">Impulse</span>.kr(4), 1, amp);</p>
87 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">SinOsc</span>.ar(freq, 0, 0.3) ! 2</p>
88 <p class="p5">}.play;</p>
89 <p class="p7"><br></p>
90 <p class="p6"><span class="s3">o.remove;<span class="Apple-converted-space">  </span></span>// when done, you need to clean up the OSCresponderNode</p>
91 <p class="p7"><br></p>
92 <p class="p6"><span class="s3">l[0].array.plot<span class="Apple-tab-span"> </span></span>// view frequencies</p>
93 <p class="p5">l[1].array.plot<span class="Apple-tab-span"> </span><span class="s4">// view amps</span></p>
94 <p class="p2"><br></p>
95 <p class="p4"><b>Shared controls (Internal server only, control rate only)<span class="Apple-converted-space"> </span></b></p>
96 <p class="p2"><br></p>
97 <p class="p4">The internal server allocates a number of control buses whose memory addresses are shared with the client. The client can poll these buses without using OSC messages.<span class="Apple-converted-space"> </span></p>
98 <p class="p2"><br></p>
99 <p class="p4">Insert a SharedOut.kr UGen into your synthdef. Then, on the client side, use s.getSharedControl(num) to read the value. If you want to track the value over time, use a routine to poll repeatedly.</p>
100 <p class="p2"><br></p>
101 <p class="p5">{<span class="Apple-tab-span"> </span><span class="s1">var</span><span class="Apple-tab-span"> </span>freq;</p>
102 <p class="p5"><span class="Apple-tab-span"> </span>freq = <span class="s1">LFNoise1</span>.kr(2, 600, 800);</p>
103 <p class="p6"><span class="s3"><span class="Apple-tab-span"> </span></span><span class="s1">SharedOut</span><span class="s3">.kr(0, freq);<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// no need for Impulse here</p>
104 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">SinOsc</span>.ar(freq, 0, 0.3) ! 2</p>
105 <p class="p5">}.play;</p>
106 <p class="p7"><br></p>
107 <p class="p5">l = <span class="s1">List</span>.new;</p>
108 <p class="p5">r = fork { loop { l.add(s.getSharedControl(0)); 0.1.wait } };</p>
109 <p class="p5">r.stop;</p>
110 <p class="p6"><span class="s3">l.array.plot;<span class="Apple-converted-space">  </span></span>// to view the results graphically<span class="Apple-converted-space"> </span></p>
111 <p class="p2"><br></p>
112 <p class="p4"><b>Server-side trace<span class="Apple-converted-space"> </span></b></p>
113 <p class="p2"><br></p>
114 <p class="p4">The /n_trace message causes the server to print a list of all the UGens in the node as well as their input and output values.<span class="Apple-converted-space"> </span></p>
115 <p class="p2"><br></p>
116 <p class="p4">It takes some practice to read a synthdef trace, but it's the ultimate source of information when a synthdef is not behaving as expected. Signal flow can be identified by looking at the numbers at inputs and outputs. When a UGen's output feeds into another's input, the values will be the same at both ends.</p>
117 <p class="p2"><br></p>
118 <p class="p4">For a concrete example, let's look at a synthdef that doesn't work. The intent is to generate a detuned sawtooth wave and run it through a set of parallel resonant filters whose cut-off frequencies are modulating randomly. We run the synth and generate the trace (reproduced below). The trace comes out in monochrome; colors are used here to highlight signal flow.</p>
119 <p class="p2"><br></p>
120 <p class="p8">SynthDef<span class="s3">(</span><span class="s2">\resonz</span><span class="s3">, { </span>|freq = 440|</p>
121 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">var</span><span class="Apple-tab-span"> </span>sig, ffreq;</p>
122 <p class="p5"><span class="Apple-tab-span"> </span>sig = <span class="s1">Saw</span>.ar([freq, freq+1], 0.2);</p>
123 <p class="p5"><span class="Apple-tab-span"> </span>ffreq = <span class="s1">LFNoise1</span>.kr(2, 1, 0.5);</p>
124 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">Out</span>.ar(0, <span class="s1">Resonz</span>.ar(sig, (800, 1000..1800) * ffreq, 0.1))</p>
125 <p class="p5">}).send(s);</p>
126 <p class="p7"><br></p>
127 <p class="p5">a = <span class="s1">Synth</span>(<span class="s2">\resonz</span>);</p>
128 <p class="p5">a.trace;</p>
129 <p class="p5">a.free;</p>
130 <p class="p2"><br></p>
131 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>TRACE 1005<span class="Apple-converted-space">  </span>resonz<span class="Apple-converted-space">    </span>#units: 21</p>
132 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 0 Control</p>
133 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space"> </span></p>
134 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out 440</p>
135 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 1 BinaryOpUGen</p>
136 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>440 1</p>
137 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out 441</p>
138 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 2 Saw</p>
139 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>441</p>
140 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out 0.451348</p>
141 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 3 BinaryOpUGen</p>
142 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>0.451348 0.2</p>
143 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out 0.0902696</p>
144 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 4 Saw</p>
145 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>440</p>
146 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out -0.367307</p>
147 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 5 BinaryOpUGen</p>
148 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>-0.367307 0.2</p>
149 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out -0.0734615</p>
150 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 6 LFNoise1</p>
151 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>2</p>
152 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out -0.836168</p>
153 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 7 BinaryOpUGen</p>
154 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>-0.836168 0.5</p>
155 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out <span class="s5"><i>-0.336168</i></span></p>
156 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 8 BinaryOpUGen</p>
157 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>800 <span class="s5"><i>-0.336168</i></span></p>
158 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out <span class="s5"><i>-268.934</i></span></p>
159 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 9 Resonz</p>
160 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>-0.0734615 <span class="s5"><i>-268.934</i></span> 0.1</p>
161 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out <b>843934</b></p>
162 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 10 BinaryOpUGen</p>
163 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>1000 -0.336168</p>
164 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out -336.168</p>
165 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 11 Resonz</p>
166 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>0.0902696 <i>-336.168</i> 0.1</p>
167 <p class="p9"><span class="s3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out </span><b>3.02999e+08</b></p>
168 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 12 BinaryOpUGen</p>
169 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>1200 -0.336168</p>
170 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out -403.402</p>
171 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 13 Resonz</p>
172 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>-0.0734615 <i>-403.402</i> 0.1</p>
173 <p class="p10"><span class="s3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out </span><b>9.14995e+10</b></p>
174 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 14 BinaryOpUGen</p>
175 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>1400 -0.336168</p>
176 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out -470.635</p>
177 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 15 Resonz</p>
178 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>0.0902696 <i>-470.635</i> 0.1</p>
179 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out <span class="s6"><b>-5.42883</b></span></p>
180 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 16 BinaryOpUGen</p>
181 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>1600 -0.336168</p>
182 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out -537.869</p>
183 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 17 Resonz</p>
184 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>-0.0734615 <i>-537.869</i> 0.1</p>
185 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out <span class="s7"><b>515.506</b></span></p>
186 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 18 BinaryOpUGen</p>
187 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>1800 -0.336168</p>
188 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out -605.102</p>
189 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 19 Resonz</p>
190 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>0.0902696 <i>-605.102</i> 0.1</p>
191 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out <span class="s8"><b>32785.2</b></span></p>
192 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">  </span>unit 20 Out</p>
193 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>in<span class="Apple-converted-space">  </span>0 <b>843934 </b><span class="s9"><b>3.02999e+08</b></span><b> </b><span class="s10"><b>9.14995e+10</b></span><b> </b><span class="s6"><b>-5.42883</b></span><b> </b><span class="s7"><b>515.506</b></span><b> </b><span class="s8"><b>32785.2</b></span></p>
194 <p class="p4"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-converted-space">    </span>out<span class="Apple-converted-space"> </span></p>
195 <p class="p2"><br></p>
196 <p class="p4">Two problems leap out from the trace: first, there are six channels of the output (there should be 1), and second, all the outputs are well outside the audio range -1..1. The first is because we use multichannel expansion to produce an array of Resonz filters, but we don't mix them down into a single channel.<span class="Apple-converted-space"> </span></p>
197 <p class="p2"><br></p>
198 <p class="p4">The above trace uses colors to track the source of each output signal. Note that there are no out of range signals prior to each Resonz. Looking at the Resonz inputs, we see that the frequency input is negative, which will blow up most digital filters.<span class="Apple-converted-space"> </span></p>
199 <p class="p2"><br></p>
200 <p class="p4">The resonance frequency derives from multiplying an array by a LFNoise1. Tracing back (the red, italicized numbers), the LFNoise1 is outputting a negative number, where we expected it to be 0.5..1.5. But, the mul and add inputs are reversed!<span class="Apple-converted-space"> </span></p>
201 <p class="p2"><br></p>
202 <p class="p4">If you look very carefully at the trace, you will see another problem relating to multichannel expansion. The two components of the detuned sawtooth go into alternate Resonz'es, where we expected both to go, combined, into every Resonz. To fix it, the sawtooths need to be mixed as well.</p>
203 <p class="p2"><br></p>
204 <p class="p8">SynthDef<span class="s3">(</span><span class="s2">\resonz</span><span class="s3">, { </span>|freq = 440|</p>
205 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">var</span><span class="Apple-tab-span"> </span>sig, ffreq;</p>
206 <p class="p5"><span class="Apple-tab-span"> </span>sig = <span class="s1">Mix</span>.ar(<span class="s1">Saw</span>.ar([freq, freq+1], 0.2));</p>
207 <p class="p5"><span class="Apple-tab-span"> </span>ffreq = <span class="s1">LFNoise1</span>.kr(2, 0.5, 1);</p>
208 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">Out</span>.ar(0, <span class="s1">Mix</span>.ar(<span class="s1">Resonz</span>.ar(sig, (800, 1000..1800) * ffreq, 0.1)))</p>
209 <p class="p5">}).send(s);</p>
210 <p class="p7"><br></p>
211 <p class="p5">a = <span class="s1">Synth</span>(<span class="s2">\resonz</span>);</p>
212 <p class="p5">a.trace;</p>
213 <p class="p5">a.free;</p>
214 <p class="p7"><br></p>
215 <p class="p7"><br></p>
216 <p class="p3"><b>Debugging client-to-server communication</b></p>
217 <p class="p2"><br></p>
218 <p class="p4">Some bugs result from OSC messages to the server being constructed incorrectly. Julian Rohrhuber's DebugNetAddr is a convenient way to capture messages. The class may be downloaded from:</p>
219 <p class="p2"><br></p>
220 <p class="p4"><span class="s11">http://swiki.hfbk-hamburg.de:8888/MusicTechnology/710</span><span class="Apple-converted-space"> </span></p>
221 <p class="p2"><br></p>
222 <p class="p4">To use it, you need to quit the currently running local server, then create a new server using a DebugNetAddr instead of a regular NetAddr. Messages will be dumped into a new document window.</p>
223 <p class="p2"><br></p>
224 <p class="p5">s.quit;</p>
225 <p class="p7"><br></p>
226 <p class="p5"><span class="s1">Server</span>.default = s = <span class="s1">Server</span>.new(<span class="s2">'local-debug'</span>, <span class="s1">DebugNetAddr</span>(<span class="s12">"localhost"</span>, 57110));</p>
227 <p class="p5">s.boot;</p>
228 <p class="p5">s.makeWindow;<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s4">// optional</span></p>
229 <p class="p7"><br></p>
230 <p class="p5"><span class="Apple-tab-span"> </span>latency nil<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>// these messages get sent on bootup</p>
231 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>[ "/notify", 1 ]</p>
232 <p class="p7"><span class="Apple-tab-span"> </span></p>
233 <p class="p5"><span class="Apple-tab-span"> </span>latency nil</p>
234 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>[ "/g_new", 1 ]</p>
235 <p class="p7"><br></p>
236 <p class="p5">a = { <span class="s1">SinOsc</span>.ar(440, 0, 0.4) ! 2 }.play;</p>
237 <p class="p7"><br></p>
238 <p class="p5"><span class="Apple-tab-span"> </span>latency nil</p>
239 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>[ "/d_recv", "data[ 290 ]", [ 9, "-1589009783", 1001, 0, 1, 'i_out', 0, 'out', 0 ] ]</p>
240 <p class="p7"><br></p>
241 <p class="p5">a.free;</p>
242 <p class="p7"><br></p>
243 <p class="p5"><span class="Apple-tab-span"> </span>latency nil</p>
244 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>[ 11, 1001 ]</p>
245 <p class="p7"><br></p>
246 <p class="p3"><b>Debugging client code<span class="Apple-converted-space"> </span></b></p>
247 <p class="p2"><span class="Apple-converted-space"> </span></p>
248 <p class="p4">SuperCollider does not have a step trace function, which makes debugging on the client side tougher, but not impossible.<span class="Apple-converted-space"> </span></p>
249 <p class="p2"><br></p>
250 <p class="p4"><b>Errors</b><span class="Apple-converted-space"> </span></p>
251 <p class="p2"><br></p>
252 <p class="p4">Learning how to read SuperCollider error output is absolutely essential. Error dumps often (though not always) contain a great deal of information: what the action was, which objects are being acted upon, and how the flow of execution reached that point.</p>
253 <p class="p2"><br></p>
254 <p class="p4">See the <a href="Understanding-Errors.html"><span class="s13">Understanding-Errors</span></a> help file for a tutorial.<span class="Apple-converted-space"> </span></p>
255 <p class="p2"><br></p>
256 <p class="p4">There's also a graphic Inspector for error dumps, which is enabled with the following command:</p>
257 <p class="p2"><br></p>
258 <p class="p8">Exception<span class="s3">.debug = </span>true<span class="s3">;<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span><span class="s4">// enable</span></p>
259 <p class="p8">Exception<span class="s3">.debug = </span>false<span class="s3">;<span class="Apple-tab-span"> </span></span><span class="s4">// disable<span class="Apple-converted-space"> </span></span></p>
260 <p class="p2"><br></p>
261 <p class="p4">In most cases, this will give you more information than a regular error dump. Usually the regular error dump is sufficient. If you are using Environments or prototype-style programming, the graphic inspector is indispensable.</p>
262 <p class="p2"><br></p>
263 <p class="p4"><b>Debug output using post statements</b></p>
264 <p class="p2"><br></p>
265 <p class="p4">The most common approach is to insert statements to print the values of variables and expressions. Since the normal printing methods don't change the value of an expression, they can be placed in the middle of the statement without altering the processing flow. There's no significant difference between:</p>
266 <p class="p2"><br></p>
267 <p class="p5">if(a &gt; 0) { positive.value(a) };</p>
268 <p class="p2"><br></p>
269 <p class="p4">and</p>
270 <p class="p2"><br></p>
271 <p class="p5">if((a &gt; 0).postln) { positive.value(a) };<span class="Apple-converted-space"> </span></p>
272 <p class="p2"><br></p>
273 <p class="p4">Common methods to use are:<span class="Apple-converted-space"> </span></p>
274 <p class="p2"><br></p>
275 <p class="p4">.postln</p>
276 <p class="p11"><span class="s3">.postcs<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// post the object as a compile string</p>
277 <p class="p11"><span class="s3">.debug(caller)<span class="Apple-tab-span"> </span></span>// post the object along with a tag identifying the caller</p>
278 <p class="p2"><br></p>
279 <p class="p4">.debug is defined in the crucial library, so Linux and Windows users may not have access to it. It's used like this:</p>
280 <p class="p2"><br></p>
281 <p class="p5">(</p>
282 <p class="p5"><span class="s1">var</span><span class="Apple-tab-span"> </span>positiveFunc;</p>
283 <p class="p5">positiveFunc = { <span class="s1">|a|</span></p>
284 <p class="p12"><span class="s3"><span class="Apple-tab-span"> </span>a.debug(</span>'positiveFunc-arg a'<span class="s3">);</span></p>
285 <p class="p5"><span class="Apple-tab-span"> </span>a*10</p>
286 <p class="p5">};</p>
287 <p class="p5">a = 5;</p>
288 <p class="p5">if (a &gt; 0) { positiveFunc.value(a) };</p>
289 <p class="p5">)</p>
290 <p class="p7"><br></p>
291 <p class="p5">// output:</p>
292 <p class="p5">positiveFunc-arg a: 5</p>
293 <p class="p5">50</p>
294 <p class="p2"><br></p>
295 <p class="p4">The caller argument is optional; however, it's very helpful for tracing the origin of erroneous values.<span class="Apple-converted-space"> </span></p>
296 <p class="p2"><br></p>
297 <p class="p4">Another advantage of .debug is that it's easier to search for debug calls and differentiate them from legitimate postln and postcs calls.</p>
298 <p class="p2"><br></p>
299 <p class="p4">To print multiple values at one time, wrap them in an array before using .debug or .postcs. Note that if any of the array members are collections, postln will hide them behind the class name: "an Array, a Dictionary" etc. Use postcs if you expect to be posting collections.</p>
300 <p class="p2"><br></p>
301 <p class="p6"><span class="s3">[val1, val2, val3].debug(</span><span class="s2">\myMethod</span><span class="s3">);<span class="Apple-tab-span"> </span></span>// or, for a non-Crucial way:</p>
302 <p class="p5">[<span class="s2">\callerTag</span>, val1, val2, val3].postcs;</p>
303 <p class="p2"><br></p>
304 <p class="p4">By sprinkling these throughout your code, especially at the beginnings of functions or methods, the debugging output can give you a partial trace of which code blocks get visited in what order.</p>
305 <p class="p2"><br></p>
306 <p class="p4"><b>dumpBackTrace</b></p>
307 <p class="p2"><br></p>
308 <p class="p4">If you discover that a particular method or function is being entered but you don't know how it got there, you can use the .dumpBackTrace method on any object. You'll get what looks like an error dump, but without the error. Execution continues normally after the stack dump.</p>
309 <p class="p2"><br></p>
310 <p class="p8">(</p>
311 <p class="p5"><span class="s1">var</span><span class="Apple-tab-span"> </span>positiveFunc;</p>
312 <p class="p5">positiveFunc = { <span class="s1">|a|</span></p>
313 <p class="p12"><span class="s3"><span class="Apple-tab-span"> </span>a.debug(</span>'positiveFunc-arg a'<span class="s3">);</span></p>
314 <p class="p5"><span class="Apple-tab-span"> </span>a.dumpBackTrace;</p>
315 <p class="p5"><span class="Apple-tab-span"> </span>a*10</p>
316 <p class="p5">};</p>
317 <p class="p5">a = 5;</p>
318 <p class="p5">if (a &gt; 0) { positiveFunc.value(a) };</p>
319 <p class="p5">)</p>
320 <p class="p7"><br></p>
321 <p class="p5">// output:</p>
322 <p class="p5">positiveFunc-arg a: 5</p>
323 <p class="p5">CALL STACK:</p>
324 <p class="p5"><span class="Apple-tab-span"> </span>&lt; FunctionDef in closed FunctionDef &gt;</p>
325 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>arg a = 5</p>
326 <p class="p5"><span class="Apple-tab-span"> </span>&lt; closed FunctionDef &gt;</p>
327 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>var positiveFunc = &lt;instance of Function&gt;</p>
328 <p class="p5"><span class="Apple-tab-span"> </span>Interpreter-interpretPrintCmdLine</p>
329 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>arg this = &lt;instance of Interpreter&gt;</p>
330 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>var res = nil</p>
331 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>var func = &lt;instance of Function&gt;</p>
332 <p class="p5"><span class="Apple-tab-span"> </span>Process-interpretPrintCmdLine</p>
333 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>arg this = &lt;instance of Main&gt;</p>
334 <p class="p5">50</p>
335 <p class="p2"><br></p>
336 <p class="p4">This tells you that the function came from interpreting a closed FunctionDef (automatically created when evaluating a block of code).</p>
337 <p class="p2"><br></p>
338 <p class="p4">In a method definition, it's recommended to use "this.dumpBackTrace"; in a free-standing function, there is no "this" so you should pick some arbitrary object.</p>
339 <p class="p2"><br></p>
340 <p class="p4"><b>Tracing streams</b></p>
341 <p class="p2"><br></p>
342 <p class="p4">To see the results of a pattern, use the .trace method. Each output value from the pattern gets posted to the main output.</p>
343 <p class="p2"><br></p>
344 <p class="p5">s.boot;</p>
345 <p class="p5"><span class="s1">SynthDescLib</span>.global.read;</p>
346 <p class="p7"><br></p>
347 <p class="p5">p = <span class="s1">Pbind</span>(<span class="s2">\degree</span>, <span class="s1">Pwalk</span>((0..14), <span class="s1">Pstutter</span>(<span class="s1">Pwhite</span>(1, 4, <span class="s1">inf</span>), <span class="s1">Prand</span>(#[-2, -1, 1, 2], <span class="s1">inf</span>)), <span class="s1">Pseq</span>(#[-1, 1], <span class="s1">inf</span>), 0), <span class="s2">\delta</span>, 0.25, <span class="s2">\sustain</span>, 0.2, <span class="s2">\instrument</span>, <span class="s2">\default</span>).trace.play;</p>
348 <p class="p7"><br></p>
349 <p class="p5">p.stop;</p>
350 <p class="p2"><br></p>
351 <p class="p4"><b>Debugging infinite loops or recursion</b></p>
352 <p class="p2"><br></p>
353 <p class="p5">while(<span class="s1">true</span>);<span class="Apple-converted-space"> </span></p>
354 <p class="p2"><br></p>
355 <p class="p4">This is a bad idea. It will lock up SuperCollider and you will have to force quit. Sometimes this happens in your code and the reason isn't obvious. Debugging these situations is very painful because you might have to force quit, relaunch SuperCollider, and reload your code just to try again.<span class="Apple-converted-space"> </span></p>
356 <p class="p2"><br></p>
357 <p class="p5">f = { <span class="s1">|func|</span> func.value(func) };</p>
358 <p class="p5">f.value(f);<span class="Apple-converted-space"> </span></p>
359 <p class="p2"><br></p>
360 <p class="p4">Infinite recursion, on the other hand, is more likely to cause SuperCollider to quit unexpectedly when the execution stack runs out of space.</p>
361 <p class="p2"><br></p>
362 <p class="p4">In Mac OS X, inserting "post" or "debug" calls will not help with infinite loops or recursion, because posted output is held in a buffer until execution is complete. If execution never completes, you never see the output.<span class="Apple-converted-space"> </span></p>
363 <p class="p2"><br></p>
364 <p class="p4">One useful approach is to insert statements that will cause execution to halt. The easiest is .halt, but it provides you with no information about where or how it stopped, or how it got there. If you want a more descriptive message, make up an error and throw it:</p>
365 <p class="p2"><br></p>
366 <p class="p13"><span class="s1">Error</span><span class="s3">(</span>"myFunction-halt"<span class="s3">).throw;<span class="Apple-converted-space"> </span></span></p>
367 <p class="p2"><br></p>
368 <p class="p4">When debugging code that crashes, place a line like this somewhere in the code. If you get the error output, you know that the infinite loop is happening after the error--so move the error.throw later and try again. If it crashes, you know the infinite loop is earlier. Eventually, after a lot of heartache, you can zero in on the location.<span class="Apple-converted-space"> </span></p>
369 <p class="p2"><br></p>
370 <p class="p4">Here is a rogues' gallery of infinite loop gotchas--things that don't look like infinite loops, but they will kill your code quicker than you can wish you hadn't just pushed the enter key:</p>
371 <p class="p2"><br></p>
372 <p class="p5">i = 0;</p>
373 <p class="p5">while (i &lt; 10) { i.postln; i = i+1 }; <span class="Apple-tab-span"> </span><span class="s4">// crash</span></p>
374 <p class="p2"><br></p>
375 <p class="p4">While loop syntax is different in SuperCollider from C. The above loop means to check whether i &lt; 10 once, at the beginning of the loop, then loop if the value is true. Since the loop condition is evaluated only once, it never changes, so the loop never stops. The loop condition should be written inside a function, to wit:</p>
376 <p class="p2"><br></p>
377 <p class="p5">i = 0;</p>
378 <p class="p5">while { i &lt; 10 } { i.postln; i = i+1 };</p>
379 <p class="p2"><br></p>
380 <p class="p4">Routines and empty arrays:</p>
381 <p class="p2"><br></p>
382 <p class="p5">a = <span class="s1">Array</span>.new;</p>
383 <p class="p8"><span class="s3">r = </span>Routine<span class="s3">({</span></p>
384 <p class="p5"><span class="Apple-tab-span"> </span>loop {</p>
385 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>a.do({ <span class="s1">|item|</span> item.yield });</p>
386 <p class="p5"><span class="Apple-tab-span"> </span>}</p>
387 <p class="p5">});<span class="Apple-converted-space"> </span></p>
388 <p class="p5">r.next;<span class="Apple-tab-span"> </span><span class="s4">// crash</span></p>
389 <p class="p2"><br></p>
390 <p class="p4">This looks pretty innocent: iterate repeatedly over an array and yield each item successively. But, if the array is empty, the do loop never executes and yield never gets called. So, the outer loop{} runs forever, doing nothing.<span class="Apple-converted-space"> </span></p>
391 <p class="p2"><br></p>
392 <p class="p4">Recursion is often used to walk through a tree structure. Tree structures are usually finite--no matter which branch you go down, eventually you will reach the end. If you have a data structure that is self-referential, you can easily get infinite recursion:</p>
393 <p class="p2"><br></p>
394 <p class="p5">a = (1..10);</p>
395 <p class="p6"><span class="s3">a.put(5, a);<span class="Apple-tab-span"> </span></span>// now one of the items of a is a itself</p>
396 <p class="p6"><span class="s3">a.postcs;<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// crash--postcs has to walk through the entire collection, which loops on itself<span class="Apple-converted-space"> </span></p>
397 <p class="p2"><br></p>
398 <p class="p4">Self-referential data structures are sometimes an indication of poor design. If this is the case, avoid them.</p>
399 <p class="p2"><br></p>
400 <p class="p5">a = 0;</p>
401 <p class="p6"><span class="s1">SystemClock</span><span class="s3">.sched(2, { a.postln });<span class="Apple-tab-span"> </span></span>// crashes when scheduler fires the function</p>
402 <p class="p2"><br></p>
403 <p class="p4">When a scheduled function executes, if it returns a number, the function will be rescheduled for now + the number. If the number is 0, it is effectively the same as an infinite loop.</p>
404 <p class="p2"><br></p>
405 <p class="p4">To fix it, make sure the function returns a non-number.</p>
406 <p class="p2"><br></p>
407 <p class="p5">a = 0;</p>
408 <p class="p5"><span class="s1">SystemClock</span>.sched(2, { a.postln; <span class="s1">nil</span> });</p>
409 <p class="p2"><br></p>
410 <p class="p4"><b>Removing debugging statements</b></p>
411 <p class="p2"><br></p>
412 <p class="p4">Use formatting to help your eye locate debugging statements when it's time to remove them. SuperCollider code is usually indented. If you write your debugging statements fully left-justified, they're much easier to see.</p>
413 <p class="p2"><br></p>
414 <p class="p5">a = <span class="s1">Array</span>.new;</p>
415 <p class="p8"><span class="s3">r = </span>Routine<span class="s3">({</span></p>
416 <p class="p5"><span class="Apple-tab-span"> </span>loop {</p>
417 <p class="p6"><span class="s3"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span><span class="s12">"debugging"</span><span class="s3">.postln;<span class="Apple-tab-span"> </span></span>// looks like regular code, doesn't stand out</p>
418 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>a.do({ <span class="s1">|item|</span> item.yield });</p>
419 <p class="p5"><span class="Apple-tab-span"> </span>}</p>
420 <p class="p5">});<span class="Apple-converted-space"> </span></p>
421 <p class="p5">r.next;<span class="Apple-tab-span"> </span><span class="s4">// crash</span></p>
422 <p class="p7"><br></p>
423 <p class="p6">// vs:</p>
424 <p class="p7"><br></p>
425 <p class="p5">a = <span class="s1">Array</span>.new;</p>
426 <p class="p8"><span class="s3">r = </span>Routine<span class="s3">({</span></p>
427 <p class="p5"><span class="Apple-tab-span"> </span>loop {</p>
428 <p class="p6"><span class="s12">"debugging"</span><span class="s3">.postln;<span class="Apple-tab-span"> </span></span>// this obviously sticks out</p>
429 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>a.do({ <span class="s1">|item|</span> item.yield });</p>
430 <p class="p5"><span class="Apple-tab-span"> </span>}</p>
431 <p class="p5">});<span class="Apple-converted-space"> </span></p>
432 <p class="p5">r.next;<span class="Apple-tab-span"> </span><span class="s4">// crash</span></p>
433 </body>
434 </html>