SuperCollider CLASSES

# Node

Abstract superclass of Synth and Group
Source: /usr/local/share/SuperCollider/SCClassLibrary/Common/Control/Node.sc
Inherits from: Object
Subclasses: AbstractGroup, Synth

## Description

This class is the abstract super class of Synth and Group, which represent synth and group nodes on the server. Node objects are not made explicitly, but Synth and Group are subclasses, and inherit the methods documented below.

### Freed Nodes and Node Status

Nodes which you explicitly free using the methods free or release will have their group instance variable set to nil. However Nodes which are automatically freed after a certain time (for instance by an EnvGen with a doneAction of 2) will not. This keeps the implementation of the classes simple and lightweight.

To have the current state of a Node tracked you can register it with an instance of NodeWatcher, either by calling register on the Node instance or on the NodeWatcher singleton. This will enable two variables, isPlaying and isRunning, which you can use for checking purposes.

### Bundling

Many of the methods below have two versions: a regular one which sends its corresponding message to the server immediately, and one which returns the message in an Array so that it can be added to a bundle. It is also possible to capture the messages generated by the regular methods using Server's automated bundling capabilities. See Server and Bundled Server Messages for more details.

## Class Methods

#### Returns:

the list of addActions as an event.

#### Discussion:

Useful for converting addAction symbols to their corresponding integer codes.

(
);
// returns 1

## Instance Methods

### Instance Variables

The following getter methods also have corresponding setters, but they should be used with extreme care and only if you are sure you know what you're doing.

### -nodeID = value

#### Returns:

the Node's node ID number.

#### Discussion:

Normally you should not need to access this since instances of Node can be passed directly as UGen inputs or Synth args.

### -group = value

#### Returns:

an instance of Group or RootNode corresponding to this Node's group on the server.

### -server = value

#### Returns:

an instance of Server corresponding to this Node's server app.

### -isPlaying = value

#### Returns:

a boolean indicating if this node is currently on the server, providing this Node has been registered with a NodeWatcher.

#### Discussion:

N.B. If this Node has not been registered this will likely be false in any case.

### -isRunning = value

#### Returns:

a boolean indicating if this node is currently on the server, providing this Node has been registered with a NodeWatcher.

#### Discussion:

N.B. If this Node has not been registered this will likely be false in any case.

### Node Commands

See the Node Commands section in Server Command Reference for the OSC equivalents of the methods outlined below.

### -freeMsg

Stop this Node and free it from its parent group on the server. Once a Node has been freed, you cannot restart it.

#### Arguments:

 (sendFlag) a boolean indicating whether the free message should be sent. If false an n_free message will not be sent to this Node's server, but its isPlaying and isRunning variables will be set to false. The default for sendFlag is true.

#### Discussion:

If this Node is a Group this will free all Nodes within the Group.

s.boot;
x = Synth("default");
x.free;

### -runMsg (flag: true)

Set the running state of this Node according to a boolean. False will pause the node without freeing it. The default is true.

#### Discussion:

If this Node is a Group this will set the running state of all Nodes within the Group.

s.boot;
(
x = SynthDef("help-node-set", {arg freq = 440, out = 0;
Out.ar(out, SinOsc.ar(freq, 0, 0.1));}).play(s);
)
x.run(false);
x.run; // default is true
x.free;

### -setMsg ( ... args)

Set controls in this Node to values.

#### Discussion:

Controls are defined in a SynthDef as args or instances of Control. They are specified here using symbols, strings, or indices, and are listed in pairs with values. If this Node is a Group this will set all Nodes within the Group.

s.boot;
(
x = SynthDef("help-node-set", {| freq = 440, out = 0 |
Out.ar(out, SinOsc.ar(freq, 0, 0.1));
});
x = x.play(s);
)
x.set(\freq, 880, \out, 1); // two pairs
x.set(0, 660, 1, 0); // freq is the first argument, so it's index is 0. out is index 1.
x.free;

Values that are arrays are sent using the OSC array type-tags ($[ and$]). These values will be assigned to subsequent controls in the manner of setn.

s.boot;
(
x = SynthDef("help-node-set", {| freq = #[440, 450, 460], out = 0 |
Out.ar(out, Mix(SinOsc.ar(freq, 0, 0.1)));
});
x = x.play(s);
)
x.set(\freq, [1,2,3] * 400 + [1,2,3], \out, 1); // two pairs
x.set(\freq, [3] * 400 + [1,2,3], \out, 1); // two pairs
x.set(0, [660, 680, 720], 1, 0); // freq is the first argument, so it's index is 0. out is index 1.
x.free;

### -setnMsg ( ... args)

Set sequential ranges of controls in this Node to values.

#### Discussion:

Controls are defined in a SynthDef as args or instances of Control. They are specified here using symbols, strings, or indices, and are listed in pairs with arrays of values. If this Node is a Group this will setn all Nodes within the Group.

s.boot;
(
x = SynthDef("help-node-setn", {
arg freq1 = 440, freq2 = 440, freq3 = 440, amp1 = 0.05, amp2 = 0.05, amp3 = 0.05;
Out.ar(0, Mix(SinOsc.ar([freq1, freq2, freq3], 0, [amp1, amp2, amp3])));}).play(s);
)
// set 3 controls starting from \freq1, and 3 controls starting from \amp1
x.setn(\freq1, [440, 880, 441], \amp1, [0.3, 0.1, 0.3]);
x.free;

### -fillMsg (controlName, numControls, value... args)

Set sequential ranges of controls in this Node to a single value.

#### Discussion:

Controls are defined in a SynthDef as args or instances of Control. They are specified here using symbols, strings, or indices, and are listed in groups of three along with an integer indicating the number of controls to set, and the value to set them to. If this Node is a Group this will fill all Nodes within the Group.

### -mapMsg ( ... args)

Map controls in this Node to read from control or audio rate Buses.

#### Discussion:

Controls are defined in a SynthDef as args or instances of Control or its subclasses. They are specified here using symbols, strings, or indices, and are listed in pairs with Bus objects. The number of sequential controls mapped corresponds to the Bus' number of channels.

If this Node is a Group this will map all Nodes within the Group.

Note that with mapMsg if you mix audio and control rate busses you will get an Array of two messages rather than a single message. Integer bus indices are assumed to refer to control buses. To map a control to an audio bus, you must use a Bus object.

s.boot;
(
b = Bus.control(s, 1); b.set(880);
c = Bus.control(s, 1);    c.set(884);
x = SynthDef("help-Node-map", { arg freq1 = 440, freq2 = 440;
Out.ar(0, SinOsc.ar([freq1, freq2], 0, 0.1));
}).play(s);)
x.map(\freq1, b, \freq2, c);
x.free; b.free; c.free;

// same as above with a multichannel Bus and Control
(
b = Bus.control(s, 2); b.set(880, 884);
x = SynthDef("help-Node-map2", { arg freqs = #[440, 440];
Out.ar(0, SinOsc.ar(freqs, 0, 0.1));
}).play(s);)
x.map(\freqs, b);
x.free; b.free;

### -mapnMsg ( ... args)

Map sequential ranges of controls in this Node to read from control rate Buses.

#### Discussion:

This is similar to map above, but you specify the number of sequential Controls to map. If this Node is a Group this will mapn all Nodes within the Group.

### -releaseMsg (releaseTime)

This is a convenience method which assumes that the synth contains an envelope generator (an EnvGen, Linen, or similar UGen) running a sustaining envelope (see Env) and that it's gate argument is set to a control called \gate. This method will cause the envelope to release.

#### Arguments:

 releaseTime if not nil, it will override the envelope's decay or release time.

#### Discussion:

If this Node is a Group this will release all Nodes within the Group.

x = { arg gate=1; BrownNoise.ar(0.5) * EnvGen.kr(Env.cutoff(1), gate, doneAction:2) }.play;
x.release(5); // overide the Env's specified 1 second release time

### -query

Sends an n_query message to the server, which will reply with a message containing information about this node and its place in the server's node tree.

#### Discussion:

This information will be printed to the post window. (See also the queryAllNodes method of Server.) "parent" indicates the Node's enclosing group. If "prev" or "next" are equal to -1 that indicates that there are no other nodes in the enclosing group before or after this one, respectively.

g = Group.new;
x.query;
g.query;
s.queryAllNodes; // Note the RootNode (ID 0) and the default Group (ID 1)
x.free; g.free;

### -trace

Causes a synth to print out the values of the inputs and outputs of its unit generators for one control period to the post window. Causes a group to print the node IDs and names of each node in the group for one control period.

g = Group.new;
x.trace;
g.trace;
x.free; g.free;

### -register (assumePlaying: false)

Registers the node at the NodeWatcher object.

#### Discussion:

This will enable two variables, isPlaying and isRunning, which you can use for checking purposes.

(
b = s.makeBundle(false, {
a = Group.new(s); //create a node object
a.register; // register before creating on the server
});
)
a.isPlaying;
s.listSendBundle(nil, b); //start the node on the server
a.isPlaying;
a.isRunning;
a.run(false);
a.isRunning;
s.freeAll; //free all nodes
a.isPlaying;
a.isRunning;

### Changing the order of execution

The following methods can be used to change the Node's place in the order of execution. See the Order of execution help file for more information on this important topic. See Server Command Reference for the OSC equivalents of these methods.

### -moveAfterMsg (aNode)

Move this Node to be directly after aNode. N.B. n_after, the OSC message which this method encapsulates, allows already freed nodes as targets. This is so that one may attempt a series of moves, with the last successful one taking effect. For this reason this method will fail silently if either the target or this node have already been freed. If you will need to check, you may register the relevant nodes with a NodeWatcher.

### -moveBeforeMsg (aNode)

Move this Node to be directly before aNode. N.B. n_before, the OSC message which this method encapsulates, allows already freed nodes as targets. This is so that one may attempt a series of moves, with the last successful one taking effect. For this reason this method will fail silently if either the target or this node have already been freed. If you will need to check, you may register the relevant nodes with a NodeWatcher.

If aGroup is a Group then this method will move this Node to the head of that Group. If it is nil this will move this Node to the head of the default_group of this Node's Server.

### -moveToTailMsg (aGroup)

If aGroup is a Group then this method will move this Node to the tail of that Group. If it is nil this will move this Node to the tail of the default_group of this Node's Server.

### -asTarget

#### Returns:

this Node. See the asTarget help file for more details.

### -printOn (stream)

Prints this Node's Class (Synth or Group) and nodeID on stream.

### -hash

#### Returns:

server.hash bitXor: nodeID.hash

### -== (that)

#### Returns:

true if this Node and aNode have the same nodeID and the same Server object, otherwise returns false.

#### Discussion:

Under certain circumstances this Node and aNode might not be the same object, even though this returns true.

g = Group.basicNew(s, 1); // the default group of s
h = Group.basicNew(s, 1); // and again
g == h;     // true
g === h;    // false

### -onFree (func)

Evaluate function when this Node is freed.

#### Discussion:

{PinkNoise.ar(1) * Line.kr(1,0,2,doneAction:2)}.play.onFree {"done".postln};

### -waitForFree

Wait until this Node is freed. Should be used inside a Routine or similar.

#### Discussion:

(
fork {
{SinOsc.ar(440!2) * Line.kr(0,1,5,doneAction:2)}.play.waitForFree;
{PinkNoise.ar(1) * Line.kr(1,0,2,doneAction:2)}.play.onFree {"done".postln};
}
)
(
SynthDef(\help, {
var mod = LFNoise2.kr(Rand(1, 6)) * 0.2;
var snd = mod * Blip.ar(Rand(200, 800) * (mod + 1));
Out.ar(0, snd);
FreeSelf.kr(mod < 0);
)

(
fork {
10.do {
"started a synth".postln;
Synth(\help).waitForFree;
"This one ended. Wait a second, I will start the next one.".postln;
1.wait;
};
"This is it.".postln;
}
);