public class SynthDef extends Object implements Constants
While in SClang as an interpreter language the graph is represented as a function, this is not appropriate for java as a (semi)compiled language. Therefore, you do not pass a graph function to the constructor, but rather a collection of graph elements (UGens and Constants) which have already been put together.
This also implies that there is no
function header which can be read by SynthDef
to
automatically construct Control
UGens from the
function's arguments. You therefore have to create Control
UGens explicitly yourself. SynthDef
will find them
and construct the synth def binary object accordingly.
Note that this class includes the functionality found separately
in SClang's SynthDesc class, that is methods for reading and formatting
a synth def. Unlike SClang, when a synth def is read, UGens are
created as instances of the UGen
class. In an earlier
version, java.lang.reflect
was used to dynamically load
UGen subclasses. This concept was dropped because it would imply
So instead, there is one clumsy UGen
class which
carries all the information about inlets and outlets. A synth def
file is sufficient to recreate the graph tree using this class.
On the other side, when you yourself create a UGen tree, another
objects comes in, the UGenInfo
which acts as a lookup
table for installed UGen clases.
This class is somewhat more simple than the SClang counterpart.
For example, input rate consistency is not checked.
Tree optimization is still inferior because of the non-existing
UGen subclasses (like BinaryOpUGen
) that could handle
context-sensitive optimization. Control-lags and Trigger-controls
are not supported. For the sake of cleanness, all the strange
interpenetration of SynthDef and UGen in the building process as
exhibited by SClang was dropped, where the def would go and write
things into the UGen and vice versa, setting up temporary fields
like the building-def and so on. So this implementation is more
stripped down but way cleaner and less spaghetti.
There seemed to be a non-finished project in SClang's SynthDef called "variants". i don't know what this was, it has was just been dropped.
Here is an example of building a SynthDef (comments are below):
GraphElem f = null; GraphElem g, h; Control c = Control.kr( new String[] { "resinv" }, new float[] { 0.5f }); UGenChannel reso = c.getChannel( 0 ); Synth synth; Random r = new Random( System.currentTimeMillis() ); String defName = "JNoiseBusiness1b"; OSCBundle bndl; SynthDef def; long time; f = null; for( int i = 0; i < 4; i++ ) { g = UGen.ar( "*", UGen.ar( "LFSaw", UGen.kr( "midicps", UGen.kr( "MulAdd", UGen.kr( "LFPulse", UGen.ir( 0.06f ), UGen.ir( 0 ), UGen.ir( 0.5f )), UGen.ir( 2 ), UGen.array( UGen.ir( 34 + r.nextFloat() * 0.2f ), UGen.ir( 34 + r.nextFloat() * 0.2f ))))), UGen.ir( 0.01f )); f = (f == null) ? g : UGen.ar( "+", f, g ); } h = UGen.kr( "LinExp", UGen.kr( "SinOsc", UGen.ir( 0.07f )), UGen.ir( -1 ), UGen.ir( 1 ), UGen.ir( 300 ), UGen.ir( 5000 )); f = UGen.ar( "softclip", UGen.ar( "RLPF", f, h, reso )); f = UGen.ar( "softclip", UGen.ar( "RLPF", f, h, reso )); def = new SynthDef( defName, UGen.ar( "Out", UGen.ir( 0 ), f )); synth = Synth.basicNew( defName, myServer ); try { def.send( myServer, synth.newMsg( myServer.asTarget(), new String[] { "resinv" }, new float[] { 0.98f })); time = System.currentTimeMillis(); for( int i = 500; i < 5000; i += 250 ) { bndl = new OSCBundle( time + i ); bndl.addPacket( synth.setMsg( "resinv", r.nextFloat() * 0.8f + 0.015f )); myServer.sendBundle( bndl ); } bndl = new OSCBundle( time + 5500 ); bndl.addPacket( synth.freeMsg() ); myServer.sendBundle( bndl ); } catch( IOException e1 ) { System.err.println( e1 ); }Yes, it's true, the code is at least three times as big as would be the SClang counter part, but we're definitely focussing on an application different from jit developing synthesizers.
So some remarks on the example (the sound isn't particularly
interesting though ;-) : generally it improves readability if
me create piece of the graph in more than one line. While the
loop body is difficult to read, the statement that adds clipping
and resonance is easy. Since we have only one dead end for the
graph (Out.ar), we simply pass the result of UGen.ar( "Out" ... )
to the synth def constructor. to overwrite the resonance control default
value of 0.5 (as specified in the Control
constructor),
we add control name and value parameters to the synth.newMsg
call. the result of this call is an OSCMessage
(whereas
new Synth( ... )
would have sent that message immediately),
this is passed to the synth def constructor as the completion message.
the rest shows you how to send bundles to set the resonance value
of the synth at certain times.
You will probably want to use SClang to prototype the synthesizers and then just port them to JCollider which shouldn't be too difficult after some practising. See the JColliderDemo for more examples of UGen graphs.
Modifier and Type | Field and Description |
---|---|
static int |
SCGF_VERSION
Currently supported synth def file
version (1).
|
static String |
SUFFIX
Default file suffix when writing defs to disk.
|
kAddAfter, kAddBefore, kAddReplace, kAddToHead, kAddToTail, kAudioRate, kControlRate, kDemandRate, kDoneFree, kDoneFreeAll, kDoneFreeAllPred, kDoneFreeAllSucc, kDoneFreeGroup, kDoneFreePausePred, kDoneFreePauseSucc, kDoneFreePred, kDoneFreePredGroup, kDoneFreePredGroupDeep, kDoneFreeSucc, kDoneFreeSuccGroup, kDoneFreeSuccGroupDeep, kDoneNothing, kDonePause, kDumpBoth, kDumpHex, kDumpOff, kDumpText, kHeaderAIFF, kHeaderIRCAM, kHeaderNeXT, kHeaderRaw, kHeaderWAVE, kSampleALaw, kSampleDouble, kSampleFloat, kSampleInt16, kSampleInt24, kSampleInt32, kSampleInt8, kSampleMuLaw, kScalarRate
Constructor and Description |
---|
SynthDef(String name,
GraphElem graph)
Constructs a new SynthDef from the given
graph element.
|
Modifier and Type | Method and Description |
---|---|
String |
getName()
Returns the name of the synth definition
|
List |
getUGens()
Return a list of all UGens in the graph
(in the depth-first sorted topological order).
|
static boolean |
isDefFile(File path)
Checks to see if a given file is a
synth definition file.
|
void |
load(Server s)
Stores the def in a temp file and sends a
corresponding OSC
/d_load message to the server. |
void |
load(Server s,
de.sciss.net.OSCMessage completionMsg)
Stores the def in a temp file and sends a
corresponding OSC
/d_load message to the server. |
void |
load(Server s,
de.sciss.net.OSCMessage completionMsg,
File path)
Stores the def in a file and sends a
corresponding OSC
/d_load message to the server. |
Synth |
play(Group target)
Sends the def to the server and creates a synth from this def.
|
Synth |
play(Group target,
String[] argNames,
float[] argValues)
Sends the def to the server and creates a synth from this def.
|
Synth |
play(Node target,
String[] argNames,
float[] argValues,
int addAction)
Sends the def to the server and creates a synth from this def.
|
void |
printOn(PrintStream out)
Prints a textual representation
of the synth def to the given stream.
|
static SynthDef |
read(InputStream is)
Reads a single
SynthDef from an input stream
(such as a harddisk file or memory buffer). |
static SynthDef[] |
readDefFile(File path)
Reads definitions from a synth def file.
|
static SynthDef[] |
readDefFile(InputStream is)
Reads definitions from an input stream
(such as a harddisk file or memory buffer).
|
static SynthDef[] |
readDefFile(URL path)
Reads definitions from a synth def file.
|
de.sciss.net.OSCMessage |
recvMsg()
Constructs a message to sends to
a server for providing the synth def.
|
de.sciss.net.OSCMessage |
recvMsg(de.sciss.net.OSCMessage completionMsg)
Constructs a message to sends to
a server for providing the synth def.
|
void |
send(Server server)
Sends the definition to
a server.
|
void |
send(Server server,
de.sciss.net.OSCMessage completionMsg)
Sends the definition to
a server.
|
void |
write(OutputStream os)
Writes this def to an output stream (such as a file or
a memory buffer).
|
void |
writeDefFile(File path)
Writes this def to a definition file.
|
static void |
writeDefFile(File path,
SynthDef[] defs)
Writes an array of definitions to a file.
|
public static final String SUFFIX
public static final int SCGF_VERSION
public SynthDef(String name, GraphElem graph)
name
- the name of the synth def
as would be used to instantiate a Synth
graph
- a graph element such as a UGen
or
a collection of ugens. Basically anything that
comes out of one of the static contructor methods
of the UGen
class. Note that when there
are several "dead ends" in the graph, those
dead ends should be collected in a GraphElemArray
which is then passed to SynthDef
, otherwise the
synthdef may be incomplete. See the JColliderDemo
to see how to do it.public void send(Server server) throws IOException
server
- to representation of the server
to send the def toIOException
- if a network error occuredpublic void send(Server server, de.sciss.net.OSCMessage completionMsg) throws IOException
server
- to representation of the server
to send the def tocompletionMsg
- message to execute by the server
when the synth def has become available.
typically something like Synth.newMsg( ... )
.
may be null
IOException
- if a network error occuredpublic de.sciss.net.OSCMessage recvMsg() throws IOException
IOException
- when synth def compilation
fails (? this should never happen?)public de.sciss.net.OSCMessage recvMsg(de.sciss.net.OSCMessage completionMsg) throws IOException
completionMsg
- completion message, such as /s_new
or null
IOException
- when synth def compilation
fails (? this should never happen?)public String getName()
public void load(Server s) throws IOException
/d_load
message to the server.s
- the server to send the def toIOException
- if the file could not be created or the message could not be sentpublic void load(Server s, de.sciss.net.OSCMessage completionMsg) throws IOException
/d_load
message to the server.s
- the server to send the def tocompletionMsg
- an OSC message to be executed when the def was received (can be null
)IOException
- if the file could not be created or the message could not be sentpublic void load(Server s, de.sciss.net.OSCMessage completionMsg, File path) throws IOException
/d_load
message to the server.s
- the server to send the def tocompletionMsg
- an OSC message to be executed when the def was received (can be null
)path
- path to a file. if a file by this name
already exists, the caller should delete it
before calling this methodIOException
- if the file could not be created or the message could not be sentpublic Synth play(Group target) throws IOException
target
- the group to whose head the node is addedIOException
- if a network error occurspublic Synth play(Group target, String[] argNames, float[] argValues) throws IOException
target
- the group to whose head the node is addedargNames
- the names of the controls to set. can be null
argValues
- the values of the controls. each array element corresponds to
the element in argNames
with the same index. the sizes of argValues
and argNames
must be equal. can be null
IOException
- if a network error occurspublic Synth play(Node target, String[] argNames, float[] argValues, int addAction) throws IOException
target
- the node to which the new synth is addedargNames
- the names of the controls to set. can be null
argValues
- the values of the controls. each array element corresponds to
the element in argNames
with the same index. the sizes of argValues
and argNames
must be equal. can be null
addAction
- the add action re target
IOException
- if a network error occurspublic void printOn(PrintStream out)
out
- the stream to print on, such as System.out
System.out
public List getUGens()
UGen
public static boolean isDefFile(File path) throws IOException
path
- to the synth def filetrue
if the file starts with
the synth definition magic cookie. does not
check for the synth def file versionIOException
- if the file could not be readpublic static void writeDefFile(File path, SynthDef[] defs) throws IOException
path
- path to a file. if a file by this name
already exists, the caller should delete it
before calling this methoddefs
- array of definitions which will be written
one after anotherIOException
- if the file cannot be opened, denotes a
directory, or if a write error occurspublic void writeDefFile(File path) throws IOException
path
- path to a file. if a file by this name
already exists, the caller should delete it
before calling this methodIOException
- if the file cannot be opened, denotes a
directory, or if a write error occurspublic void write(OutputStream os) throws IOException
os
- stream to write to. the stream will be
buffered by this method, so you do not need
to do thisIOException
- if a write error occurspublic static SynthDef[] readDefFile(URL path) throws IOException
path
- the location of the synth def file
such as a local harddisk or remote server fileIOException
- if a read error occurs, if the
file has not a valid synth def
format or if the synth def file
version is unsupported (greater than SCFG_VERSION
)public static SynthDef[] readDefFile(File path) throws IOException
path
- the location of the synth def fileIOException
- if a read error occurs, if the
file has not a valid synth def
format or if the synth def file
version is unsupported (greater than SCFG_VERSION
)public static SynthDef[] readDefFile(InputStream is) throws IOException
is
- the stream to read fromIOException
- if a read error occurs, if the
stream has not a valid synth def
format or if the synth def file
version is unsupported (greater than SCFG_VERSION
)public static SynthDef read(InputStream is) throws IOException
SynthDef
from an input stream
(such as a harddisk file or memory buffer). Please refer
to the SuperCollider document Synth-Definition-File-Format.rtf
to read how a synth def is constructed
(read the paragraph "a synth-definition is :").
This assumes synth def file format version 1 as used
by SuperCollider as of september 2005.is
- the stream to read from with the current read
position placed at the start of a new synth defIOException
- if a read error occursCopyright © 2015–2022 SciJava. All rights reserved.