Difference between revisions of "SuperCollider Cookbook"

From CCRMA Wiki
Jump to: navigation, search
(Arrays)
(Scale and Offset (mul, add))
 
(42 intermediate revisions by the same user not shown)
Line 1: Line 1:
'''SuperCollider Cookbook by Bruno'''
+
'''SuperCollider Cookbook / Quick Reference'''
  
 
This page collects short and simple code examples of useful stuff. These are just quick "reminders" of how to do common things.
 
This page collects short and simple code examples of useful stuff. These are just quick "reminders" of how to do common things.
Line 6: Line 6:
 
'''create a buffer'''
 
'''create a buffer'''
 
<pre>
 
<pre>
~mysound = Buffer.read(s, "path/to/sound/file.wav");
+
~pizza = Buffer.read(s, "path/to/sound/file.wav");
 
</pre>
 
</pre>
 
'''simple play'''
 
'''simple play'''
<pre>{PlayBuf.ar(1, ~mysound)}.play; // number of channels and buffer</pre>
+
<pre>
 +
{PlayBuf.ar(1, ~pizza)}.play; // number of channels and buffer</pre>
 
'''get sound file info'''
 
'''get sound file info'''
<pre>[~mysound.bufnum, ~mysound.numChannels, ~mysound.path, ~mysound.numFrames];</pre>
+
<pre>[~pizza.bufnum, ~pizza.numChannels, ~pizza.path, ~pizza.numFrames];</pre>
 
'''varying speed'''
 
'''varying speed'''
<pre>{PlayBuf.ar(1, ~mysound, 2, loop: 1)}.play; // play 2x faster
+
<pre>
{PlayBuf.ar(1, ~mysound, 0.5, loop: 1)}.play; // play at half the speed
+
{PlayBuf.ar(1, ~pizza, 2, loop: 1)}.play; // play 2x faster
{PlayBuf.ar(1, ~mysound, Line.kr(0.5, 2, 10), loop: 1)}.play; // playback speed goes from 0.5 to 2 in 10 seconds</pre>
+
 
'''changing direction'''
+
{PlayBuf.ar(1, ~pizza, 0.5, loop: 1)}.play; // play at half the speed
<pre>{PlayBuf.ar(1, ~mysound, -1, loop: 1)}.play; // reverse sound
+
 
{PlayBuf.ar(1, ~mysound, -0.5, loop: 1)}.play; // play at half the speed AND reversed</pre>
+
{PlayBuf.ar(1, ~pizza, Line.kr(0.5, 2, 10), loop: 1)}.play; // playback speed goes from 0.5 to 2 in 10 seconds</pre>
 +
'''changing direction (reverse)'''
 +
<pre>
 +
{PlayBuf.ar(1, ~pizza, -1, loop: 1)}.play; // reverse sound
 +
 
 +
{PlayBuf.ar(1, ~pizza, -0.5, loop: 1)}.play; // play at half the speed AND reversed</pre>
  
 
==Play a MIDI file==
 
==Play a MIDI file==
  
 
Do this and that.
 
Do this and that.
 +
 +
==Random numbers==
 +
'''rrand'''
 +
<pre>
 +
rrand(0, 5)  // generates a random number between 0 and 5 (inclusive)
 +
</pre>
 +
 +
'''rand'''
 +
<pre>
 +
rand(10)  // generates a random integer number between 0 and 10 (10 not included)
 +
 +
rand(10.0) // generates a random decimal number between 0.0 and 10.0 (10.0 not included)
 +
 +
10.0.rand  // same as above
 +
 +
10.0.rand.round(0.01) // same as above with rounding
 +
 +
exprand(1, 10.0)  // generates a random decimal number between 0.0 and 10.0, mostly lower values
 +
</pre>
 +
Note the difference between these two:
 +
<pre>
 +
dup(rand(100), 5)  // picks a number, duplicates it
 +
 +
dup({rand(100)}, 5) // duplicates the function of picking a number
 +
</pre>
 +
'''LFNoise0, LFNoise1, LFNoise2'''
 +
 +
Random values between -1 and +1 generated at a specified rate. Compare the three:
 +
 +
<pre>
 +
{LFNoise0.ar(5000)}.plot
 +
{LFNoise1.ar(5000)}.plot
 +
{LFNoise2.ar(5000)}.plot
 +
 +
// freq - approximate rate at which to generate random values.
 +
// LFNoise0.ar(freq, mul, add)
 +
// LFNoise0.kr(freq, mul, add)
 +
 +
// One way of hearing the difference - try replacing LFNoise0 by LFNoise1 and LFNoise2:
 +
 +
{SinOsc.ar(800, mul: LFNoise0.kr(7))}.scope
 +
</pre>
 +
 +
'''Dust'''
 +
 +
Generates random impulses from 0 to +1.
 +
<pre>
 +
{Dust.ar(5000)}.plot;
 +
 +
// Dust.ar(density, mul, add)
 +
// density: average number of impulses per second
 +
</pre>
 +
 +
'''TRand'''
 +
 +
Generates a random float value in uniform distribution from lo to hi each time the trig signal changes from nonpositive to positive values:
 +
<pre>
 +
(
 +
{var trig = Dust.kr(10);
 +
  SinOsc.ar(TRand.kr(300, 3000, trig)) * 0.1
 +
}.play;
 +
)
 +
</pre>
 +
 +
==Mouse input==
 +
'''MouseX, MouseY'''
 +
<pre>
 +
(
 +
{
 +
  var freq = MouseX.kr(220, 440), amp = MouseY.kr(0, 0.3);
 +
  SinOsc.ar(freq, mul: amp)
 +
}.play
 +
)
 +
</pre>
 +
 +
==Scale and Offset (mul, add)==
 +
 +
<pre>
 +
SinOsc.kr.signalRange  // is the UGen bipolar (outputs between -1 and +1) or unipolar (outputs between 0 and +1)?
 +
 +
{SinOsc.kr(1, mul: 200, add: 1000).poll(label: "output")}.play // outputs numbers between 800-1200
 +
 +
{SinOsc.kr(1).range(800, 1200).poll(label: "output")}.play    // same result as above
 +
 +
LFPulse.kr.signalRange  // this one is unipolar
 +
 +
{LFPulse.kr(1, mul: 400, add: 800).poll(label: "output")}.play  // outputs 800-1200
 +
 +
{LFPulse.kr(1).range(800, 1200).poll(label: "output")}.play    // same result as above
 +
</pre>
 +
 
==Looping==
 
==Looping==
  
 
'''While'''
 
'''While'''
 
 
<pre>(
 
<pre>(
 
i = 0;
 
i = 0;
Line 33: Line 129:
  
 
'''For'''
 
'''For'''
 
 
<pre>for (3, 7, { arg i; i.postln }); // prints values 3 through 7</pre>
 
<pre>for (3, 7, { arg i; i.postln }); // prints values 3 through 7</pre>
  
 
'''ForBy'''
 
'''ForBy'''
 
 
<pre>forBy (0, 8, 2, { arg i; i.postln }); // prints values 0 through 8 by 2's</pre>
 
<pre>forBy (0, 8, 2, { arg i; i.postln }); // prints values 0 through 8 by 2's</pre>
  
 
'''Do'''
 
'''Do'''
 
 
<pre>
 
<pre>
 
do(9, {"Wow".postln}); // print "Wow" nine times
 
do(9, {"Wow".postln}); // print "Wow" nine times
 +
 
9.do({"Wow".postln}); // same as above
 
9.do({"Wow".postln}); // same as above
 +
 
5.do({ arg item; item.postln }); // iterates from zero to four
 
5.do({ arg item; item.postln }); // iterates from zero to four
 +
 
do(5, {arg item; item.postln}); // same as above
 
do(5, {arg item; item.postln}); // same as above
 
</pre>
 
</pre>
Line 51: Line 147:
 
<pre>
 
<pre>
 
do(9, {arg whatevername; whatevername.postln}); // give whatever name you want to the arg of 'do'
 
do(9, {arg whatevername; whatevername.postln}); // give whatever name you want to the arg of 'do'
 +
 
do([9, 8, 3, 5], {arg whatevername; whatevername.postln}); // elements from collection (not a counter)
 
do([9, 8, 3, 5], {arg whatevername; whatevername.postln}); // elements from collection (not a counter)
 +
 
do([9, 8, 3, 5], {arg whatevs1, whatevs2; [whatevs2, whatevs1].postln}); // second argument works as a counter
 
do([9, 8, 3, 5], {arg whatevs1, whatevs2; [whatevs2, whatevs1].postln}); // second argument works as a counter
 
</pre>
 
</pre>
Line 57: Line 155:
 
<pre>
 
<pre>
 
["zero", "first", "second", "third", 500].do({ arg item, i; [i, item].postln; });
 
["zero", "first", "second", "third", 500].do({ arg item, i; [i, item].postln; });
 +
 
do(["zero", "first", "second", "third", 500], {arg item, i; [i, item].postln});
 
do(["zero", "first", "second", "third", 500], {arg item, i; [i, item].postln});
 +
 
"you".do({ arg item; item.postln }); // a String is a collection of characters
 
"you".do({ arg item; item.postln }); // a String is a collection of characters
 +
 
'they'.do({ arg item; item.postln }); // a Symbol is a singular item
 
'they'.do({ arg item; item.postln }); // a Symbol is a singular item
 +
 
(8..20).do({ arg item; item.postln }); // iterates from eight to twenty 
 
(8..20).do({ arg item; item.postln }); // iterates from eight to twenty 
 +
 
(8,10..20).do({ arg item; item.postln }); // iterates from eight to twenty, with stepsize two
 
(8,10..20).do({ arg item; item.postln }); // iterates from eight to twenty, with stepsize two
 
</pre>
 
</pre>
 
  
 
==If...Else==
 
==If...Else==
Line 98: Line 200:
 
a = [10, 11, 12, 13, 14, 15, 16, 17]
 
a = [10, 11, 12, 13, 14, 15, 16, 17]
  
a.scramble
+
a.reverse  // reverse
 +
 
 +
a.scramble // scramble
  
 
a.choose  // picks one element at random
 
a.choose  // picks one element at random
Line 112: Line 216:
 
a ++ 999  // ++ (concatenate) adds something to the end of the array
 
a ++ 999  // ++ (concatenate) adds something to the end of the array
  
a ++ \hi  // Check out the difference between this and the next example
+
a ++ \hi  // a Symbol is a single character
  
a ++ "hi" // NOT the same as above;  
+
a ++ 'hi' // same as above
 +
 
 +
a ++ "hi" // a String is a collection of characters
 +
 
 +
a.insert(5, "wow") // inserts "wow" at position 5, pushes other items forward
 +
 
 +
a // evaluate this and see that none of the above operations actually changed the original array
 +
 
 +
a.put(2, "oops") // put "oops" at index 2 (destructive; evaluate line above again to check)
 +
 
 +
a.add(44)    // adds new element at the end of the array (permanently)
 +
 
 +
a.do({arg whatever, blech; [blech, whatever].postln}) // how to "do" an array
 +
 
 +
b = Array.series(5, 1); // create an array with 5 sequential numbers, starting at 1)
 +
 
 +
b.mirror  // makes it a palindrome
 +
 
 +
b.permute(3) // permute: item in position 3 goes to position 0, and vice-versa
 +
 
 +
b.powerset // returns all possible combinations of the array's elements
 +
 
 +
Array.fill(10, "same"); // Another way of building an array
 +
 
 +
Array.fill(10, {arg counter; (counter + 1)*440});
 +
 
 +
</pre>
 +
 
 +
More info: http://sc3howto.blogspot.com/2010/05/arrays.html
 +
 
 +
==poll and scope==
 +
Check what's going on with your UGens:
 +
<pre>
 +
{SinOsc.kr(1/2).round(0.01).poll(label: "watchThis")}.scope
 
</pre>
 
</pre>
  

Latest revision as of 22:32, 10 June 2011

SuperCollider Cookbook / Quick Reference

This page collects short and simple code examples of useful stuff. These are just quick "reminders" of how to do common things.

Play a sound file, vary speed, reverse

create a buffer

~pizza = Buffer.read(s, "path/to/sound/file.wav");

simple play

{PlayBuf.ar(1, ~pizza)}.play; // number of channels and buffer

get sound file info

[~pizza.bufnum, ~pizza.numChannels, ~pizza.path, ~pizza.numFrames];

varying speed

{PlayBuf.ar(1, ~pizza, 2, loop: 1)}.play; // play 2x faster

{PlayBuf.ar(1, ~pizza, 0.5, loop: 1)}.play; // play at half the speed

{PlayBuf.ar(1, ~pizza, Line.kr(0.5, 2, 10), loop: 1)}.play; // playback speed goes from 0.5 to 2 in 10 seconds

changing direction (reverse)

{PlayBuf.ar(1, ~pizza, -1, loop: 1)}.play; // reverse sound

{PlayBuf.ar(1, ~pizza, -0.5, loop: 1)}.play; // play at half the speed AND reversed

Play a MIDI file

Do this and that.

Random numbers

rrand

rrand(0, 5)   // generates a random number between 0 and 5 (inclusive)

rand

rand(10)  // generates a random integer number between 0 and 10 (10 not included)

rand(10.0) // generates a random decimal number between 0.0 and 10.0 (10.0 not included)

10.0.rand  // same as above

10.0.rand.round(0.01) // same as above with rounding

exprand(1, 10.0)  // generates a random decimal number between 0.0 and 10.0, mostly lower values

Note the difference between these two:

dup(rand(100), 5)   // picks a number, duplicates it

dup({rand(100)}, 5) // duplicates the function of picking a number

LFNoise0, LFNoise1, LFNoise2

Random values between -1 and +1 generated at a specified rate. Compare the three:

{LFNoise0.ar(5000)}.plot
{LFNoise1.ar(5000)}.plot
{LFNoise2.ar(5000)}.plot

// freq - approximate rate at which to generate random values.
// LFNoise0.ar(freq, mul, add)
// LFNoise0.kr(freq, mul, add)

// One way of hearing the difference - try replacing LFNoise0 by LFNoise1 and LFNoise2:

{SinOsc.ar(800, mul: LFNoise0.kr(7))}.scope

Dust

Generates random impulses from 0 to +1.

{Dust.ar(5000)}.plot;

// Dust.ar(density, mul, add)
// density: average number of impulses per second

TRand

Generates a random float value in uniform distribution from lo to hi each time the trig signal changes from nonpositive to positive values:

(
 {var trig = Dust.kr(10);
  SinOsc.ar(TRand.kr(300, 3000, trig)) * 0.1
 }.play;
)

Mouse input

MouseX, MouseY

(
 {
  var freq = MouseX.kr(220, 440), amp = MouseY.kr(0, 0.3);
  SinOsc.ar(freq, mul: amp)
 }.play
)

Scale and Offset (mul, add)

SinOsc.kr.signalRange  // is the UGen bipolar (outputs between -1 and +1) or unipolar (outputs between 0 and +1)?

{SinOsc.kr(1, mul: 200, add: 1000).poll(label: "output")}.play // outputs numbers between 800-1200

{SinOsc.kr(1).range(800, 1200).poll(label: "output")}.play     // same result as above

LFPulse.kr.signalRange  // this one is unipolar

{LFPulse.kr(1, mul: 400, add: 800).poll(label: "output")}.play  // outputs 800-1200

{LFPulse.kr(1).range(800, 1200).poll(label: "output")}.play     // same result as above

Looping

While

(
i = 0;
while ( { i < 5 }, { i = i + 1; "boing".postln });
)

For

for (3, 7, { arg i; i.postln }); // prints values 3 through 7

ForBy

forBy (0, 8, 2, { arg i; i.postln }); // prints values 0 through 8 by 2's

Do

do(9, {"Wow".postln}); // print "Wow" nine times

9.do({"Wow".postln}); // same as above

5.do({ arg item; item.postln }); // iterates from zero to four

do(5, {arg item; item.postln}); // same as above

Compare the output of these:

do(9, {arg whatevername; whatevername.postln}); // give whatever name you want to the arg of 'do'

do([9, 8, 3, 5], {arg whatevername; whatevername.postln}); // elements from collection (not a counter)

do([9, 8, 3, 5], {arg whatevs1, whatevs2; [whatevs2, whatevs1].postln}); // second argument works as a counter

More examples:

["zero", "first", "second", "third", 500].do({ arg item, i; [i, item].postln; });

do(["zero", "first", "second", "third", 500], {arg item, i; [i, item].postln});

"you".do({ arg item; item.postln }); // a String is a collection of characters

'they'.do({ arg item; item.postln }); // a Symbol is a singular item

(8..20).do({ arg item; item.postln }); // iterates from eight to twenty 

(8,10..20).do({ arg item; item.postln }); // iterates from eight to twenty, with stepsize two

If...Else

Syntax is if(condition, {true action}, {false action}). Examples:

if(10 == 10, {"10 is indeed equal to 10"}, {"false"})

if(condition, {true action}, {false action});

if(10 == 10, {"10 is indeed equal to 10"}, {"false"})

if((1 < 20).and(1.8.isInteger), {"very true"}, {"hmmm..."})

10.do({arg count; [count, if(count.odd, {"odd"}, {"even"})].postln})

(
84.do({arg count; if([0, 4, 7].includes(count%12), 
	{count.post; " is part of a C triad.".postln}, 
	{count.post; " is not part of a C triad".postln})})
)

50.do({if(1.0.rand.round(0.01).post > 0.5,  {" > 0.5".postln}, {" < 0.5".postln})})

50.do({if(1.0.rand > 0.5,  {"play a note".postln}, {"rest".postln})})

50.do({if(0.5.coin, {"play a note".postln}, {"rest".postln})}) // same as above

if((10.odd).or(10 < 20), {"true".postln}, {"false".postln})

Arrays

Various array operations:

a = [10, 11, 12, 13, 14, 15, 16, 17]

a.reverse  // reverse

a.scramble // scramble

a.choose  // picks one element at random

a.size	  // returns size of array

a.at(0)   // retrieves item at specified position

a[0]	  // same as above

a.wrapAt(9) // retrives item at specified position, wrapping around if > a.size

a ++ 999  // ++ (concatenate) adds something to the end of the array

a ++ \hi  // a Symbol is a single character

a ++ 'hi' // same as above

a ++ "hi" // a String is a collection of characters

a.insert(5, "wow") // inserts "wow" at position 5, pushes other items forward

a // evaluate this and see that none of the above operations actually changed the original array

a.put(2, "oops") // put "oops" at index 2 (destructive; evaluate line above again to check)

a.add(44)    // adds new element at the end of the array (permanently) 

a.do({arg whatever, blech; [blech, whatever].postln}) 	// how to "do" an array

b = Array.series(5, 1); // create an array with 5 sequential numbers, starting at 1)

b.mirror  // makes it a palindrome

b.permute(3) // permute: item in position 3 goes to position 0, and vice-versa 

b.powerset // returns all possible combinations of the array's elements

Array.fill(10, "same"); // Another way of building an array

Array.fill(10, {arg counter; (counter + 1)*440}); 

More info: http://sc3howto.blogspot.com/2010/05/arrays.html

poll and scope

Check what's going on with your UGens:

{SinOsc.kr(1/2).round(0.01).poll(label: "watchThis")}.scope

Amplitude Modulation

Frequency Modulation

Additive Synthesis

Subtractive Synthesis