2 summary:: Getting Started With SuperCollider
3 categories:: Tutorials>Getting-Started
4 related:: Tutorials/Getting-Started/00-Getting-Started-With-SC
6 Now a little bit more about busses on the server. Busses are named after the busses or sends in analog mixing desks, and they serve a similar purpose: Routing signals from one place to another. In SC this means to or from the audio hardware, or between different synths. They come in two types: audio rate and control rate. As you've probably guessed, the former routes audio rate signals and the latter routes control rate signals.
8 The control rate busses are fairly simple to understand, each one has an index number, starting from 0.
10 Audio rate busses are similar, but require slightly more explanation. A server app will have a certain number of output and input channels. These correspond to the first audio busses, with outputs coming before inputs.
12 For example, if we imagine a server with two output channels and two input channels (i.e. stereo in and out) then the first two audio busses (index 0 and index 1) will be the outputs, and the two immediately following those (index 2 and index 3) will be the inputs. Writing audio out to one of the output busses will result in sound being played from your speakers, and reading audio in from the input busses will get sound into SC for things like recording and processing (providing you have a source such as a microphone connected to your computer's or audio interface's inputs).
14 The remaining audio busses will be 'private'. These are used simply to send audio and control signals between various synths. Sending audio to a private bus will not result in sound in your speakers unless you reroute it later to one of the output busses. These 'private' busses are often used for things like an 'effects send', i.e. something that requires further processing before it's output.
16 The number of control and audio busses available, as well as the number of input and output channels is set at the time the server app is booted. (See link::Classes/ServerOptions:: for information on how to set the number of input and output channels, and busses.)
18 section::Writing to or Reading from Busses
20 We've already seen Out.ar, which allows you to write (i.e. play out) audio to a bus. Recall that it has two arguments, an index, and an output, which can be an array of UGens (i.e. a multichannel output) or a single UGen.
22 To read in from a bus you use another UGen: In. In's 'ar' method also takes two arguments: An index, and the number of channels to read in. If the number of channels is greater than one, than In's output will be an Array. Execute the following examples, and watch the post window:
25 In.ar(0, 1); // this will return 'an OutputProxy'
26 In.ar(0, 4); // this will return an Array of 4 OutputProxies
29 An OutputProxy is a special kind of UGen that acts as a placeholder for some signal that will be present when the synth is running. You'll probably never need to deal with one directly, so don't worry about them, just understand what they are so that you'll recognise them when you see them in the post window and elsewhere.
31 In and Out also have 'kr' methods, which will read and write control rate signals to and from control rate busses. Note that Out.kr will convert an audio rate signal to control rate (this is called 'downsampling'), but that the reverse is not true: Out.ar needs an audio rate signal as its second arg.
34 // This throws an error. Can't write a control rate signal to an audio rate bus
35 {Out.ar(0, SinOsc.kr)}.play;
37 // This will work as the audio rate signal is downsampled to control rate
39 {Out.kr(0, SinOsc.ar)}.scope;
42 (This limitation is not universal amongst audio rate UGens however, and most will accept control rate signals for some or all of their arguments. Some will even convert control rate inputs to audio rate if needed, filling in the extra values through a process called interpolation.)
44 You'll note that when multiple Synths write to the same bus, there output is summed, or in other words, mixed.
48 SynthDef("tutorial-args", { arg freq = 440, out = 0;
49 Out.ar(out, SinOsc.ar(freq, 0, 0.2));
52 // both write to bus 1, and their output is mixed
53 x = Synth("tutorial-args", ["out", 1, "freq", 660]);
54 y = Synth("tutorial-args", ["out", 1, "freq", 770]);
57 section::Creating a Bus Object
59 There is a handy client-side object to represent server busses: Bus. Given that all you need is an In or Out Ugen and an index to write to a bus, you might wonder what one would need a full-fledged Bus object for. Well, much of the time you don't, particularly if all you're doing is playing audio in and out. But Bus does provide some useful functionality. We'll get to that in a second, but first lets look at how to make one.
61 Just as many UGens have ar and kr methods, Bus has two commonly used creation methods: Bus-audio and Bus-control. These each take two arguments: a Server object, and the number of channels.
64 b = Bus.control(s, 2); // Get a two channel control Bus
65 c = Bus.audio(s); // Get a one channel private audio Bus (one is the default)
68 You may be wondering what a 'two channel' bus is, since we haven't mentioned these before. You should recall that when Out has an Array as its second argument it will write the channels of the Array to consecutive busses. Recall this example from link::Tutorials/Getting-Started/10-SynthDefs-and-Synths:: :
72 SynthDef.new("tutorial-SinOsc-stereo", { var outArray;
73 outArray = [SinOsc.ar(440, 0, 0.2), SinOsc.ar(442, 0, 0.2)];
74 Out.ar(0, outArray); // writes to busses 0 and 1
79 The truth is that there aren't multichannel busses per se, but Bus objects are able to represent a series of busses with consecutive indices. Then emphasis::encapsulate:: several adjacent sever-side busses into a single Bus object, allowing you to treat them as a group. This turns out to be rather handy.
81 When you're working with so-called 'private' busses (i.e. anything besides the input and output channels; all control busses are 'private') you generally want to make sure that that bus is only used for exactly what you want. The point after all is to keep things separate. You could do this by carefully considering which indices to use, but Bus allows for this to be done automatically. Each Server object has a bus allocator, and when you make a Bus object, it reserves those private indices, and will not give them out again until freed. You can find out the index of a Bus by using its 'index' method. Normally however, you will not need to store this value, as instances of Bus can be passed directly as UGen inputs or Synth args.
84 s.reboot; // this will restart the server app and thus reset the bus allocators
86 b = Bus.control(s, 2); // a 2 channel control Bus
87 b.index; // this should be zero
88 b.numChannels // Bus also has a numChannels method
90 c.numChannels; // the default number of channels is 1
91 c.index; // note that this is 2; b uses 0 and 1
94 So by using Bus objects to represent adjacent busses, you can guarantee that there won't be a conflict. Since the indices are allocated dyamically, you can change the number of channels of a Bus in your code (for instance because you now need to route a multichannel signal), and you're still guaranteed to be safe. If you were simply 'hard allocating' busses by using index numbers, you might have to adjust them all to make room for an extra adjacent channel, since the indices need to be consecutive! This is a good example of the power of objects: By encapsulating things like index allocation, and providing a emphasis::layer of abstraction::, they can make your code more flexible.
96 You can free up the indices used by a Bus by calling its 'free' method. This allows them to be reallocated.
99 b = Bus.control(s, 2);
100 b.free; // free the indices. You can't use this Bus object after that
103 Note that this doesn't actually make the bus on the server go away, it's still there. 'free' just lets the allocator know that you're done using this bus for the moment, and it can freely reallocate its index.
105 Now here's another advantage when working with private audio rate busses. As we said above, the first few busses are the output and input channels. So if we want to use the first private bus, all we need to do is add those together, right? Consider our server app with 2 output and 2 input channels. The first private audio bus is index 4. (0, 1, 2, 3 ... 4!) So we write our code, and give the appropriate Out UGen 4 as its index arg.
107 But what happens if we later decide to change the number of output channels to 6? Now everything that was written to our private bus is going out one of the output channels! A Server's audio bus allocator will only assign private indices, so if you change the number of input or output channels it will take this into account when you execute your code. Again this makes your code more flexible.
109 section::Busses in Action
111 So here are two examples using busses. The first is with a control rate bus.
115 SynthDef("tutorial-Infreq", { arg bus, freqOffset = 0;
116 // this will add freqOffset to whatever is read in from the bus
117 Out.ar(0, SinOsc.ar(In.kr(bus) + freqOffset, 0, 0.5));
120 SynthDef("tutorial-Outfreq", { arg freq = 400, bus;
121 Out.kr(bus, SinOsc.kr(1, 0, freq/40, freq));
124 b = Bus.control(s,1);
128 x = Synth.new("tutorial-Outfreq", [\bus, b]);
129 y = Synth.after(x, "tutorial-Infreq", [\bus, b]);
130 z = Synth.after(x, "tutorial-Infreq", [\bus, b, \freqOffset, 200]);
132 x.free; y.free; z.free; b.free;
135 Both y and z read from the same bus, the latter just modifies the frequency control signal by adding a constant value of 200 to it. This is more efficient than having two separate control oscillators to control frequency. This sort of strategy of connecting together synths, each of which does different things in a larger process, can be very effective in SC.
137 Now an example with an audio bus. This is the most complicated example we've seen so far, but should give you some idea of how to start putting all the things we've learned together. The code below will use two Synths as sources, one creating pulses of PinkNoise (a kind of Noise which has less energy at high frequencies than at low), and another creating pulses of Sine Waves. The pulses are created using the UGens link::Classes/Impulse:: and link::Classes/Decay2::. These are then reverberated using a chain of link::Classes/AllpassC::, which is a kind of delay.
139 Note the construction 16.do({ ... }), below. This makes the chain by evaluating the function 16 times. This is a very powerful and flexible technique, as by simply changing the number, I can change the number of evaluations. See link::Classes/Integer:: for more info on Integer-do.
143 // the arg direct will control the proportion of direct to processed signal
144 SynthDef("tutorial-DecayPink", { arg outBus = 0, effectBus, direct = 0.5;
146 // Decaying pulses of PinkNoise. We'll add reverb later.
147 source = Decay2.ar(Impulse.ar(1, 0.25), 0.01, 0.2, PinkNoise.ar);
148 // this will be our main output
149 Out.ar(outBus, source * direct);
150 // this will be our effects output
151 Out.ar(effectBus, source * (1 - direct));
154 SynthDef("tutorial-DecaySin", { arg outBus = 0, effectBus, direct = 0.5;
156 // Decaying pulses of a modulating Sine wave. We'll add reverb later.
157 source = Decay2.ar(Impulse.ar(0.3, 0.25), 0.3, 1, SinOsc.ar(SinOsc.kr(0.2, 0, 110, 440)));
158 // this will be our main output
159 Out.ar(outBus, source * direct);
160 // this will be our effects output
161 Out.ar(effectBus, source * (1 - direct));
164 SynthDef("tutorial-Reverb", { arg outBus = 0, inBus;
166 input = In.ar(inBus, 1);
169 // aNumber.do will evaluate it's function argument a corresponding number of times
170 // {}.dup(n) will evaluate the function n times, and return an Array of the results
171 // The default for n is 2, so this makes a stereo reverb
172 16.do({ input = AllpassC.ar(input, 0.04, { Rand(0.001,0.04) }.dup, 3)});
174 Out.ar(outBus, input);
177 b = Bus.audio(s,1); // this will be our effects bus
181 x = Synth.new("tutorial-Reverb", [\inBus, b]);
182 y = Synth.before(x, "tutorial-DecayPink", [\effectBus, b]);
183 z = Synth.before(x, "tutorial-DecaySin", [\effectBus, b, \outBus, 1]);
186 // Change the balance of wet to dry
187 y.set(\direct, 1); // only direct PinkNoise
188 z.set(\direct, 1); // only direct Sine wave
189 y.set(\direct, 0); // only reverberated PinkNoise
190 z.set(\direct, 0); // only reverberated Sine wave
191 x.free; y.free; z.free; b.free;
194 Note that we could easily have many more source synths being processed by the single reverb synth. If we'd built the reverb into the source synths we'd be duplicating effort. But by using a private bus, we're able to be more efficient.
196 section::More Fun with Control Busses
198 There are some other powerful things that you can do with control rate busses. For instance, you can map any arg in a running synth to read from a control bus. This means you don't need an In UGen. You can also write constant values to control busses using Bus' 'set' method, and poll values using its 'get' method.
202 // make two control rate busses and set their values to 880 and 884.
203 b = Bus.control(s, 1); b.set(880);
204 c = Bus.control(s, 1); c.set(884);
205 // and make a synth with two frequency arguments
206 x = SynthDef("tutorial-map", { arg freq1 = 440, freq2 = 440;
207 Out.ar(0, SinOsc.ar([freq1, freq2], 0, 0.1));
210 // Now map freq1 and freq2 to read from the two busses
211 x.map(\freq1, b, \freq2, c);
213 // Now make a Synth to write to the one of the busses
214 y = {Out.kr(b, SinOsc.kr(1, 0, 50, 880))}.play(addAction: \addToHead);
216 // free y, and b holds its last value
219 // use Bus-get to see what the value is. Watch the post window
220 b.get({ arg val; val.postln; f = val; });
222 // set the freq2, this 'unmaps' it from c
223 x.set(\freq2, f / 2);
225 // freq2 is no longer mapped, so setting c to a different value has no effect
228 x.free; b.free; c.free;
231 Note that unlike audio rate busses, control rate busses hold their last value until something new is written.
233 Also note that Bus-get takes a Function (called an action function) as an argument. This is because it takes a small amount of time for the server to get the reply and send it back. The function, which is passed the value (or Array of values in the case of a multichannel bus) as an argument, allows you to do something with the value once its come back.
235 This concept of things taking a small amount of time to respond (usually called emphasis::latency::) is quite important to understand. There are a number of other methods in SC which function this way, and it can cause you problems if you're not careful. To illustrate this consider the example below.
238 // make a Bus object and set its values
239 b = Bus.control(s, 1); b.set(880);
241 // execute this altogether
243 f = nil; // just to be sure
244 b.get({ arg val; f = val; });
248 // f equals nil, but try it again and it's as we expected!
252 So why was f nil the first time but not the second time? The part of the language app which executes your code (called the emphasis::interpreter::), does what you tell it, as fast as it can, when you tell it to. So in the block of code between the parentheses above it sends the 'get' message to the server, schedules the Function to execute when a reply is received, and then moves on to posting f. Since it hasn't received the reply yet f is still nil when it's posted the first time.
254 It only takes a tiny amount of time for the server to send a reply, so by the time we get around to executing the last line of code f has been set to 880, as we expected. In the previous example this wasn't a problem, as we were only executing a line at a time. But there will be cases where you will need to execute things as a block, and the action function technique is very useful for that.
256 section::Getting it all in the Right Order
258 In the examples above, you may have wondered about things like Synth.after, and addAction: \addToHead. During each cycle (the period in which a block of samples is calculated) the server calculates things in a particular order, according to its list of running synths.
260 It starts with the first synth in its list, and calculates a block of samples for its first UGen. It then takes that and calculates a block of samples for each of its remaining UGens in turn (any of which may take the output of an earlier UGen as an input.) This synth's output is written to a bus or busses, as the case may be. The server then moves on to the next synth in its list, and the process repeats, until all running synths have calculated a block of samples. At this point the server can move on to the next cycle.
262 The important thing to understand is that as a emphasis::general rule::, when you are connecting synths together using busses it is important that synths which write signals to busses are earlier in the server's order than synths which read those signals from those busses. For instance in the audio bus example above it was important that the 'reverb' synth is calculated after the noise and sine wave synths that it processes.
264 This is a complicated topic, and there are some exceptions to this, but you should be aware that ordering is crucial when interconnecting synths. The file link::Guides/Order-of-execution:: covers this topic in greater detail.
266 Synth-new has two arguments which allow you to specify where in the order a synth is added. The first is a emphasis:: target::, and the second is an emphasis:: addAction::. The latter specifies the new synth's position in relation to the target.
269 x = Synth("default", [\freq, 300]);
270 // add a second synth immediately after x
271 y = Synth("default", [\freq, 450], x, \addAfter);
275 A target can be another Synth (or some other things; more on that soon), and an addAction is a symbol. See link::Classes/Synth:: for a complete list of possible addActions.
277 Methods like Synth-after are simply convenient ways of doing the same thing, the difference being that they take a target as their first argument.
280 // These two lines of code are equivalent
281 y = Synth.new("default", [\freq, 450], x, \addAfter);
282 y = Synth.after(x, "default", [\freq, 450]);
285 For more information see:
287 link::Classes/Bus::, link::Classes/In::, link::Classes/OutputProxy::, link::Guides/Order-of-execution::, link::Classes/Synth::
289 section::Suggested Exercise
291 Experiment with interconnecting different synths using audio and control busses. When doing so be mindful of their ordering on the server.
295 This document is part of the tutorial strong::Getting Started With SuperCollider::.
297 Click here to go on to the next section: link::Tutorials/Getting-Started/12-Groups::
299 Click here to return to the table of Contents: link::Tutorials/Getting-Started/00-Getting-Started-With-SC::