#lang scribble/manual @(require (for-label racket)) @title{Unit Generators and Synths} Introduction to some fundamental concepts@section{categories} Server>Nodes A unit generator is an object that processes or generates sound. There are many classes of unit generators, all of which derive from the class link::Classes/UGen::. Unit generators in SuperCollider can have many inputs, but always have a single output. Unit generator classes which would naturally have several outputs such as a panner, return an array of unit generators when instantiated. The convention of having only a single output per unit generator allows the implementation of multiple channels by using arrays of unit generators. (See link::Guides/Multichannel-Expansion:: for more details.) @section{section} Instantiation. Audio Rate, Control Rate A unit generator is created by sending the 'ar' or 'kr' message to the unit generator's class object. The 'ar' message creates a unit generator that runs at audio rate. The 'kr' message creates a unit generator that runs at control rate. Control rate unit generators are used for low frequency or slowly changing control signals. Control rate unit generators produce only a single sample per control cycle and therefore use less processing power than audio rate unit generators. The input parameters for a unit generator are given in the documentation for that class. @racketblock[ FSinOsc.ar(800, 0.0, 0.2); // create a sine oscillator at 800 Hz, phase 0.0, amplitude 0.2 :: A unit generator's signal inputs can be other unit generators, scalars, or arrays of unit generators and scalars. ] @section{section} SynthDefs and Synths In order to play a unit generator one needs to compile it in a link::Classes/SynthDef:: and play it on the server in a link::Classes/Synth::. A synth node is a container for one or more unit generators that execute together. A SynthDef is like a kind of pattern for creating synth nodes on the server. @racketblock[ s.boot; // boot the server // compile and send this def SynthDef.new("FSinOsc-test", { Out.ar(0, FSinOsc.ar(800, 0, 0.2)) }).send(s); // out channel 0 // now create a Synth object which represents a synth node on the server x = Synth.new("FSinOsc-test"); // free the synth x.free; :: The synth node created above could also be created using 'messaging style', thus saving the overhead of a clientside Synth object: ] @racketblock[ n = s.nextNodeID; s.sendMsg("/s_new", "FSinOsc-test", n); s.sendMsg("/n_free", n); :: Because any expression returns its value, we can nest the first two lines above for convenience. (See link::Reference/Expression-Sequence:: for more detail.) ] @racketblock[ s.sendMsg("/s_new", "FSinOsc-test", n = s.nextNodeID;); s.sendMsg("/n_free", n); :: It is VERY important and useful to understand the messaging structure which underlies the clientside Synth, Group, Buffer, and Bus objects. See link::Guides/NodeMessaging::, link::Tutorials/Tutorial::, and link::Guides/ClientVsServer:: for more detail. As a convenience the 'play' method of class link::Classes/Function:: will compile a SynthDef and create and play a synth using the function for you. With this method an link::Classes/Out:: ugen will be created for you if you do not do so explicitly. ] @racketblock[ { FSinOsc.ar(800, 0, 0.2) }.play; // create and play a sine oscillator at 800 Hz :: ] @section{section} Building Patches You can do math operations on unit generators and the result will be another unit generator. Doing math on unit generators is not doing any signal calculation itself - it is building the network of unit generators that will execute once they are played in a Synth. This is the essential thing to understand: Synthesis networks, or in other words signal flow graphs are created by executing expressions of unit generators. The following expression creates a flow graph whose root is an instance of link::Classes/BinaryOpUGen:: which performs the '+' operation. Its inputs are the link::Classes/FSinOsc:: and link::Classes/BrownNoise:: unit generators. @racketblock[ FSinOsc.ar(800, 0.0, 0.2) + BrownNoise.ar(0.2); // press enter and look at the post window {FSinOsc.ar(800, 0.0, 0.2) + BrownNoise.ar(0.2)}.play; // play it :: ]