Syn is like Synth in that it instantiates a SynthDef as a synth node in a server.
The argument list to a Synth may assign only numbers, or arrays of numbers, to a control name.
The argument list to a Syn may also include Plug objects, which patch signals from other SynthDefs to the synth input automatically.
Syn is designed for polyphony. When a Syn releases, all of its resources (auxiliary synth nodes for input signals, and control or audio buses) are freed up to be reused. Using the \syn
event type (see Event types), an event pattern can play a sequence of Syn objects, where every network of synths is independent.
(JITLib also supports on-the-fly dynamic patching, but its support for polyphony appears to be limited. You can copy
a NodeProxy, but AFAICS this does not copy its connections to other NodeProxies. JITLib's focus is on interaction; Syn's focus is replicable structure.)
A Syn creates a flat list of nodes, arranged in order so that Plugs feeding into inputs come first.
Node 1000 is created first, using the given target
and addAction
. Subsequent nodes are added immediately after the previous one.
release
-ing the Syn cascades through all the other objects, freeing them as well.
Buses are allocated and released automatically. In the above example, the Plug function returns one kr channel, and the single kr bus matches the single kr freq
input defined by the default SynthDef.
If you need to use Syn with supernova, make sure to configure the following:
With this option enabled, each Syn will create its own Group (not ParGroup!) to maintain processing order. Syn Groups may be placed into a ParGroup for parallel processing.
Syn
defines the following event types:
\note
, except that it creates a Syn object for each note (including multichannel expansion).\on
.\off
.\set
. (Note that the arguments to set must be specified in an args
array.)Plugs may be generated dynamically by event keys ending in "Plug" -- see examples below.
Feedback between Plugs is not supported.
While it is supported to define Plugs based on a synthesis function, and Syn will attempt to maintain timing according to latency, a very complex Syn with a large number of function-based Plugs may take too long to prepare. For efficiency, it is recommended to use SynthDefs as much as possible in production settings.
However (new as of April 2025), Plugs based on functions will attempt to cache and reuse their temporary SynthDefs. This will improve efficiency of, for instance, patterns using function-based Plugs. See Plug: Plugs based on Functions.
Create and perform a new Syn.
source |
A SynthDef name (string or symbol), or a Function, specifying the main output signal. |
args |
A Synth-style argument list: |
target |
The node relative to which this Syn's nodes will be created. |
addAction |
One of |
latency |
Server messaging latency to specify when the sound should hit the speakers. |
A playing Syn instance.
Like *new
, but accepts a list of argument paths and values applying to the entire Syn-Plug complex.
Syn.new
-- each args
list applies only to its owner. Argument values belonging to a Plug must be written into the specific Plug's argument list. This is faster.Syn.newByArgPaths
-- the main Syn argument list can contain arguments for any location in the Syn-Plug tree, using the same path syntax as Syn: -set. This incurs some processing overhead, since the paths need to be converted into the Syn.new
structure. But this may be more convenient for programmatic generation of argument lists.See Setting controls examples below.
source |
A SynthDef name (string or symbol), or a Function, specifying the main output signal. |
args |
A Synth-style argument list, where names may be paths to Plug inputs in the tree: |
target |
The node relative to which this Syn's nodes will be created. |
addAction |
One of |
latency |
Server messaging latency to specify when the sound should hit the speakers. |
A playing Syn instance.
Create a new Syn, but don't perform it.
source |
A SynthDef name (string or symbol), or a Function, specifying the main output signal. |
args |
A Synth-style argument list: |
target |
The node relative to which this Syn's nodes will be created. |
addAction |
One of |
An idle Syn instance.
Create a new Syn with path-style arguments (see Syn: *newByArgPaths, but don't perform it.
source |
A SynthDef name (string or symbol), or a Function, specifying the main output signal. |
args |
A Synth-style argument list, where names may be paths to Plug inputs in the tree: |
target |
The node relative to which this Syn's nodes will be created. |
addAction |
One of |
An idle Syn instance.
If true, each Syn will place its nodes into a dedicated group. If false, nodes go directly into the parent group. Default is false.
The following methods use OSCBundle because preparation messages may be needed.
Generates and sends an OSC bundle for a Syn.basicNew
.
latency |
Server messaging latency defining the time when the sound should hit the speakers. |
Produce an OSCBundle object containing the messages required to perform the object.
bundle |
Optional. An OSCBundle object. |
An OSCBundle.
Given an OSCBundle, perform it at the time specified by latency
.
bundle |
An OSCBundle object created by prepareToBundle. |
latency |
Server messaging latency defining the time when the sound should hit the speakers. |
The following methods use a plain List for bundling.
As in Synth: -release, send gate-set messages to cause sustaining envelopes to release. When the primary node(s) are removed, Syn will also release auxiliary resources.
latency |
Server messaging latency defining the time to begin the release. |
gate |
The gate value to set. Numbers less than -1.0 will trigger a forced release (see EnvGen). |
Construct a bundle (List) of all the messages required to release this Syn.
bundle |
A List or nil. |
gate |
The gate value to set. Numbers less than -1.0 will trigger a forced release (see EnvGen). |
The bundle, as a List.
Send /n_free
messages to hard-stop this Syn.
latency |
Server messaging latency defining the time to free the nodes. |
... why |
Optional. An annotation. Mainly intended for debugging purposes. |
Construct a bundle (List) of all the messages required to hard-stop this Syn.
bundle |
A List or nil. |
The bundle, as a List.
Set controls in the Syn.
A control input may receive a signal from another synth node. This synth node may itself have control inputs. These may be accessed using a path-style syntax: 'freq/rate'
would set the rate parameter belonging to the Plug supplying the frequency to the main synth.
.set
can replace the plug with a new Plug, but it cannot remove the Plug and replace it with a fixed number. See Setting controls and Three-point modulation below.... args |
Path-value pairs. |
Adds "set" messages into a bundle, for later sending.
bundle |
Optional. A List of OSC messages. If not provided, one will be created for you. |
... args |
Name-value pairs. |
A List of OSC messages.
Set arrayed controls in the Syn.
... args |
Name-value pairs. |
Adds "setn" messages into a bundle, for later sending.
bundle |
Optional. A List of OSC messages. If not provided, one will be created for you. |
... args |
Name-value pairs. |
A List of OSC messages.
Force the Syn's associated objects to clean themselves up, without actually sending a free
message to the main Syn node. Normally, there is no need to call this method directly; however, cleanupToBundle
is useful for non-real-time rendering.
Performs a cleanup
operation, and captures all of the OSC messages into an OSCBundle. These messages may then be added into a NRT Score. See examples.
bundle |
Optional. An OSCBundle. If omitted, an OSCBundle will be created for you, and returned. |
An OSCBundle containing cleanup messages.
The Syn's source. Currently a string or symbol specifies an existing SynthDef, or a Function can create a SynthDef on-the-fly.
The argument list.
Access a given argument value only for the top-level Syn. This method does not look into child Plug arguments.
key |
A Symbol identifying the argument to look up. |
Access a given argument value anywhere in the object tree.
path |
A string or symbol locating a parameter, using the same syntax as in -set. |
An argument value, or Plug object.
Finds the object to which a plug or other input belongs. Normally you should not need to call this directly. It is used when set()
replaces a Plug: the old Plug's owner object is responsible for completing this operation.
path |
A string or symbol locating a parameter, using the same syntax as in -set. |
The owner object of the given parameter.
The existing node relative to which the Syn was created.
One of \addToHead
, \addToTail
, \addBefore
or \addAfter
.
The server on which the Syn is running. (Note that this is not specified directly, but derived from target
.)
Calculation rate, either \control
or \audio
.
Mainly for private use. This method returns an array consisting of either [target, addAction]
or (in "group" style) [group, \addToTail]
.
The top-level synth node.
A Synth node.
If group-style node ordering has been chosen, this is the Syn's dedicated Group.
An IdentitySet of Plugs feeding into the main synth node. (These Plugs may themselves have antecedents -- that is, you can use the antecedents collections to iterate over the entire tree.)
The owner Syn -- i.e., this
.
A LinkedList of all Synth nodes controlled by this Syn.
By default, a Plug copies itself before rendering. It's assumed that, wherever a Plug is used, its signal should be unique. Here, the three notes will be modulated by independent random curves.
Creating a Plug.shared
will render one signal only for this object, which may be read in multiple places.
Synth: -set is simple because there is a one-to-one relationship between the Synth object and the synth node in the server.
A Syn can represent multiple nodes, so there needs to be a way to address set
messages to specific nodes in the tree. Also, if a control is mapped onto a Plug, setting it will break the connection, and it can be difficult to recover.
Syn uses a path-style syntax to locate controls:
This Syn has three nodes, which are effectively nested:
To set the main synth's 'amp' parameter, use x.set(\amp, 0.1)
.
To set the frequency range of the Plug controlling 'freq': x.set("freq/low", 500, "freq/high", 1200)
. (Note that there is no leading slash.)
To set the innermost Plug, continue adding to the path: "freq/rate/rate"
, "freq/rate/low"
etc.
Syn.newByArgPaths
supports "set"-style path arguments at Syn creation time. For example, all of the following are equivalent to x
above.
The redundancy in the multiple paths might be cumbersome to type manually, but in some cases may be more convenient to generate programmatically.
What if you try x.set(\freq, 300)
? "freq" is mapped to a Plug. Setting it to a fixed value would break the modulation. Instead, Syn will try to push the freq set down to a lower level Plug, if possible. In this case, the Plug synth has no 'freq' input, so nothing will happen. If it did have a 'freq' input, then it would be set at the second level.
There is a reason for this:
In three-point modulation, there are three values to consider:
For Event use, however, it is inconvenient to set the base frequency as "freq/base"
. Events expect to address frequency as "freq"
. This is why .set will pass values down into the Plug tree. Plug's map
parameter can change the control name to which passed-down values are sent.
In the previous example, you have direct control over the Syn's structure. An Event creates Syn objects for you. This poses a problem: How to specify a parameter's baseline value using normal pattern calculations, and apply Plug modulation to it?
The \syn
and \synOn
event types look for event values ending in Plug:
\degree
will control the default SynthDef's freq
input, to which a "freqPlug" may be applied. This is given as a function to be evaluated per event. The function argument comes from the event being processed (see Function: -valueEnvir). In this function, you can create a Plug with any structure you want. Here, the frequency is passed in an arg list, and modulated in the standard way.
The NRT interface at this point is not especially convenient, but it is possible to use xxxToBundle
methods to capture OSC messaging, and at the messages one by one into a Score.
Plugs' sources can be changed on the fly, without disrupting the structure. To do this, access the Plug object using -argAtPath and call Plug: -source on it.
Alternately, new Plugs may be introduced at any time through the standard -set interface. If there was already a Plug in that location, the old Plug and all of its upstream Plugs will be removed.