/* More on Classes - methods, getters, setters */


// We have seen how new objects can be created, but many classes also have methods 

// associated with them that contain functions that can operate on an Objects data:


e = Env([0, 1, 0], [1, 2], \sin);

e.plot

// looking at the classdef for Env, we can see there is an 'at' method that will

// calculate values from Envelopes at a given time


e.at(0.2);


e = Env([440, 880, 220], [10, 2], \exp);

e.plot;

e[2]


// Inside a Class definition, the '^' indicates what is returned from a method


f = e.delay(2);

f.postln; // post the 'value' of the object

f.postcs; // post a compile string representation of the object


// If the var is prepended with a '<', that means we can access the data stored 

// in the var from the language (this is a getter).


f.times;

f.levels;


// if a var has a 'setter' character - '>' - you can also directly alter the value

// of that variable.


f.times_([1, 10, 2]);

f.times;

f.postcs;


/* SynthDefs */

/* Celia says - "UGens belong in SynthDefs" */

attachments/class03/DSCF0035.png


s.boot;


a = SynthDef(\mysynth, {arg freq = 300, dur = 1, amp = 1;

var src, env;

src = SinOsc.ar(freq, 0, 1);

env = EnvGen.kr(

Env([0, 1, 0], [0.5, 0.5], \sin),

timeScale: dur,

levelScale: amp,

doneAction: 2);

Out.ar(0, src * env);

});

a.load(s); // once loaded, it is available to your server for usage. You only 

// need to reload if you change something.

Server-Command-Reference

// \s_new, \synthdefid, nodeId, addaction, target, .... args 


s.sendMsg(\s_new, \mysynth, 1000, 0, 1);


s.sendMsg(\s_new, \mysynth, 1001, 0, 1, \freq, 1000, \amp, 0.1, \dur, 40);


// use n_free to stop the synth


s.sendMsg(\n_free, 1000);


// use the Server object to give you a nodeID


s.sendMsg(\s_new, \mysynth, s.nextNodeID, 0, 1, \freq, 2000, \amp, 0.2);


// Using s.nextNodeID makes multiple note creation much easier to do:

(

f = Array.fill(30, {220.rrand(1760)});

f.do({arg myfreq; s.sendMsg(\s_new, \mysynth, s.nextNodeID, 0, 1, \freq, myfreq, 

\amp, f.size.reciprocal)});

)


f = Array.fill(300, {1760.rrand(7040)});

f.do({arg me; s.sendMsg(\s_new, \mysynth, s.nextNodeID, 0, 1, \freq, me, 

\amp, f.size.reciprocal)});


// Object style


f = Array.fill(300, {1760.rrand(7040)});

f.do({arg me; Synth(\mysynth, [\freq, me, \amp, f.size.reciprocal])});


/* Order-of-Execution - groups, nodes and targets */


s.queryAllNodes;


// First, a couple of synthdefs that will not shut off until you tell them 

// to (gated Envs):

(

SynthDef(\noise, {arg gate = 1, amp = 0.2, outbus = 0;

var src, env;

src = PinkNoise.ar(amp);

env = EnvGen.kr(

Env([0, 1, 0], [1, 1], \sin, 1),

gate,

doneAction: 2);

Out.ar(outbus, src * env);

}).load(s); // create and load the SynthDef in one step

SynthDef(\filtandsin, {arg gate = 1, sinamp = 0.2, filtamp = 1, sinfreq = 440, filtfreq = 880,

inbus = 0, outbus = 0;

var sin, filt, src, env;

src = In.ar(inbus);

sin = SinOsc.ar(sinfreq, 0, sinamp);

filt = BPF.ar(src, filtfreq, 0.01, filtamp);

env = EnvGen.kr(

Env([0, 1, 0], [1, 1], \sin, 1),

gate,

doneAction: 2);

Out.ar(outbus, (sin + filt) * env);

}).load(s);

)

// a noise gen: I need to refer to this synth later, so I save the nodeID in a var:


s.sendMsg(\s_new, \noise, a = s.nextNodeID, 0, 1);


s.sendMsg(\n_set, a, \amp, 0.1);

s.sendMsg(\n_set, a, \outbus, 0);


// see which nodes are running?


s.queryAllNodes;


// use the gate arg to shut off the env, and the note


s.sendMsg(\n_set, a, \gate, 0);


s.options.numOutputBusChannels;

s.options.numInputBusChannels;

s.options.numAudioBusChannels;



b = s.audioBusAllocator.alloc(1);


s.sendMsg(\s_new, \noise, a = s.nextNodeID, 0, 1, \outbus, b);

s.queryAllNodes; // see where this is executed in the Node chain

s.sendMsg(\s_new, \filtandsin, c = s.nextNodeID, 0, 1, \inbus, b, \sinamp, 0.1, 

\filtamp, 100);

s.queryAllNodes;

s.sendMsg(\n_set, c, \sinamp, 0.01);


s.sendMsg(\n_set, c, \gate, 0);


// here, to hear the filtered noise, we need to make sure the second synth is 

// executed AFTER the first add to the TAIL of group 1


s.sendMsg(\s_new, \filtandsin, c = s.nextNodeID, 1, 1, \inbus, b, \sinamp, 0.1, 

\filtamp, 100);


s.queryAllNodes;


s.sendMsg(\n_set, c, \gate, 0);


// or more specifically, after node a


s.sendMsg(\s_new, \filtandsin, c = s.nextNodeID, 3, a, \inbus, b, \sinamp, 0.1, 

\filtamp, 100);


s.queryAllNodes;


s.sendMsg(\n_set, c, \gate, 0);


s.sendMsg(\n_set, a, \gate, 0);


// groups are another way to control a large number of synth instances at one time. 

// If we take our earlier \mysynth SynthDef and alter it to sound indefinitely, we 

// can see an example of this:

(

SynthDef(\mysynth, {arg gate = 1, freq = 300, amp = 1;

var src, env;

src = SinOsc.ar(freq, 0, 1);

env = EnvGen.kr(

Env([0, 1, 0], [0.5, 0.5], \sin, 1), // add a releaseNode

gate,

levelScale: amp,

doneAction: 2);

Out.ar(0, src * env);

}).load(s);

)

// create an array of freqs:


f = Array.fill(10, {1760.rrand(7040)});


// create a new group at the head of 1


s.sendMsg(\g_new, g = s.nextNodeID, 0, 1);


// now, create your synths inside that group 'g'


f.do({arg me; s.sendMsg(\s_new, \mysynth, s.nextNodeID, 0, g, \freq, me, 

\amp, f.size.reciprocal)});


s.queryAllNodes;


// you can now message all the synths in group g!


s.sendMsg(\n_set, g, \gate, 0);


/* Audio Busses - In.ar - AudioIn.ar */


// By default, the Server sets up a certain number of output busses and input busses 

// for use with your hardware:


s.options.numOutputBusChannels; // these are numbered 0 - 7 on my system

s.options.numInputBusChannels; // ... and 8 - 15


// However, it also creates a number of virtual busses for you to route sound with:


s.options.numAudioBusChannels;


// earlier, to route the noise, we used the Server's audioBusAllocator to set aside 

// one of these busses to route the PinkNoise through


// We used the In UGen to access that sound... In can also be used to access sound 

// from the hardware


s.audioBusAllocator.alloc(1); 

 

SynthDef(\livefilt, {arg gate = 1, inbus, amp = 1;

var in, filt, env, pan;

in = In.ar(inbus);

env = EnvGen.kr(

Env([0, 1, 0], [0.5, 0.5], \sin, 1), // add a releaseNode

gate,

levelScale: amp,

doneAction: 2);

// LFNoise2 is a cubic interpolated noise... outputs from -1 to 1 by default.

// Use mul and add args to change the range

filt = BPF.ar(in, LFNoise2.ar(0.5, 400, 1000), 0.01) * amp;

// pan the sound in the stereo field... use the env in the level field

pan = Pan2.ar(filt, LFNoise1.ar(1), env);

Out.ar(0, pan);

}).load(s);

// I have 8 output channels (0 - 7), so audio bus 8 is my first input channel


s.sendMsg(\s_new, \livefilt, a = s.nextNodeID, 0, 1, \inbus, 8 + 6, \amp, 10);


s.sendMsg(\n_set, a, \gate, 0);


// while my computer has 8 outs and ins, not all do... using the ServerOptions info 

// is safer. s.options.numOutputBusChannels ALSO gives you the first input bus 

// number!


s.sendMsg(\s_new, \livefilt, a = s.nextNodeID, 0, 1, \inbus, s.options.numOutputBusChannels, \amp, 10);


s.sendMsg(\n_set, a, \gate, 0);


// create a large number of these filts in a single group


s.sendMsg(\g_new, g = s.nextNodeID, 0, 1);

(

10.do({

s.sendMsg(\s_new, \livefilt, s.nextNodeID, 0, g, 

\inbus, s.options.numOutputBusChannels, \amp, 2)

});

);



s.sendMsg(\n_set, g, \gate, 0);


// One of the methods of UGen is the range function... for UGens that normally 

// output values between -1 and 1 you can rescale its output by using UGen.range(hi, 

// low)... so, the previous freq arg for the BPF


filt = BPF.ar(in, LFNoise2.ar(0.5, 400, 1000), 0.01) * amp;


// which output values between 600 and 1400 could also be stated as


filt = BPF.ar(in, LFNoise2.ar(0.5).range(600, 1400), 0.01) * amp;


SynthDef(\livefilt, {arg gate = 1, inbus, hi = 1000, low = 200, rq = 0.01, amp = 1;

var in, filt, env, pan;

in = In.ar(inbus);

env = EnvGen.kr(

Env([0, 1, 0], [0.5, 0.5], \sin, 1),

gate,

levelScale: amp,

doneAction: 2);

filt = BPF.ar(in, LFNoise2.ar(0.5).range(hi, low), rq) * amp;

pan = Pan2.ar(filt, LFNoise1.ar(0.2), env);

Out.ar(0, pan);

}).load(s);

s.sendMsg(\g_new, g = s.nextNodeID, 0, 1);

(

100.do({

var freqbase;

freqbase = 400.rrand(1200);

s.sendMsg(\s_new, \livefilt, s.nextNodeID, 0, g, 

\inbus, s.options.numOutputBusChannels, \amp, 0.4, \low, freqbase, 

\high, freqbase * 4, \rq, 0.01);

});

);


// change the rq of the filter

s.sendMsg(\n_set, g, \rq, 0.001);

// change the amp

s.sendMsg(\n_set, g, \amp, 10);

// free them

s.sendMsg(\n_set, g, \gate, 0);


/* For tonight


Look at


[UGens]

[Server-Command-Reference]

[Tour_of_UGens]

[Randomness]


*/