supernova: fix for small audio vector sizes
[supercollider.git] / HelpSource / Tutorials / Getting-Started / 12-Groups.schelp
blob5de307974b99f84dbaefa7a32deea1e4e6d8fd1a
1 title:: 12. Groups
2 summary:: Getting Started With SuperCollider
3 categories:: Tutorials>Getting-Started
4 related:: Tutorials/Getting-Started/00-Getting-Started-With-SC
6 Our discussion about the order of synths on the server brings us to the topic of groups. Synths on the server are a type of what are called emphasis::nodes::. There's one other type of node: groups. Groups are simply collections of nodes, and can contain synths, other groups, or combinations of both. They are mostly useful in two ways: First they are very helpful in controlling order, second, they allow you to easily group together nodes and send them messages all at once. As you've probably guessed, there's a handy Server abstraction object to represent group nodes in the client app: Group.
8 section::Groups as Ordering Tools
10 Groups can be quite helpful in terms of controlling order. Like synths they take targets and addActions as arguments, which makes it easy to put them in position.
12 code::
13 g = Group.new;
14 h = Group.before(g);
15 g.free; h.free;
18 This can be very helpful for things like keeping effects or processing separate from sound sources, and in the right order. Let's reconsider our reverb example from the previous section.
20 code::
22 // a stereo version
23 SynthDef(\tutorial_DecaySin2, { arg outBus = 0, effectBus, direct = 0.5, freq = 440;
24         var source;
25         // 1.0.rand2 returns a random number from -1 to 1, used here for a random pan
26         source = Pan2.ar(Decay2.ar(Impulse.ar(Rand(0.3, 1), 0, 0.125), 0.3, 1,
27                 SinOsc.ar(SinOsc.kr(0.2, 0, 110, freq))), Rand(-1.0, 1.0));
28         Out.ar(outBus, source * direct);
29         Out.ar(effectBus, source * (1 - direct));
30 }).send(s);
32 SynthDef(\tutorial_Reverb2, { arg outBus = 0, inBus;
33         var input;
34         input = In.ar(inBus, 2);
35         16.do({ input = AllpassC.ar(input, 0.04, Rand(0.001,0.04), 3)});
36         Out.ar(outBus, input);
37 }).send(s);
40 // now we create groups for effects and synths
42 ~sources = Group.new;
43 ~effects = Group.after(~sources);       // make sure it's after
44 ~bus = Bus.audio(s, 2);                 // this will be our stereo effects bus
47 // now synths in the groups. The default addAction is \addToHead
49 x = Synth(\tutorial_Reverb2, [\inBus, b], ~effects);
50 y = Synth(\tutorial_DecaySin2, [\effectBus, ~bus, \outBus, 0], ~sources);
51 z = Synth(\tutorial_DecaySin2, [\effectBus, ~bus, \outBus, 0, \freq, 660], ~sources);
54 // we could add other source and effects synths here
56 ~sources.free; ~effects.free; // this frees their contents (x, y, z) as well
57 ~bus.free;
59 // remove references to ~sources and ~effects environment variables:
60 currentEnvironment.clear;
63 Note that we probably don't care what order the sources and effects are within the groups, all that matters is that all effects synths come after the source synths that they process.
65 If you're wondering about the names '~sources' and '~effects', placing a tilde (~) in front of a word is a way of creating an emphasis::environment:: variable. For the moment, all you need to know about them is that they can be used in the same way as interpreter variables (you don't need to declare them, and they are persistent), and they allow for more descriptive names. You should consider using strong::variable definitions:: and link::Classes/Function::s wherever no later direct access is needed - a large number of environment variables may cause bugs that are hard to find. Remember to strong::clear:: the currentEnvironment (see above) to avoid interference.
67 code::
68 // to be sure, create a new Environment:
69 Environment.new.push;
71 // some code..
73 // restore old environment
74 currentEnvironment.pop;
77 section::All the addActions
79 At this point it's probably good to cover the remaining add actions. In addition to \addBefore and \addAfter, there is also the (rarely) used \addReplace, and two add actions which apply to Groups: \addToHead and \addToTail. The former adds the receiver to the beginning of the group, so that it will execute first, the latter to the end of the group, so that it will execute last. Like the other addActions, \addToHead and \addToTail have convenience methods called 'head' and 'tail'.
81 code::
82 g = Group.new;
83 h = Group.head(g);              // add h to the head of g
84 x = Synth.tail(h, \default);    // add x to the tail of h
85 s.queryAllNodes;                // this will post a representation of the node hierarchy
86 x.free; h.free; g.free;
89 section::'queryAllNodes' and node IDs
91 Server has a method called 'queryAllNodes' which will post a representation of the server's node tree. You should have seen something like the following in the post window when executing the example above:
93 code::
94 nodes on localhost:
95 a Server
96 Group(0)
97         Group(1)
98                 Group(1000)
99                         Group(1001)
100                                 Synth 1002
103 When you see a Group printed here, anything below it and indented to the right is contained within it. The order of nodes is from top to bottom. The numbers you see are what are called node IDs, which are how the server keeps track of nodes. Normally when working with Server abstraction objects you won't need to deal with node IDs as the objects keep track of them, assigning and freeing them when appropriate.
105 You may have been wondering why there were four groups posted above when we only created two. The first two, with the IDs 0 and 1, are special groups, called the RootNode and the 'default group'.
107 section::The Root Node and the Default Group
109 When a server app is booted there is a special group created with a node ID of 0. This represents the top of the server's node tree. There is a special server abstraction object to represent this, called RootNode. In addition there is another group created with an ID of 1, called the default group. This is the default target for all Nodes and is what you will get if you supply a Server as a target. If you don't specify a target or pass in nil, you will get the default group of the default Server.
111 code::
112 Server.default.boot;
113 a = Synth.new(\default); // creates a synth in the default group of the default Server
114 a.group; // Returns a Group object. Note the ID of 1 (the default group) in the post window
117 The default group serves an important purpose: It provides a predictable basic Node tree so that methods such as Server-scope and Server-record (which create nodes which emphasis::must:: come after everything else) can function without running into order of execution problems. In the example below the scoping node will come after the default group.
119 code::
120 Server.internal.boot;
122 { SinOsc.ar(mul: 0.2) }.scope(1);
124 // watch the post window;
125 Server.internal.queryAllNodes;
127 // our SinOsc synth is within the default group (ID 1)
128 // the scope node ('stethoscope') comes after the default group, so no problems
130 Server.internal.quit;
133 In general you should add nodes to the default group, or groups contained within it, and emphasis::not:: before or after it. When adding an 'effects' synth, for instance, one should resist the temptation to add it after the default group, and instead create a separate source group within the default group. This will prevent problems with scoping or recording.
135 code::
136 default group [
137         source group [
138                 source synth1
139                 source synth2
140         ]
141         effects synth
143 recording synth
146 section::Groups as, well, groups...
148 The other major use of groups is to allow you to easily treat a number of synths as a whole. If you send a 'set' message to a group, it will apply that message to all nodes contained within it.
150 code::
151 g = Group.new;
153 // make 4 synths in g
154 // 1.0.rand2 returns a random number from -1 to 1.
155 4.do({ { arg amp = 0.1; Pan2.ar(SinOsc.ar(440 + 110.rand, 0, amp), 1.0.rand2) }.play(g); });
157 g.set(\amp, 0.005); // turn them all down
159 g.free;
162 section::Groups, their Inheritance, and More on Tracking Down Help
164 Now for a little more OOP theory. Both Group and Synth are examples of what are called emphasis::subclasses::. You can think of subclasses as being children of a parent class, called their emphasis::superclass::. All subclasses inherit the methods of their superclass. They may emphasis::override:: some methods with their own implementation (taking advantage of emphasis::polymorphism::), but in general subclasses respond to all the methods of their superclass, and some other ones of their own. Some classes are emphasis::abstract classes::, which means that you don't actually make instances of them, they just exist to provide a common set of methods and variables to their subclasses.
166 We might for instance imagine an abstract class called Dog, which has a number of subclasses, such as Terrier, BassetHound, etc. These might all have a 'run' method, but not all would need a 'herdSheep' method.
168 This way of working has certain advantages: If you need to change an inherited method, you can do so in one place, and all the subclasses which inherit it will be changed too. As well, if you want to extend a class to make your own personal variant or enhanced version, you can automatically get all the functionality of the superclass.
170 Inheritance can go back through many levels, which is to say that a class' superclass may also have a superclass. (A class cannot, however have more than one immediate superclass.) All objects in SC in fact inherit from a class called Object, which defines a certain set of methods which all its subclasses either inherit or override.
172 Group and Synth are subclasses of the abstract class link::Classes/Node::. Because of this, some of their methods are defined in Node, and (perhaps more practically important) are emphasis::documented in Node's helpfile::.
174 So if you're looking at a helpfile and can't find a particular method that a class responds to, you may need to go to the helpfile for that class' superclass, or farther up the chain. Most classes have their superclass listed at the top of their helpfile. You can also use the following methods for getting this kind of info and tracking down documentation (watch the post window):
176 code::
177 Group.superclass;                               // this will return 'Node'
178 Group.superclass.openHelpFile;
179 Group.findRespondingMethodFor('set');           // Node-set
180 Group.findRespondingMethodFor('postln');        // Object-postln;
181 Group.helpFileForMethod('postln');              // opens class Object help file
184 For more information see:
186 link::Classes/Group::, link::Classes/Node::, link::Reference/default_group::, link::Classes/RootNode::, link::Guides/Intro-to-Objects::, link::Guides/Order-of-execution::, link::Classes/Synth::, link::Guides/More-On-Getting-Help::, link::Guides/Internal-Snooping::
188 ____________________
190 This document is part of the tutorial strong::Getting Started With SuperCollider::.
192 Click here to go on to the next section: link::Tutorials/Getting-Started/13-Buffers::
194 Click here to return to the table of Contents: link::Tutorials/Getting-Started/00-Getting-Started-With-SC::