//-- Switch from PureData! (or MAX/MSP for that matter)
//-- workshop 110513, organized by l'ull cec [ http://lullcec.org ] @hangar
//-- beginner-intermediate level
//--running code...
//fn+return - for osx
//ctrl+return - for win
//c-c, c-c - for emacs
1+10
1/40
3+4+5
( //select all inbetween () and evaluate
var a= 5;
a+100;
)
//--making sound...
s.boot
//panic stop all sound keyboard shortcuts
//cmd+. - for osx
//alt+. - for win
//c-c, c-s - for emacs
Ndef(\mysine).play
Ndef(\mysine, {SinOsc.ar(500)})
Ndef(\mysine).stop
//multi channel expansion
Ndef(\mysaw).play
Ndef(\mysaw, {Saw.ar([400, 404])}) //two sawtooth oscillators
Ndef(\mysaw).stop
Ndef(\mysaw).play
Ndef(\mysaw, {Saw.ar([400, 404, 500])})
Ndef(\mysaw).stop
//mysaw ndef is stereo by default so channels will wrap left, right, left, right etc
Ndef(\mysaw).play
Ndef(\mysaw, {Saw.ar([400, 404, 500, 505, 600, 606], 0.5)})
Ndef(\mysaw).stop
//0.5 is amplitude. we need to scale down the signal to not distort
{100.rand+500}.dup(10) //generate array with 10 random integers between 500 and 599
Ndef(\mysaw).play
Ndef(\mysaw, {Saw.ar({500.rand+600}.dup(20), 0.1)})
Ndef(\mysaw, {Saw.ar({500.rand+600}.dup(20), 0.1)})
Ndef(\mysaw, {Saw.ar({500.rand+600}.dup(20), 0.1)})
Ndef(\mysaw).stop
//the clicks are phase alignment due to integer numbers.
//try same but with floats...
Ndef(\mysaw).play
Ndef(\mysaw, {Saw.ar({500.0.rand+600}.dup(20), 0.1)})
Ndef(\mysaw, {Saw.ar({500.0.rand+600}.dup(20), 0.1)})
Ndef(\mysaw).stop
//and with different number of sawtooth oscillators...
Ndef(\mysaw).play
Ndef(\mysaw, {Saw.ar({500.0.rand+600}.dup(4), 0.2)})
Ndef(\mysaw, {Saw.ar({500.0.rand+600}.dup(30), 0.1)})
Ndef(\mysaw, {Saw.ar({500.0.rand+600}.dup(60), 0.07)})
Ndef(\mysaw).stop
//note how we compensate for amplitude due to the shifting number of oscillators
//and amplitude (mul) argument can also be an array...
Ndef(\mysaw).play
Ndef(\mysaw, {Saw.ar({500.0.rand+600}.dup(10), [0.1, 0.2, 0.05])})
Ndef(\mysaw, {Saw.ar({500.0.rand+600}.dup(10), {0.2.rand}.dup(10))})
Ndef(\mysaw).stop
//set a cross fade time
Ndef(\mysaw).fadeTime= 2 //2 seconds
Ndef(\mysaw).play
Ndef(\mysaw, {Saw.ar({500.0.rand+600}.dup(20), 0.1)})
Ndef(\mysaw, {Saw.ar({500.0.rand+600}.dup(10), 0.12)})
Ndef(\mysaw, {Saw.ar({500.0.rand+600}.dup(30), 0.08)})
Ndef(\mysaw).stop
//last with different range (run each line multiple times)
0.5.rrand(1.0) //range random between 0.5 and 1.0
Ndef(\mysaw).play
Ndef(\mysaw, {Saw.ar({50.0.rand+1000}.dup(40), {0.2.rand}.dup(40))})
Ndef(\mysaw, {Saw.ar({50.0.rrand(1000)}.dup(40), {0.2.rand}.dup(40))})
Ndef(\mysaw, {Saw.ar({150.0.rrand(5000)}.dup(50), 0.1)})
Ndef(\mysaw, {Saw.ar({350.0.rrand(400)}.dup(30), 0.15)})
Ndef(\mysaw).stop
//--draw the synthesis network
Ndef(\mysaw).source.draw //needs graphviz and rd_dot quark
//install the rd_dot quark with this command
Quarks.install("rd_dot")
//download and install graphviz separately from
http://www.pixelglow.com/graphviz/
//(version 2.26 works well on my mac osx 10.5.8)
//--more static sounds
Ndef(\pad).play
Ndef(\pad, {SinOsc.ar({300.rrand(1600)}.dup(10), 0, 0.1)})
Ndef(\pad).fadeTime= 5
//now modulate with another sinosc instead of static 0.1 amplitude (run multiple times)
Ndef(\pad, {SinOsc.ar({300.rrand(1600)}.dup(10), 0, 0.1+SinOsc.ar({0.01.rrand(0.2)}.dup(10), 0, 0.1))})
Ndef(\pad, {SinOsc.ar({400.rrand(700)}.dup(15), 0, 0.1+SinOsc.ar({0.01.rrand(1.0)}.dup(15), 0, 0.1))})
Ndef(\pad).source.draw
Ndef(\pad).stop
//--recording soundfiles
//just click the record button in the server gui window
thisProcess.platform.recordingsDir //where files are stored by default
//optional: set a different path if you prefer
thisProcess.platform.recordingsDir = "/Users/ifields/Desktop/"
//and set different file header, sampleformat if you prefer
s.recHeaderFormat= "WAV"
s.recSampleFormat= "int16"
//but it's recommended to use the default 32bit floatingpoint aiff
//--level meters display
s.meter
//handy gui to see in and outgoing levels
//can also be activated by bringing the server gui window to the front and typing the letter 'l'
//--recommended patch setup
//save the following in a seperate document and use as template for you own patches. includes some handy gui for playing back your sounds
s.boot
s.meter
NdefMixer(s)
Ndef(\pad).play
Ndef(\pad, {SinOsc.ar({300.rrand(1600)}.dup(10), 0, 0.1+SinOsc.ar({0.1.rrand(0.5)}.dup(10), 0, 0.1))})
Ndef(\pad).fadeTime= 5
Ndef(\pad).vol= 0.4
Ndef(\pad).stop(6) //fade out over 6 sec
//--envelopes...
Env.perc(0.1, 0.5).plot
Env.perc(0.1, 0.5, 0.6).plot //goes from 0 to 0.6 (plot will look similar due to normalisation)
Env.perc(0.1, 0.5, 0.6, 0).plot //fourth arg is curve
Env.perc(0.1, 0.5, 0.6, 3).plot
Env.perc(0.1, 0.5, 0.6, -4).plot //-4 is the default
Env.sine(0.2).plot
Env.adsr(0.01, 0.2, 0.75, 0.1, 0.6, -4).plot
//see Env helpfile for more
//manually set levels, times, curves
Env([0, 1, 0], [0.2, 0.6], [0, -4]).plot
Env([0, 1, 0.3, 0.8, 0.1, 0], [0.2, 0.6, 0.1, 0.6, 2], [0, -4, 2.5, 3, 5]).plot
//always one more value in the levels array. this is the init starting value.
//there is also .test for quickly listening to the envelope
Env([0, 1, 0.2, 0.3, 0], [0.2, 0.1, 0.1, 0.6], -3).plot.test
//--playing sounds that start and stop
Ndef(\myping).play
Ndef(\myping, {EnvGen.ar(Env.perc(0.05, 2.5), doneAction:2)*SinOsc.ar([400, 404])})
Ndef(\myping).spawn //will re-trigger
//--arguments
//arguments are sort of the equivalent of inlets in puredata
Ndef(\myping, {|freq= 400| EnvGen.ar(Env.perc(0.05, 2.5), doneAction:2)*SinOsc.ar([freq, freq+4])})
//compare with ndef above. the only thing we added was freq. should sound the same
//but now we re-trigger with different values for the freq argument
Ndef(\myping).spawn([\freq, 600.rrand(800)])
Ndef(\myping).spawn([\freq, 600.rrand(800)])
Ndef(\myping).spawn([\freq, 600.rrand(800)])
//add 2 more arguments: amp, pan
Ndef(\myping, {|freq= 400, amp= 0.5, pan= 0| EnvGen.ar(Env.perc(0.05, 2.5, amp), doneAction:2)*Pan2.ar(Mix(SinOsc.ar([freq, freq+4])), pan)})
Ndef(\myping).source.draw
Ndef(\myping).spawn([\freq, 600.rrand(800), \amp, 0.6.rand, \pan, -1.0.rrand(1.0)])
Ndef(\myping).spawn([\freq, 600.rrand(800), \amp, 0.6.rand, \pan, -1.0.rrand(1.0)])
Ndef(\myping).spawn([\freq, 600.rrand(800), \amp, 0.6.rand, \pan, -1.0.rrand(1.0)])
//add even 2 more arguments (atk and rel)
Ndef(\myping, {|freq= 400, amp= 0.5, pan= 0, atk= 0.05, rel= 2.5| EnvGen.ar(Env.perc(atk, rel, amp), doneAction:2)*Pan2.ar(Mix(SinOsc.ar([freq, freq+4])), pan)})
Ndef(\myping).spawn([\freq, 600.rrand(800), \amp, 0.6.rand, \pan, -1.0.rrand(1.0), \atk, 0.05.rand, \rel, 0.8.rand])
//or same but using midi notes as frequencies
60.rrand(80).midicps
Ndef(\myping).spawn([\freq, 60.rrand(80).midicps, \amp, 0.6.rand, \pan, -1.0.rrand(1.0), \atk, 0.05.rand, \rel, 0.8.rand])
//--sequencing...
(
Tdef(\metro, {loop{
Ndef(\myping).spawn([\freq, 60.rrand(80).midicps, \amp, 0.4.rand, \pan, -1.0.rrand(1.0), \atk, 0.05.rand, \rel, 0.4.rand]);
0.1.wait;
}}).play;
)
Tdef(\metro).stop
//using arrays with counter i indexing
(
Tdef(\metro, {var i= 0; loop{
Ndef(\myping).spawn([\freq, [50, 60, 55, 53, 80, 82].wrapAt(i).midicps, \amp, [0, 0.2, 0.1, 0.2, 0.3].wrapAt(i), \pan, -1.0.rrand(1.0), \atk, 0.05.rand, \rel, 0.4.rand]);
0.1.wait;
i= i+1;
}}).play;
)
//it's possible to change the sound while sequencer is running
Ndef(\myping, {|freq= 400, amp= 0.5, pan= 0, atk= 0.05, rel= 2.5| EnvGen.ar(Env.perc(atk, rel, amp), doneAction:2)*Pan2.ar(Mix(SinOsc.ar([freq, freq+4])+WhiteNoise.ar(0.3)), pan)})
//also one can change the sequencer without stopping
(
Tdef(\metro, {var i= 0; loop{
Ndef(\myping).spawn([\freq, [60, 80].wrapAt(i).midicps, \amp, [0, 0.1, 0.2, 0.05, 0.1].wrapAt(i), \pan, -1.0.rrand(1.0), \atk, 0.02.rand, \rel, [0.3, 0.1].wrapAt(i)]);
[0.125, 0.125, 0.125, 0.125, 0.125, 1/16, 1/16].wrapAt(i).wait;
i= i+1;
}}).play;
)
Tdef(\metro).stop
//--new example
Ndef(\snare).play
Ndef(\snare,{|amp= 0.1, atk= 0.01, rel= 0.1, pan= 0| Pan2.ar(WhiteNoise.ar*EnvGen.ar(Env.perc(atk, rel, amp), doneAction:2), pan)})
Ndef(\drum).play
Ndef(\drum, {|amp= 0.5, atk= 0.03, rel= 0.5, pan= 0, freq= 100| Pan2.ar(Mix(SinOsc.ar([freq, freq+4]))*EnvGen.ar(Env.perc(atk, rel, amp), doneAction:2), pan)})
Ndef(\hat).play
Ndef(\hat, {|amp= 0.1, atk= 0.02, rel= 0.1, pan= 0, freq= 4000| Pan2.ar(BPF.ar(GrayNoise.ar, freq, 0.2, 10)*EnvGen.ar(Env.perc(atk, rel, amp), doneAction:2), pan)})
Tdef(\seq).play(quant:1)
Tdef(\seq, {loop{Ndef(\drum).spawn; 1.wait}})
Tdef(\seq2).play(quant:1)
Tdef(\seq2, {loop{Ndef(\hat).spawn; 2.wait}})
Tdef(\seq3).play(quant:1)
Tdef(\seq3, {loop{Ndef(\snare).spawn([\rel, 0.5.rand]); 4.wait}})
Tdef(\seq, {var i= 0; loop{Ndef(\drum).spawn([\freq, [60, 60, 160, 180, 180, 190].wrapAt(i)]); [0.5, 0.5, 0.5, 0.125, 0.125].wrapAt(i).wait; i= i+1}})
Tdef(\seq, {var i= 0; loop{Ndef(\drum).spawn([\freq, [60, 60, 160, 180, 180, 190].wrapAt(i), \pan, [-1, 1].wrapAt(i)]); [0.5, 0.5, 0.5, 0.125, 0.125].wrapAt(i).wait; i= i+1}})
Tdef(\seq2, {loop{Ndef(\hat).spawn([\freq, 3000.rrand(8000), \amp, 0.15.rand]); 0.125.wait; }})
TempoClock.default.tempo= 114/60 //114 bpm
TempoClock.default.tempo= 80/60 //80 bpm
Tdef(\seq3, {var i= 0; loop{Ndef(\snare).spawn([\amp, [0.2, 0.1, 0.05, 0].wrapAt(i), \pan, -0.3.rrand(0.3)]); 0.25.wait; i= i+1}})
Tdef(\seq, {var i= 0; loop{Ndef(\drum).spawn([\freq, [100, 200, 300, 400, 500, 500.rrand(1500)].wrapAt(i), \pan, [-0.8, 0, 0.8].wrapAt(i), \atk, 0.005, \rel, 0.1]); [0.5, 0.5, 0.5, 0.125, 0.125].wrapAt(i).wait; i= i+1}})
Tdef(\seq4).play(quant:1) //different tdef using same ndef (drum)
Tdef(\seq4, {var i= 0; loop{Ndef(\drum).spawn([\freq, 50, \atk, 0, \rel, 0.1, \amp, 0.7]); 0.5.wait; i= i+1}})
Tdef(\seq2).stop
Tdef(\seq3).stop
Tdef(\seq4).stop
Tdef(\seq).stop
Tdef(\seq).play(quant:1)
Tdef(\seq2).play(quant:1)
Tdef(\seq4).play(quant:1)
Tdef(\seq3).play(quant:1)
Tdef(\seq).stop
Tdef(\seq4).stop
Tdef(\seq3).stop
Tdef(\seq2).stop
//--additional tips and tricks
OSCresponder //receive osc data over network
NetAddr //send osc data
//some granulators that comes with sc
TGrains, GrainBuf, GrainFM, GrainIn, GrainSin
//package manager gui to install more extras
Quarks.gui
SynthDefPool //quark with premade instruments
sc3-plugins //separate download plugins (recommeded - lots of extras here)
//different speaker setups, ambisonics etc
VBAP, PanAz, BiPanB2
//using your own soundcard you will need to set your own ServerOptions
Server.default.options.dump //list current server options
//see helpfile: using the startup file
//there is built in simple gui control for ndefs
//just do .edit on an existing ndef. click play button to start and send to retrigger in case the ndef uses an envelope
Ndef(\myping).edit
Ndef(\snare).edit
//some sc tweets (little pieces that fit in 140 characters)
http://supercollider.sourceforge.net/sc140/
http://fredrikolofsson.com/f0blog/?q=node/478
//openobject quark to easily connect puredata or maxmsp with supercollider
http://fredrikolofsson.com/f0blog/?q=node/401
//--learning more...
//sample chapter from the scbook
http://supercolliderbook.net/wilsondescrivanch3.pdf
//and the sc book itself is of course recommended reading
//last check this page for a collection of links
http://supercollider.sourceforge.net/learning/