<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-10668379</id><updated>2012-01-18T20:08:40.547-05:00</updated><category term='while'/><category term='asynchronous'/><category term='pbind'/><category term='synthdef'/><category term='howto'/><category term='stream'/><category term='example'/><category term='tutorial'/><category term='wait'/><category term='Prout'/><category term='playbuf'/><category term='gui'/><category term='control structures'/><category term='array'/><category term='SuperCollider'/><category term='Pfunc'/><category term='buffer'/><category term='data structures'/><category term='IdentityDictionary'/><category term='functional notation'/><category term='task'/><category term='bbcut'/><category term='function'/><category term='server'/><category term='Routine'/><category term='pattern'/><category term='sc'/><category term='timing'/><category term='Event'/><category term='boolean'/><category term='if'/><category term='envelopes'/><category term='variables'/><category term='conductor'/><title type='text'>How to Program in SuperCollider</title><subtitle type='html'>A very rarely updated guide to Supercollider programming.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-10668379.post-8989329876647182739</id><published>2010-10-13T16:03:00.002-04:00</published><updated>2010-10-13T17:14:47.572-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='bbcut'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Getting Started with BBCut2</title><content type='html'>&lt;h3&gt;Installing&lt;/h3&gt;
&lt;p&gt;BBCut2 is a nifty library for doing break beat cutting.  To use it, you must first install it. It is not available as a quark, alas.  To get the library, download it from &lt;a href="http://www.cogs.susx.ac.uk/users/nc81/bbcut2.html"&gt;http://www.cogs.susx.ac.uk/users/nc81/bbcut2.html&lt;/a&gt;. Then unzip it.  Inside, you will find several directories.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Move the "bbcut2 classes" directory to &lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;~/Library/Application\ Support/SuperCollider/Extensions&lt;/span&gt; .  That tilda represents your home directory, so if your user name is nicole, you would put the file in &lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;/Users/nicole/Library/Application\ Support/SuperCollider/Extensions&lt;/span&gt; . If the Extensions directory does not exist on your system, then create it.&lt;/li&gt;
&lt;li&gt;Put the "bbcut2 help" directory inside the classes directory that you just moved.&lt;/li&gt;
&lt;li&gt;Put the "bbcut2 ugens" directory in&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; ~/Library/Application\ Support/SuperCollider/Extensions/sc3-plugins&lt;/span&gt; . If this directory does not exist, then create it.&lt;/li&gt;
&lt;li&gt;Take the contents of the "bbcut2 sounds" directory and put them in the sounds folder with your SuperCollider application.  so if you have SuperCollider in /Applications, you would put the contents of "bbcut2 sounds" in &lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;/Applications/SuperCollider/sounds&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then, re-start SuperCollider. Depending on what version of SC you have, you may have duplicate classes.  If you do, there will be errors in the post window.  If you see that this is a problem for you, go find the files in the BBCut classes and delete them, making sure to keep the other copy.  The error message will tell you where to find the files and which ones they are.&lt;/p&gt;

&lt;h3&gt;The Clock&lt;/h3&gt;
&lt;p&gt;BBCut relies on a clock.  When I'm coding, I usually base the clock off the default clock:&lt;/p&gt;
&lt;pre&gt;
 TempoClock.default.tempo_(180/60);
 clock = ExternalClock(TempoClock.default); 
 clock.play;  
&lt;/pre&gt;
&lt;p&gt;The tempo is defined as beats per second. That's beats per minute, divided by 60 seconds. In the above example, the clock rate is 180 bpm, which is then divided by 60 to set the tempo.  If you wanted a clock that was 60 bpm, you would set tempo_(60/60), or for 103 bpm, it would be tempo_(103/60)&lt;/p&gt;
&lt;p&gt;BBCut uses an ExternalClock, which uses a TempoClock, so in the above example, I give it the default TempoClock.  I don't have to use the default one, but could declare a new one if I wanted: &lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;clock = ExternalClock(TempoClock(182/60));&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The next step is to the clock to play. If you forget this step (which I often do), nothing happens later on.  Telling the clock to play is important.  BBCut relies on this clock.&lt;/p&gt;

&lt;h3&gt;Working with Buffers&lt;/h3&gt;

&lt;p&gt;There is a special sort of &lt;a href="http://sc3howto.blogspot.com/2010/10/more-buffers.html"&gt;buffer&lt;/a&gt; used by BBCut, called a &lt;b&gt;BBCutBuffer&lt;/b&gt;.  The constructor for this takes two arguments.  The first is a string which should contain the path and file name of the file.  The second argument is the number of beats in the file.  For example, we could open one of the sound files that came with BBCut:&lt;/p&gt;
&lt;pre&gt;
 sf= BBCutBuffer("sounds/break",8);
&lt;/pre&gt;
&lt;p&gt;We need to wait for the Buffer to load before we can start using it.  One way to do that is to put the code that relies on the Buffer into a Routine. And then, we can tell the Routine to wait until the server is ready to carry on.&lt;/p&gt;
&lt;pre&gt;
 sf= BBCutBuffer("sounds/break",8);

 Routine.run({
  s.sync; // this tells the task to wait
  // below here, we know all out Buffers are loaded
   . . .
 })
&lt;/pre&gt;
&lt;p&gt;Now we can tell BBCut that we want to cut up a buffer and get it to start doing that.&lt;/p&gt;
&lt;pre&gt;
  cut = BBCut2(CutBuf3(sf)).play(clock);
&lt;/pre&gt;
&lt;p&gt;BBCut2 is the class that runs everything, so we make a new one of these.  Inside, we pass a &lt;b&gt;CutBuf&lt;/b&gt;, which is a class that handles Buffer cutting.  We tell the BBCut2 object to play, using the clock.  This starts something going.&lt;/p&gt;
&lt;p&gt;Cutting is much more interesting if it can jump around in the buffer a bit:&lt;/p&gt;
&lt;pre&gt;
  cut = BBCut2(CutBuf3(sf, 0.4)).play(clock);
&lt;/pre&gt;
&lt;p&gt;We can specify the chances of a random cut. 0.0 means a 0% chance and 1.0 is a 100% chance.  We can set the chances at any numbers between and including 0.0 to 1.0.  If we want a 40% chance of a random jump, we would use 0.4.&lt;/p&gt;

&lt;h3&gt;Cut Procedures&lt;/h3&gt;
&lt;p&gt;We can tell BBCut to use one of several &lt;b&gt;cut procedures&lt;/b&gt;. The original one is called BBCutProc11.&lt;/p&gt;
&lt;pre&gt;
  cut = BBCut2(CutBuf3(sf, 0.4), BBCutProc11.new).play(clock);
&lt;/pre&gt;
&lt;p&gt;It can take several arguments, which are: sdiv, barlength, phrasebars, numrepeats, stutterchance,
  stutterspeed, stutterarea&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;sdiv - is subdivision. 8 subdivsions gives quaver (eighthnote) resolution.&lt;/li&gt;
  &lt;li&gt;barlength - is normally set to 4 for 4/4 bars. If you give it 3, you get 3/4&lt;/li&gt;
  &lt;li&gt;phrasebars - the length of the current phrase is barlength * phrasebars&lt;/li&gt;
  &lt;li&gt;numrepeats - Total number of repeats for normal cuts. So 2 corresponds to a
  particular size cut at one offset plus one exact repetition.&lt;/li&gt;
  &lt;li&gt;stutterchance - the tail of a phrase has this chance of becoming a repeating
  one unit cell stutter (0.0 to 1.0)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more on this, see the helpfile.  In general, the cut procedures are very well documented.  Here's an example of passing some arguments to BBCutProc11:&lt;/p&gt;
&lt;pre&gt;
  cut = BBCut2(CutBuf3(sf, 0.4), BBCutProc11(8, 4, 2, 2, 0.2).play(clock)
&lt;/pre&gt;
&lt;p&gt;We can tell the cutter to stop playing, or free it&lt;/p&gt;
&lt;pre&gt;
  cut.stop;
  cut.free;
&lt;/pre&gt;
&lt;p&gt;Putting all of what we have so far together, we get:&lt;/p&gt;
&lt;pre&gt;
(
 var clock, sf, cut;
 
 TempoClock.default.tempo_(180/60);
 clock = ExternalClock(TempoClock.default); 
 clock.play;
 
 sf= BBCutBuffer("sounds/break",8);

 Routine.run({
  s.sync; // this tells the task to wait

  cut = BBCut2(CutBuf3(sf, 0.4), BBCutProc11(8, 4, 2, 2, 0.2)).play(clock);

  30.wait; //  // let things run for 30 seconds
  
  cut.stop;
  cut.free;
 })
)
&lt;/pre&gt;
&lt;p&gt;There are several other cut procedures, like WarpCutProc1 or SQPusher1 or SQPusher2. If you go look at the main helpfile, you can find which ones are available.  This file is called BBCut2Wiki  (and is found at &lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;~/Library/Application\ Support/SuperCollider/Extensions/bbcut2\ classes/bbcut2\ help/BBCut2Wiki.help.rtf&lt;/span&gt; or by selecting the text BBCut2Wiki and typing apple-d )&lt;/p&gt;

&lt;h3&gt;Polyphony&lt;/h3&gt;
&lt;p&gt;The clock keeps things in sync, so you can run two different cut procedures at the same time and have things line up in time.&lt;/p&gt;
&lt;pre&gt;
  cut1 = BBCut2(CutBuf3(sf, 0.4), BBCutProc11(8, 4, 2, 2, 0.2)).play(clock);
  cut2 = BBCut2(CutBuf3(sf, 0.2), WarpCutProc1.new).play(clock);
&lt;/pre&gt;

&lt;p&gt;You can even mix and match sound files:&lt;/p&gt;
&lt;pre&gt;
(
 var clock, sf1, sf2, cut1, cut2, group;
 
 TempoClock.default.tempo_(180/60);
 clock = ExternalClock(TempoClock.default); 
 clock.play;
 
 sf1= BBCutBuffer("sounds/break",8);
 sf2= BBCutBuffer("sounds/break2",4);

 Routine.run({
  s.sync; // this tells the task to wait

  cut1 = BBCut2(CutBuf3(sf1, 0.4), BBCutProc11(8, 4, 2, 2, 0.2)).play(clock);
  cut2 = BBCut2(CutBuf3(sf2, 0.2), WarpCutProc1.new).play(clock);

  15.wait;
  cut1.stop;
  cut2.stop;
 })
)
&lt;/pre&gt;
&lt;p&gt;If you want to also sync up a Pbind, you can use BBcut's clock via the playExt method:&lt;/p&gt;
&lt;pre&gt;
Pbind.new(/*  . . . */ ).playExt(clock);
&lt;/pre&gt;
&lt;p&gt;Or, if you want to play an Event, you can use the tempo clock associated with the external clock&lt;/p&gt;
&lt;pre&gt;
Event.new.play(clock.tempoclock);
&lt;/pre&gt;

&lt;h3&gt;Groups and FX&lt;/h3&gt;
&lt;p&gt;If we want to add fx to the chain, and take them back out, we can use a thing called a &lt;b&gt;CutGroup&lt;/b&gt;:&lt;/p&gt;
&lt;pre&gt;
  // make a group with a Buffer
  group = CutGroup(CutBuf3(sf1, 0.4));
  // then send it to get cut up
  cut1 = BBCut2(group, BBCutProc11(8, 4, 2, 2, 0.2)).play(clock);
  // then put some FX in the chain
  group.add(CutMod1.new);
&lt;/pre&gt;
&lt;p&gt;The CutGroup acts like an array, which holds our CutBuf and also the fx.  To get an idea of how this works, try running the following code, adapted from CutGroup's help file:&lt;/p&gt;
&lt;pre&gt;
(
var sf, clock;

clock= ExternalClock(TempoClock(2.5)); 
  
clock.play;  
  
Routine.run({
   
sf= BBCutBuffer("sounds/break",8);

s.sync; //this forces a wait for the Buffer to load

g=CutGroup(CutBuf1(sf));

BBCut2(g, WarpCutProc1.new).play(clock);
});

)

//run these one at a time
g.cutsynths.postln; //default CutMixer was added

g.add(CutComb1.new);

g.cutsynths.postln;

g.add(CutBRF1.new);

g.cutsynths.postln;

g.removeAt(2);  //remove comb

g.cutsynths.postln;
&lt;/pre&gt;
&lt;p&gt;Note that the fx that you add on start with index 2.&lt;/p&gt;
&lt;p&gt;And also notice that you may get some errors in the post window when you remove fx: &lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;FAILURE /n_set Node not found&lt;/span&gt;. These are not usually a problem.&lt;/p&gt;

&lt;h3&gt;Tying it all Together&lt;/h3&gt;
&lt;p&gt;Here's an example using everything covered so far:&lt;/p&gt;
&lt;pre&gt;
(
 var clock, sf1, sf2, cut1, cut2, group;
 
 TempoClock.default.tempo_(180/60);
 clock = ExternalClock(TempoClock.default); 
 clock.play;
 
 sf1= BBCutBuffer("sounds/break",8);
 sf2= BBCutBuffer("sounds/break2",4);

 Routine.run({
  s.sync; // this tells the task to wait

  group = CutGroup(CutBuf3(sf1, 0.2));  // make a group with a Buffer
  cut1 = BBCut2(group, BBCutProc11(8, 4, 2, 2, 0.2)).play(clock);  // then cut it up
  
  5.wait;
  
  cut2 = BBCut2(CutBuf3(sf2, 0.2),
   BBCutProc11(8, 4, 4, 2, 0.2)).play(clock); // start more drums from the other sound file
  
  5.wait;
  
  group.add(CutComb1.new); // put some FX on the drums in cut1
  
  15.wait;
  
  group.removeAt(2); // take the fx back off
  
  1.wait;
  cut2.pause;
  
  4.wait;
  cut1.stop;
 })
)
&lt;/pre&gt;

&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;You must download BBCut2 from a website and install it by moving folders around.&lt;/li&gt;
&lt;li&gt;The main BBCut helpfile is BBCut2Wiki&lt;/li&gt;
&lt;li&gt;BBCut uses it's own clock, called ExternalClock, which relies on TempoClocks. &lt;/li&gt;
&lt;li&gt;You must remember to start the clock&lt;/li&gt;
&lt;li&gt;BBCut uses it's own buffer class called BBCutBuffer. The constructor takes two arguments: a string with the path and filename, and the number of beats in the sound file. If you get the number of beats wrong, your results may sound weird.&lt;/li&gt;
&lt;li&gt;There are several cut procedures, one of which is called BBCutProc11. To use it, (or any other cut procedure in it's place), you use the construction &lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;BBcut2(CutBuf1(sf), BBCutProc11.new).play(clock)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;The cut procedures all have good help files.&lt;/li&gt;
&lt;li&gt;Due to the magic of clocks, you can start two BBCuts going at the same time and if they have the same clock, they will line up.&lt;/li&gt;
&lt;li&gt;It is possible to add FX or remove FX from your chain by using CutGroup. &lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Problems&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Get some of your own drum loops or rhythmic samples and try this out. You can find many loops at &lt;a href="http://www.freesound.org/"&gt;http://www.freesound.org/&lt;/a&gt;.  Also, try some files with sustained tones.&lt;/li&gt;
&lt;li&gt;Experiment with the arguments to BBCutProc11.  Try your files with several different values.&lt;/li&gt;
&lt;li&gt;Try out the different cut procedures. Look at their help files to find their arguments.&lt;/li&gt;
&lt;li&gt;The FX are not as well documented, but they're located in &lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;~/Library/Application\ Support/SuperCollider/Extensions/bbcut2\ classes/cutsynths/fx&lt;/span&gt; .  Try several of them out.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-8989329876647182739?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/8989329876647182739/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=8989329876647182739&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/8989329876647182739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/8989329876647182739'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/10/getting-started-with-bbcut2.html' title='Getting Started with BBCut2'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-5862084119175962484</id><published>2010-10-13T12:47:00.005-04:00</published><updated>2010-10-13T13:54:40.154-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='server'/><category scheme='http://www.blogger.com/atom/ns#' term='Routine'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='timing'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='buffer'/><category scheme='http://www.blogger.com/atom/ns#' term='task'/><category scheme='http://www.blogger.com/atom/ns#' term='sc'/><category scheme='http://www.blogger.com/atom/ns#' term='asynchronous'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>More Buffers</title><content type='html'>&lt;h3&gt;Waiting&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://sc3howto.blogspot.com/2010/10/working-with-buffers.html"&gt;Last time&lt;/a&gt;, we learned that the language does not wait for the server to finish loading buffers before it carries on with the programme, which could lead to a situation where we instruct the server to start playing a buffer that hasn't yet loaded.  This will fail to play correctly.  Fortunately, there are a few ways to make sure this doesn't happen.&lt;/p&gt;
&lt;p&gt;If we use a Task (or a Routine), we can tell it to pause until the server has caught up.&lt;/p&gt;
&lt;pre&gt;
s.boot;
 
(
 var buf;
 
 SynthDef(\playBufMono, {| out = 0, bufnum = 0, rate = 1 |
  var scaledRate, player;
  scaledRate = rate * BufRateScale.kr(bufnum);
  player = PlayBuf.ar(1, bufnum, scaledRate, doneAction:2);
  Out.ar(out, player)
 }).add;

 buf = Buffer.read(s, "sounds/a11wlk01.wav");

 Task.new({
  
  s.sync; // wait for the server
  Synth(\playBufMono, [\out, 0, \bufnum, buf.bufnum, \rate, 1])
  
 }).play
)
&lt;/pre&gt;
&lt;p&gt;The s.sync makes the Task wait for the server to get caught up with the language.  The SynthDef, like the buffer, is also asynchronous, so the sync gives everything a chance to get caught up.&lt;/p&gt;
&lt;p&gt;We can also give the buffer an action.  This is a function that gets evaluated when the buffer has finished loading.  This might be a good idea when we are going to load several buffers, but don't need to use all of them right away.  We could use the action, for example, to set a flag so our programme knows it's ok to start using the buffer:&lt;/p&gt;
&lt;pre&gt;
s.boot;
 
(
 var buf, bufloaded;
 
 SynthDef(\playBuf, {| out = 0, bufnum = 0, rate = 1, 
       dur = 0.2, amp = 0.2, startPos = 0 |
  var scaledRate, player, env;
  
  env = EnvGen.kr(Env.sine(dur, amp), doneAction: 2);
  scaledRate = rate * BufRateScale.kr(bufnum);
  player = PlayBuf.ar(1, bufnum, scaledRate, 
       startPos: startPos, loop:1);
  Out.ar(out, player * env)
 }).add;

 bufloaded = false;
 
 buf = Buffer.read(s, "sounds/a11wlk01.wav", 
  action: { bufloaded = nil});


 Pseq([
  Pbind( // play this Pbind first
   \scale,  Scale.gong,
   \dur,   Pwhite(1, 3, inf) * 0.001,
   \degree,  Prand([0, 2, 4, \rest], inf),
   \amp,  0.2,
   \test,  Pfunc({ bufloaded }) // when this is nil, this Pbind ends
  ),
  Pbind( // next play this one
   \instrument, \playBuf,
   \bufnum,  Pfunc({buf.bufnum}), // use the buffer, now that we know it's ready
   \dur,  Pwhite(0.01, 0.3, 20),
   \startFrame, Pfunc({buf.numFrames.rand}),
   \amp,  1
  )
 ], 1). play

)


&lt;/pre&gt;
&lt;p&gt;Recall that when a Pbind gets a nil, it stops playing and the pattern goes on to the next section, so setting the flag to nil, in this case, advances the piece.  Because the second buffer has not yet loaded when the interpreter first evaluates the second Pbind, buf.numFrames will still be nil. Therefore, we put that into a Pfunc so that it gets evaluated when the Pbind plays, instead of when the interpretter first looks at the code.&lt;/p&gt;
&lt;p&gt;In that example, we don't always start playing back at the start of the Buffer, but instead offset a random number of samples (called "Frames" here).  Coupled with the short duration, this can be an interesting effect.&lt;/p&gt;
&lt;p&gt;When you are writing your own actions, you can also do a more typical true / false flag or do anything else, as it's a function.  For example, it's possible to combine the two approaches:&lt;/p&gt;
&lt;pre&gt;
s.boot;
 
(
 var buf1, syn, pink;
 
 SynthDef(\playBuf1, {| out = 0, bufnum = 0, rate = 1, loop = 1 |
  var scaledRate, player;
  scaledRate = rate * BufRateScale.kr(bufnum);
  player = PlayBuf.ar(1, bufnum, scaledRate, loop: loop,
       doneAction:2);
  Out.ar(out, player)
 }).add;

 SynthDef(\playBufST, {| out = 0, bufnum = 0, rate = 1, loop = 1,
       dur = 1, amp = 0.2 |
  var scaledRate, player, env;
  
  env = EnvGen.kr(Env.sine(dur, amp), doneAction: 2);
  scaledRate = rate * BufRateScale.kr(bufnum);
  player = PlayBuf.ar(2, bufnum, scaledRate, loop:loop);
  Out.ar(out, player * env)
 }).add;

 buf1 = Buffer.read(s, "sounds/a11wlk01.wav");

 Task.new({
  
  s.sync; // wait for buf1
  syn = Synth(\playBuf1, [\out, 0, \bufnum, buf1.bufnum, 
       \rate, 1, \loop, 1]);  // play buf1

  pink =  Buffer.read(s, "sounds/SinedPink.aiff",
   action: {  // run this when pink loads
    syn.set("loop", 0);
    syn = Synth(\playBufST, [\out, 0, \bufnum, pink.bufnum,
        \rate, 1, \loop, 1, \dur, 10]); // play pink
   });
    
  
 }).play
)
&lt;/pre&gt;
&lt;p&gt;In the above example, we first wait for the allwlk01 buffer to load and then start playing it. While it's playing, we tell the SinedPink buffer to load also and give it in action.  When it has loaded, the action will be evaluated.  The action tells the first synth to stop looping and then starts playing a new Synth with the new buffer.&lt;/p&gt;
&lt;p&gt;If we wanted to, we could use the action to set a flag or do any number of other things.&lt;/p&gt;
&lt;h3&gt;Recording&lt;/h3&gt;
&lt;p&gt;We don't need to just play Buffers, we can also record to them.  Let's start by allocating a new Buffer:&lt;/p&gt;
&lt;pre&gt;
b = Buffer.alloc(s, s.sampleRate * 3, 1)
&lt;/pre&gt;
&lt;p&gt;The first argument is the server. The second is the number of frames.  I've allocated a 3 second long Buffer.  The third argument is the number of channels.&lt;/p&gt;
&lt;p&gt;Now, let's make a synth to record into it:&lt;/p&gt;
&lt;pre&gt;
 SynthDef(\recBuf, {| in = 1, bufnum, loop = 1|
 
  var input;
  input = AudioIn.ar(in);
  RecordBuf.ar(input, bufnum, recLevel: 0.7, preLevel: 0.4, loop:loop, doneAction: 2);
 }).add;
&lt;/pre&gt;
&lt;p&gt;AudioIn.ar reads from our microphone or line in.  Channels start at 1, for this UGen.&lt;/p&gt;
&lt;p&gt;RecordBuf takes an input array, a bufnum and several other arguments.  In this example, we're scaling the input by 0.7 and keeping previous data in the buffer, scaled by 0.4. We'll keep looping until instructed to stop.&lt;/p&gt;
&lt;p&gt;We can mix this with a stuttering playback from earlier:&lt;/p&gt;
&lt;pre&gt;
s.boot;
 
(
 var buf, syn, pb;
 
 SynthDef(\playBuf2, {| out = 0, bufnum = 0, rate = 1, 
       dur = 5, amp = 1, startPos = 0 |
  var scaledRate, player, env;
  
  env = EnvGen.kr(Env.sine(dur, amp), doneAction: 2);
  scaledRate = rate * BufRateScale.kr(bufnum);
  player = PlayBuf.ar(1, bufnum, scaledRate, 
       startPos: startPos, loop:1);
  Out.ar(out, player * env)
 }).add;
 
 SynthDef(\recBuf, {| in = 1, bufnum, loop = 1|
 
  var input;
  input = AudioIn.ar(in);
  RecordBuf.ar(input, bufnum, recLevel: 0.7, preLevel: 0.4, loop:loop, doneAction: 2);
 }).add;
 
 buf = Buffer.alloc(s, s.sampleRate * 3, 1);
 
 Task({
  
  s.sync; // wait for the buffer
  
  syn = Synth(\recBuf, [\in, 1, \bufnum, buf.bufnum, \loop, 1]); // start recording
  
  2.wait; // let some stuff get recorded;
  
  
  pb = Pbind( // play from the same buffer
   \instrument, \playBuf2,
   \bufnum,  buf.bufnum,
   \dur,  Pwhite(0.01, 0.5, 2000),
   \startFrame, Pwhite(0, buf.numFrames.rand, inf),
   \amp,  1
  ).play;
  
  5.wait;
  
  syn.set("loop", 0);  // stop looping the recorder
  
  3.wait;
  pb.stop; // stop playing back
 }).play
)
&lt;/pre&gt;
&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Buffers load asynchronously and we can't count on them to be ready unless we wait for them.&lt;/li&gt;
&lt;li&gt;One way to wait is to call s.ync inside a Task or a Routine.&lt;/li&gt;
&lt;li&gt;We can start playing back a Buffer from any sample with the startFrame argument.&lt;/li&gt;
&lt;li&gt;Buffer.read has an action argument, to which we can pass a function that will be evaluated after the Buffer has been read on the server.&lt;/li&gt;
&lt;li&gt;We can allocate empty Buffers on the server with Buffer.alloc.&lt;/li&gt;
&lt;li&gt;AudioIn.ar starts with channel 1, even though most other input busses start at 0.&lt;/li&gt;
&lt;li&gt;RecordBuf.ar records to a Buffer.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Problems&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Write a programme that opens and plays several Buffers. Make sure that every Buffer is ready before you play it.  Spend the least possible amount of time waiting.&lt;/li&gt;
&lt;li&gt;Write a programme that reads a Buffer, starts playing it back in some way and the starts recording to the same Buffer.  You can use AudioIn.ar or  check out InFeedback.ar.  Note that, as the name implies, you may get feedback, especially if you are playing back in a linear manner at a rate of 1. Try other rates or ways of playing back to avoid this.&lt;/li&gt;
&lt;li&gt;Find a short audio file that contains some beat-driven audio.  If you know the number of beats in the file, could you make an array of startFrames?  Write a Pbind that does something interesting with your file and your array.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-5862084119175962484?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/5862084119175962484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=5862084119175962484&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/5862084119175962484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/5862084119175962484'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/10/more-buffers.html' title='More Buffers'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-6216356425790647882</id><published>2010-10-03T11:58:00.005-04:00</published><updated>2010-10-13T10:57:14.865-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='synthdef'/><category scheme='http://www.blogger.com/atom/ns#' term='buffer'/><category scheme='http://www.blogger.com/atom/ns#' term='playbuf'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Working with Buffers</title><content type='html'>&lt;p&gt;Let's say you want to open a short audio file and play it back.  You can do this with a &lt;b&gt;Buffer&lt;/b&gt;.&lt;/p&gt;

&lt;pre&gt;
 s.boot;
 b = Buffer.read(s, "sounds/a11wlk01.wav");
&lt;/pre&gt;
&lt;p&gt;Don't run both of those lines at once. Wait for the server to finish booting before reading the Buffer.  The reason you need to wit is because the Buffer actually lives with the server.  The server plays the audio, so the server needs to have the audio in it's memory.&lt;/p&gt;
&lt;p&gt;The first argument, is therefore the server that will hold the buffer.  The second is the path to the buffer on your computer.&lt;/p&gt;
&lt;p&gt;Because the Buffer lives with the server, the command to read it is &lt;b&gt;asynchronous&lt;/b&gt;. We tell the server to load the Buffer and then carry on, without waiting to hear back if it's been loaded or not.  For large files, it may take a few moments for it to fully load.  One way to deal with tis is to load buffers into global variables (like b, above) and then manually wait to evaluate the next section.&lt;/p&gt;
&lt;h3&gt;PlayBuf&lt;/h3&gt;
&lt;p&gt;To play the Buffer, you can use the UGen PlayBuf:&lt;/p&gt;
&lt;pre&gt;
(
 SynthDef(\playBuf, {| out = 0, bufnum = 0 |
  var scaledRate, player;
  scaledRate = BufRateScale.kr(bufnum);
  player = PlayBuf.ar(1, bufnum, scaledRate, doneAction:2);
  Out.ar(out, player)
 }).play(s, [\out, 0, \bufnum, b.bufnum]);
)
&lt;/pre&gt;
&lt;p&gt;When Buffers are allocated on the server, they're given a unique ID number, so we can reference them later. This number is called the bufnum.  It's the second argument to the SynthDef.  This way, we know which buffer we're supposed to play.&lt;/p&gt;
&lt;p&gt;Some Buffers may have unusual sample rates or otherwise be unusual. To make sure that they play at the speed we expect, we use a UGen to scale the rate.  If we wanted to play at half speed, we could change the SynthDef:&lt;/p&gt;
&lt;pre&gt;
(
 SynthDef(\playBuf, {| out = 0, bufnum = 0, rate = 1 |
  var scaledRate, player;
  scaledRate = rate * BufRateScale.kr(bufnum);
  player = PlayBuf.ar(1, bufnum, scaledRate, doneAction:2);
  Out.ar(out, player)
 }).play(s, [\out, 0, \bufnum, b.bufnum, \rate, 0.5]);
)
&lt;/pre&gt;
&lt;p&gt;Note that when we play at half speed, it takes twice as long to play the sample and pitches are all an octave lower. This is just like working with magnetic tape.  If we change the rate to 2, it will play back at half the speed of the original and be an octave higher.  If you try a rate of -1, it will play backwards at the normal rate.&lt;/p&gt;
&lt;p&gt;The PlayBuf UGen is the one that actually plays the buffer.  The first argument is the number of channels.  Our buffer is mono, so that number is 1.  If it were stereo, we would change it to 2.  You cannot pass in this number as an argument or change it while the Synth is running.  The SynthDef must be defined with the right number of channels.  If you give a stereo buffer to a mono PlayBuf, or vice versa, it will not play.  If you have both mono and stereo buffers in one piece, you will need to have two SynthDefs:&lt;/p&gt;
&lt;pre&gt;
(
 SynthDef(\playBufMono, {| out = 0, bufnum = 0, rate = 1 |
  var scaledRate, player;
  scaledRate = rate * BufRateScale.kr(bufnum);
  player = PlayBuf.ar(1, bufnum, scaledRate, doneAction:2);
  Out.ar(out, player)
 }).add;

 SynthDef(\playBufStereo, {| out = 0, bufnum = 0, rate = 1 |
  var scaledRate, player;
  scaledRate = rate * BufRateScale.kr(bufnum);
  player = PlayBuf.ar(1, bufnum, scaledRate, doneAction:2);
  Out.ar(out, player)
 }).add;
)
&lt;/pre&gt;
&lt;p&gt;PlayBuf can handle N-channel files, so if you have some three channel or 8 channel files, you can also play those if you define synthdefs with the right number of channels.&lt;/p&gt;
&lt;p&gt;To figure out which SynthDef to use, you can send the message numChannels to a buffer object:&lt;/p&gt;
&lt;pre&gt;
(
 if((b.numChannels == 1), {
  Synth(\playBufMono, [\out, 0, \bufnum, b.bufnum, \rate, 1])
 }, {
  if((b.numChannels == 2), {
   Synth(\playBufStereo, [\out, 0, \bufnum, b.bufnum, \rate, 1])
  })
 });
)
&lt;/pre&gt;
&lt;p&gt;The second argument to PlayBuf is the bufnum. This tells it which Buffer to play.&lt;/p&gt;
&lt;p&gt;The third argument is the rate.  As mentioned above, it's a good idea to scale this rate with BufRateScale.kr&lt;/p&gt;
&lt;p&gt;Buffers, like envelopes, can have a doneAction. 2 means to deallocate the synth from the server when the Buffer stops playing.&lt;/p&gt;
&lt;p&gt;If you want to loop your buffer, that's also a possible argument:&lt;/p&gt;
&lt;pre&gt;
(
 SynthDef(\playBufMonoLoop, {| out = 0, bufnum = 0, rate = 1 |
  var scaledRate, player;
  scaledRate = rate * BufRateScale.kr(bufnum);
  player = PlayBuf.ar(1, bufnum, scaledRate, loop: 1, doneAction:2);
  Out.ar(out, player)
 }).play(s, [\out, 0, \bufnum, b.bufnum, \rate, 1]);
)
&lt;/pre&gt;
&lt;p&gt;1 means do loop and 0 means don't loop. the default is 0. You can change the loop value while the Synth is running, so it's a good idea to still have a doneAction.&lt;/p&gt;
&lt;p&gt;You can trigger a PlayBuf to jump back to the start:&lt;/p&gt;
&lt;pre&gt;
(
 SynthDef(\playBufMonoStutter, {| out = 0, bufnum = 0, rate = 1 |
  var trigs, scaledRate, player;
  trigs = Dust.ar(2);
  scaledRate = rate * BufRateScale.kr(bufnum);
  player = PlayBuf.ar(1, bufnum, scaledRate, trigs, loop: 1, doneAction:2);
  Out.ar(out, player)
 }).play(s, [\out, 0, \bufnum, b.bufnum, \rate, 1]);
)
&lt;/pre&gt;
&lt;p&gt;Dust.ar returns impulses at random intervals. It's argument is the average number of impulses per second.&lt;/p&gt;
&lt;p&gt;You can also tell the PlayBuf to start someplace else than the first sample:&lt;/p&gt;
&lt;pre&gt;
(
 SynthDef(\playBufMonoLoopStart, {| out = 0, bufnum = 0, rate = 1, startPos |
  var scaledRate, player;
  scaledRate = rate * BufRateScale.kr(bufnum);
  player = PlayBuf.ar(1, bufnum, scaledRate, startPos: startPos, loop: 1, doneAction:2);
  Out.ar(out, player)
 }).play(s, [\out, 0, \bufnum, b.bufnum, \rate, 1, \startPos, b.numFrames.rand]);
)
&lt;/pre&gt;
&lt;p&gt;startPos is the number of the sample to start from.  If you have a one second long buffer with 44100 samples in it, and you want to start in the middle, you would set use 22050 for the startPos.&lt;/p&gt;
&lt;h3&gt;Dialogs&lt;/h3&gt;
&lt;p&gt;If you don't want to have to pick an audio file ahead of time, you can use Buffer.loadDialog:&lt;/p&gt;
&lt;pre&gt;

s.boot;
 
(
 SynthDef(\playBufMono, {| out = 0, bufnum = 0, rate = 1 |
  var scaledRate, player;
  scaledRate = rate * BufRateScale.kr(bufnum);
  player = PlayBuf.ar(1, bufnum, scaledRate, doneAction:2);
  Out.ar(out, player)
 }).add;

 SynthDef(\playBufStereo, {| out = 0, bufnum = 0, rate = 1 |
  var scaledRate, player;
  scaledRate = rate * BufRateScale.kr(bufnum);
  player = PlayBuf.ar(1, bufnum, scaledRate, doneAction:2);
  Out.ar(out, player)
 }).add;

 b = Buffer.loadDialog(s);
)

(
 if((b.numChannels == 1), {
  Synth(\playBufMono, [\out, 0, \bufnum, b.bufnum, \rate, 1])
 }, {
  if((b.numChannels == 2), {
   Synth(\playBufStereo, [\out, 0, \bufnum, b.bufnum, \rate, 1])
  })
 });
)
&lt;/pre&gt;

&lt;p&gt;Note that you cannot load a compressed audio format like mp3 or ogg directly into a Buffer.&lt;/p&gt;

&lt;p&gt;More on Buffers to come! &lt;/p&gt;
&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Buffers live on the server&lt;/li&gt;
&lt;li&gt;Every Buffer has a unique bufnum&lt;/li&gt;
&lt;li&gt;You can change the playback rate of a Buffer. This should be scaled with BufRateScale&lt;/li&gt;
&lt;li&gt;SynthDefs must be sent to the server already knowing how many channels PlayBuf.ar will play.&lt;/li&gt;
&lt;li&gt;PlayBuf.ar will optionally take a doneAction&lt;/li&gt;
&lt;li&gt;You can loop a Buffer, stuter it and tell it where to start&lt;/li&gt;
&lt;li&gt;You can open a Buffer with a Dialog box&lt;/li&gt;
&lt;li&gt;You cannot read an mp3 or ogg directly into a Buffer&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-6216356425790647882?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/6216356425790647882/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=6216356425790647882&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/6216356425790647882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/6216356425790647882'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/10/working-with-buffers.html' title='Working with Buffers'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-2921620780566497174</id><published>2010-08-03T13:13:00.008-04:00</published><updated>2010-10-23T14:32:20.305-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Event'/><category scheme='http://www.blogger.com/atom/ns#' term='data structures'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='IdentityDictionary'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='pbind'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Event</title><content type='html'>&lt;p&gt;The most important subclass of Dictionary is &lt;b&gt;Event&lt;/b&gt;:&lt;/p&gt;
&lt;pre&gt;
(
 var evt;
 evt = Event.new;
 evt.play;
)
&lt;/pre&gt;
&lt;p&gt;Much like Arrays can be declared just by square brackets, Events can be declared just with parenthesees:&lt;/p&gt;
&lt;pre&gt;
( ).play;
&lt;/pre&gt;
&lt;p&gt;The sonic results of that line of code might sound familiar to you:&lt;/p&gt;
&lt;pre&gt;
Pbind.new.play
&lt;/pre&gt;
&lt;p&gt;This is not a coincidence! Patterns create Events and play them sequentially. Compare:&lt;/p&gt;
&lt;pre&gt;
Pbind(\freq, 660, \pan, -1).play
&lt;/pre&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;pre&gt;
(freq: 660, pan: -1).play
&lt;/pre&gt;
&lt;p&gt;Note that the syntax for the Event is  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;(key: value, key2: value2)&lt;/span&gt; . You can have as many &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;key: value&lt;/span&gt; pairs as you want.  In the example above, &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;freq&lt;/span&gt; and &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;pan&lt;/span&gt; are both symbols, both in the Pbind and the event.&lt;/p&gt;
&lt;p&gt;Events are Dictionaries and they are created with a bunch of default keys and values.  Although, you can use any sort of object as the key for a Dictionary, you should only use symbols as keys for an Event.&lt;/p&gt;
&lt;p&gt;The Pbind modifies elements of a default Event and then plays the results of that.  To find out what interesting thigns can be changed in an Event, (and therefore also in a Pbind), check out it's helpfile, specifically the section called "Useful keys for notes."&lt;/p&gt;
&lt;p&gt;In your Pbind, you can get access to the current event:&lt;/p&gt;
&lt;pre&gt;
(
 Pbind(
  \freq, Pseq([550], 1),
  \event, Pfunc({ |evt|
     evt[\freq].postln;
    })
 ).play
)
&lt;/pre&gt;
&lt;p&gt;The current event is passed as an argument to the function in Pfunc and also the one in Prout.  Here, we have created a key, &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;\event&lt;/span&gt;, that doesn't have meaning to the Synth, nor to the Event.  This is allowed. For example:&lt;/p&gt;
&lt;pre&gt;
(
 Pbind(
  \freq, Pseq([550], 1),
  \foo, \bar
 ).play
)
&lt;/pre&gt;
&lt;p&gt;Every time the Pbind makes an event, it goes through the list of keys and values in the order that it recieves them.  For example:&lt;/p&gt;
&lt;pre&gt;
(
 Pbind(
  \event, Pfunc({ |evt|
     "Pan before: %".format(evt[\pan]).postln;
    }),
    
  \pan, Pseq([-1], 1),
  
  \event2, Pfunc({ |evt|
     "Pan after: %".format(evt[\pan]).postln;
    })
 ).play
)&lt;/pre&gt;
&lt;p&gt;The first postln prints out 0, because that's the default value for \pan.  The second postln prints out -1. Then it goes back to the first one because the Pbind does not run out the Pseq returns a nil.&lt;/p&gt;
&lt;p&gt;Let's make the duration depend on the frequency:&lt;/p&gt;
&lt;pre&gt;
(
 Pbind(
  \freq, Prand([440, 550, 660, 770], 10),
  \dur, Pfunc({ |evt|
   
     var dur;
     
     dur = evt[\freq] / 1000
    })
 ).play
)
&lt;/pre&gt;
&lt;p&gt;Events are one way you can tie together two keys in an event.  You can also do this with arrays:&lt;/p&gt;
&lt;pre&gt;
(
 Pbind(
 
  [\freq, \dur],
   Prout({
    var arr, freq, dur;
    
    arr = [440, 550, 660, 770];
    
    10.do({
     
     freq = arr.choose;
     dur = freq / 1000;
     
     [freq, dur].yield;
    })
   })
 ).play
)
&lt;/pre&gt;
&lt;p&gt;Two or more keys can be grouped together in an array.  Then, the stream, which can be a Prout, a Pfunc or any other P-thing, must return an array which is the same length as the key array.  The first item in the returned array gets paired with the first item in the key array, the second item goes with the second key and so forth.&lt;/p&gt;
&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Event is a subclass of Dictionary.
&lt;li&gt;You can declare an event by just using parenthesis.
&lt;li&gt;You should only use Symbols as keys for Events.
&lt;li&gt;Patterns work by creating events over and over again.
&lt;li&gt;You can access events in Pfunc. It's passed to the function as an argument.
&lt;li&gt;You can use keys in your Event or Pbind that are not meaningful to the Pbind, the Even or the Synth.
&lt;li&gt;Events can be used to tie together two different elements in a Pbind.
&lt;li&gt;Arrays can also be used to tie together two different elements in a Pbind.
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-2921620780566497174?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/2921620780566497174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=2921620780566497174&amp;isPopup=true' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/2921620780566497174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/2921620780566497174'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/08/event.html' title='Event'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-9025451867345004639</id><published>2010-06-25T10:44:00.008-04:00</published><updated>2011-08-28T14:37:14.653-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='array'/><category scheme='http://www.blogger.com/atom/ns#' term='data structures'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='IdentityDictionary'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Dictionary</title><content type='html'>&lt;p&gt;Let's take a break from Pbinds and their ilk to talk about a data type.  A &lt;b&gt;Dictionary&lt;/b&gt; is a data type like an array, except that instead of using integers for indexes, you can use anything that you want.&lt;/p&gt;
&lt;pre&gt;
(
 var id;
 
 id = Dictionary.new;
 id.put(\foo, "bar");
 
 id[\foo].postln;
)
&lt;/pre&gt;
&lt;p&gt;The indexes are called &lt;b&gt;keys&lt;/b&gt; and the items associated with them are called &lt;b&gt;values&lt;/b&gt;.  In the above example, &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;\foo&lt;/span&gt; is the key and &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;"bar"&lt;/span&gt; is the value.  As mentioned above, you can use any kind of object for keys. And, like arrays, any kind of object can be the value.&lt;/p&gt;
&lt;pre&gt;
(
 var id;
 
 id = Dictionary.new;
 id.put(\foo, "bar");
 id.put(15, true);
 id.put("baz", 12.5);
 
 id[15].postln;
)
&lt;/pre&gt;
&lt;p&gt;You can get a list of the keys with the message &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;keys&lt;/span&gt;, and then use that to step through a do loop:&lt;/p&gt;
&lt;pre&gt;
(
 var id, keys;
 
 id = Dictionary[
  \foo -&amp;gt; "bar",
  15 -&amp;gt; true,
  "baz" -&amp;gt; 12.5
 ];

 keys = id.keys;
 keys.postln;

 keys.do({|key|
  
  "key is %, value is %".format(key, id.at(key)).postln;
 });
)
&lt;/pre&gt;
&lt;p&gt;In that example, we see another way of declaring a Dictionary, with square brackets and key, value pairs in the format &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;key -&amp;gt; value&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We also see a new way of formatting strings.  If you want to print a string with some variables in it, you can use % to signify where the variable should go and then pass the variables as arguments to format. You can use as many variables as you would like: &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;"string %, % and %".format(var1, var2, var3)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Notice that the keys are in a random order.  If you want them in a particular order, you will have to sort them.&lt;/p&gt;
&lt;p&gt;Here's another example:
&lt;pre&gt;
(
 var triangle_spectrum, freqs;
 
 triangle_spectrum = Dictionary[
  1-&amp;gt;1, 
  3-&amp;gt;(1/9), 
  5-&amp;gt;(1/25), 
  7-&amp;gt;(1/49), 
  9-&amp;gt;(1/81)
 ];
 
 freqs = triangle_spectrum.keys;
 freqs = freqs.asArray;
 freqs = freqs.sort;
 
 freqs.do({|freq|
 
  "freq %\t amplitude %\n".postf(freq * 440, triangle_spectrum[freq]);
 })
)
&lt;/pre&gt;
&lt;p&gt;This stores the (non-normalised) spectrum of a triangle wave.  Note that when we declare the Dictionary, we need to put mathematical expressions inside parentheses.&lt;/p&gt;
&lt;p&gt;Then, we get the keys from the dictionary. Then we need to convert that Set to an Array.  We can then tell the Array to sort itself.&lt;/p&gt;
&lt;p&gt;&lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;\t&lt;/span&gt; means tab and &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;\n&lt;/span&gt; means newline.  We use these for formatting, to make our output look nice.  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;postf&lt;/span&gt; formats a string and then posts it.  It does not include a newline, so we do it ourselves with a &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;\n&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;Array.sort&lt;/span&gt; takes an optional argument, which is a sort function.  Here's an example to do a reverse sort:&lt;/p&gt;
&lt;pre&gt;
(
 var triangle_spectrum, freqs;
 
 triangle_spectrum = Dictionary[
  1-&amp;gt;1, 
  3-&amp;gt;(1/9), 
  5-&amp;gt;(1/25), 
  7-&amp;gt;(1/49), 
  9-&amp;gt;(1/81)
 ];
 
 freqs = triangle_spectrum.keys;
 freqs = freqs.asArray;
 freqs = freqs.sort({|a, b| a &gt; b});
 
 freqs.do({|freq|
 
  "freq %\t amplitude %\n".postf(freq * 440, triangle_spectrum[freq]);
 })
)
&lt;/pre&gt;
&lt;p&gt;The sort function takes two agruments and returns a boolean.  In the above example, it compares two items and if the first one is bigger, it returns true.  This will order the array so that larger items come first.&lt;/p&gt;
&lt;p&gt;We can check to see if a Dictionary includes a particular key:&lt;/p&gt;
&lt;pre&gt;
(
 var triangle_spectrum;
 
 triangle_spectrum = Dictionary[
  1-&amp;gt;1, 
  3-&amp;gt;(1/9), 
  5-&amp;gt;(1/25), 
  7-&amp;gt;(1/49), 
  9-&amp;gt;(1/81)
 ];
 
 triangle_spectrum.includesKey(4).postln;
)
&lt;/pre&gt;
&lt;p&gt;We can also look for the key of a particular item:&lt;/p&gt;
&lt;pre&gt;
(
 var id;
 
 id = Dictionary[
  \foo -&amp;gt; "bar",
  15 -&amp;gt; true,
  "baz" -&amp;gt; 12.5
 ];

 id.findKeyForValue(12.5).postln;
)
&lt;/pre&gt;
&lt;!--
&lt;p&gt;We can tell IdentityDictionaries to respond to unknown messages as keys:&lt;/p&gt;
&lt;pre&gt;
(
 var id;
 
 id = IdentityDictionary[
  \foo -&amp;gt; 17, 
  \bar -&amp;gt; pi,
  \baz -&amp;gt; 13.5
  
 ].know_(true);

 id.bar.postln;
)
&lt;/pre&gt;
&lt;p&gt;The &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;know_(true)&lt;/span&gt; is what makes this so.  Note that if we have a key called &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;\at&lt;/span&gt;, we cannot use it in this way, because at is a known message to IdentityDictionary.&lt;/p&gt;
--&gt;
&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;A Dictionary is made up of key, value pairs.&lt;/li&gt;
&lt;li&gt;You can add items to a Dictionary with a message &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;put(key, value)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Dictionaries can be declared with &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;key -&amp;gt; value&lt;/span&gt; pairs in square brackets.&lt;/li&gt;
&lt;li&gt;&lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;Dictionary.keys&lt;/span&gt; exports a set of the keys, in random order.&lt;/li&gt;
&lt;li&gt;If you want to sort the keys, you must pass them the message &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;.asArray&lt;/span&gt; and then pass the message sort to the result of that.&lt;/li&gt;
&lt;li&gt;If you want to sort anyhting besides numbers from small ot large you have to write a sort function&lt;/li&gt;
&lt;li&gt;A sort function takes two arguments and returns a boolean based on a comparison between them.&lt;/li&gt;
&lt;li&gt;You can test is an Dictionary contains a particular key with &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;includesKey&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;You can look up the key for a value with &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;findKeyForValue&lt;/span&gt;&lt;/li&gt;
&lt;!--&lt;li&gt;If you set &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;know&lt;/span&gt; to true, you can use keys as messages&lt;/li&gt;--&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-9025451867345004639?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/9025451867345004639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/9025451867345004639'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/06/identitydictionary.html' title='Dictionary'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-4619869905433238594</id><published>2010-06-24T19:35:00.002-04:00</published><updated>2010-06-24T19:40:33.411-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='stream'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Streams</title><content type='html'>&lt;p&gt;There's a very useful helpfile set for Streams Patterns and Events, which is available by looking for the helpfile for &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;Streams&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;We know what a pattern is, after looking at Pseq and he other Pthings.  But what is a stream? "A stream represents a lazy sequence of values," says the helpfile "Understanding Streams, Patterns and Events - Part 1," which you should go read.  Streams respond to the message &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;next&lt;/span&gt;.  Here's an example:&lt;/p&gt;
&lt;pre&gt;
(
 var stream;
 
 stream = Pseq([1, 2, 3], 1).asStream;
 
 3.do({
  stream.next.postln;
 })
)
&lt;/pre&gt;
&lt;p&gt;Any kind of pattern can be converted to a stream by sending it the message &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;asStream&lt;/span&gt;.  This can be more useful than you might think.  For example, if you have two &lt;b&gt;threads&lt;/b&gt; stepping through the same data:&lt;/p&gt;
&lt;pre&gt;
(

 var stream, task1, task2;
 
 stream = Pseq(["Mary", "had", "a", "little", "lamb", "whose", "fleece"], 1).asStream;
 
 task1 = Task({
 
  inf.do({
  
   "task1: ".post;
   stream.next.postln;
   1.wait;
  });
 });
 
 task2 = Task({
 
  inf.do({
  
   "task2: ".post;
   stream.next.postln;
   1.51.wait;
  });
 });
 
 task1.play;
 task2.play
)
&lt;/pre&gt;
&lt;p&gt;The two tasks can strep through a shared list.  However, note that the stream starts returning nil when it runs out of other data to return.  You have to test for that:&lt;/p&gt;
&lt;pre&gt;
(

 var stream, task;
 
 stream = Pseq(["Mary", "had", "a", "little", "lamb", "whose", "fleece"], 1).asStream;
 
 task = { |id, wait|
  var next;
  Task({
 
   next = stream.next;
   
   {next.notNil}.while({
  
    ("task" ++ id ++ ": " ++ next). postln;
    wait.wait;
    next = stream.next;
   });
  });
 };
 
 task.value(1, 1).play;
 task.value(2, 1.51).play
)
&lt;/pre&gt;
&lt;p&gt;You can also do math on streams:&lt;/p&gt;
&lt;pre&gt;
(
 var stream, squared;
 
 stream = Pseq([1, 2, 3], 1).asStream;
 squared = stream.squared;
 3.do({
  squared.next.postln;
 })
)
&lt;/pre&gt;
&lt;p&gt;And you can do binary math operations on two streams:
&lt;pre&gt;
(
 var stream1, stream2, sum;

 stream1 = Pseq([1, 2, 3], 1).asStream;
 stream2 = Pseq([4, 5, 6], 1).asStream;
 sum = stream1 + stream2;

 3.do({
  sum.next.postln;
 })
)
&lt;/pre&gt;
&lt;p&gt;You can use streams with Pbinds, but you have to wrap them in Prout or Pfunc:&lt;/p&gt;
&lt;pre&gt;
(
 var notes, pbind;
 
 notes = Pseq([ 1/1, 3/2, 4/3, 9/8, 16/9, 5/4, 8/5 ].pyramid(1), 2).asStream;
 notes = notes * 440;
 
 pbind = { |dur = 0.5|
 
  Pbind(
   \dur, dur,
   \freq, Pfunc({notes.next})
  )
 };
 
 Ppar([pbind.value(0.5), pbind.value(0.751)]).play;
)
&lt;/pre&gt;
&lt;p&gt;Note that when notes.next returns nil, the Pbind quits playing.&lt;/p&gt;
&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Streams can be create from patterns.  The respond to the message next.&lt;/li&gt;
&lt;li&gt;When streams run out of values, they start to return nil.&lt;/li&gt;
&lt;li&gt;Multiple tasks can access the same stream.&lt;/li&gt;
&lt;li&gt;You can do math on streams.&lt;/li&gt;
&lt;li&gt;Streams can be used in Pbinds, provided a function or a routine calls next&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-4619869905433238594?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/4619869905433238594/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=4619869905433238594&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/4619869905433238594'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/4619869905433238594'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/06/streams.html' title='Streams'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-3981483309629928644</id><published>2010-06-08T17:46:00.003-04:00</published><updated>2010-06-08T17:50:44.701-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Prout'/><category scheme='http://www.blogger.com/atom/ns#' term='Routine'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='pattern'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Math with Patterns &amp; Prout</title><content type='html'>&lt;p&gt;Let's say that you want to pick random numbers?  You could use Pwhite.  But what if you wanted random multiples of 2?  You would still use Pwhite:&lt;/p&gt;

&lt;pre&gt;
(
 Pbind(
  \dur,  0.2,
  \note,  Pwhite(0, 6) * 2
 ).play
)
&lt;/pre&gt;

&lt;p&gt;What if you want to square your random numbers?&lt;/p&gt;
&lt;pre&gt;
(
 Pbind(
  \dur,  0.2,
  \note,  Pwhite(0, 5).squared
 ).play
)
&lt;/pre&gt;

&lt;p&gt;You can do any math operation with a pattern as if it was a number.&lt;/p&gt;

&lt;pre&gt;
(
 Pbind(
  \dur,  0.2, 
  \note,  Pseq([1, 2, 3], 15) * Pseq([1, 2, 3, 5, 4], inf)
 ).play
)
&lt;/pre&gt;

&lt;p&gt;If you want to do math with a pattern and a variable that might change over time, you still need to use a Pfunc:&lt;/p&gt;
&lt;pre&gt;
(
 var num;
 num = 5;
 
 Pbind(
  \dur,  0.2,
  \note, Pwhite(0, 5) * Pfunc({num})
 ).play;
 
 Task({
  5.wait;
  num = 2;
 }).play;
)
&lt;/pre&gt;

&lt;p&gt;Let's say you want step through every item in a shuffled array.  You could use Pseq:&lt;/p&gt;

&lt;pre&gt;Pseq([1, 3, 5, 7].scramble, 4)&lt;/pre&gt;
&lt;p&gt;Or Pshuf does the same thing:&lt;/p&gt;
&lt;pre&gt;Pshuf([1, 3, 5, 7], 4)&lt;/pre&gt;

&lt;p&gt;But what if you want the array to reshuffle after every tme through the loop?  (As far as I know) there's not a pre-existing pattern for that.  But you can write one with Prout.&lt;/p&gt;

&lt;pre&gt;
(
 var arr, rout;
 
 arr = [1, 3, 5, 7];
 
 rout = Prout({ 
  5.do({
   arr.scramble.do({|item|
    item.yield;
  })})
 });

 
 Pbind(
  \dur, 0.2,
  \note, rout
 ).play
)
&lt;/pre&gt;

&lt;p&gt;A Routine is a function that can pause while it's running.  It can also return values more than once.  Prout is a wrapper for a Routine.  Everytime it gets to item.yield, it returns the item and then waits to be asked for it's next return value.  Then it starts running again until it finds another yield or runs out of things to run.&lt;/p&gt;
&lt;p&gt;Like Pfunc, Prout evaluates variables as it runs.  In the above example, if arr had changed, the Prout would have used the new arr:&lt;/p&gt;

&lt;pre&gt;
(
 var arr, rout;
 
 arr = [1, 3, 5, 7];
 
 rout = Prout({ 
  10.do({
   arr.scramble.do({|item|
    item.yield;
  })})
 });

 
 Pbind(
  \dur, 0.2,
  \note, rout
 ).play;
 
 Task({
  2.wait;
  arr = [12, 15, 19, 21];
  2.wait;
  arr = [-12, -13, -11];
 }).play
)
&lt;/pre&gt;

&lt;p&gt;You could do something similar also, this way:&lt;/p&gt;
&lt;pre&gt;
(
 var arr1, arr2, arr3, rout;
 
 arr1 = [1, 3, 5, 7];
 arr2 = [12, 15, 19, 21];
 arr3 = [-12, -13, -11];
 
 rout = Prout({ 
  3.do({
   arr1.scramble.do({|item|
    item.yield;
  })});
  3.do({
   arr2.scramble.do({|item|
    item.yield;
  })});
  3.do({
   arr3.scramble.do({|item|
    item.yield;
  })})
 });

 
 Pbind(
  \dur, 0.2,
  \note, rout
 ).play;
 
)
&lt;/pre&gt;

&lt;p&gt;You can have as many yields as you want in a Routine - or a Prout.&lt;/p&gt;

&lt;p&gt;If you want to pass in arguments, you can use a wrapper function:&lt;/p&gt;
&lt;pre&gt;
(
 var rout;
 
 rout = {|arr, repeats = 5|
  Prout({ 
   repeats.do({
    arr.scramble.do({|item|
     item.yield;
   })})
  });
 };

 
 Pbind(
  \dur, 0.2,
  \note, rout.value([0, 2, 4, 6], 6)
 ).play
)
&lt;/pre&gt;
&lt;p&gt;And, as with Pfunc, you can do math:&lt;/p&gt;
&lt;pre&gt;
(
 var rout; 
 
 rout = {|arr, repeats = 5|
  Prout({ 
   repeats.do({
    arr.scramble.do({|item|
     item.yield;
   })})
  });
 };

 
 Pbind(
  \dur, 0.2,
  \note, rout.value([0, 2, 4, 5], 6) * Pseq([1, 2, 3], inf)
 ).play
)
&lt;/pre&gt;
&lt;p&gt;Yielding only works inside Routines.  If you try this in a Pfunc, it does not work:&lt;/p&gt;
&lt;pre&gt;
(
 var func; 
 
 func = Pfunc({ 
  5.do({
   [1, 2, 5].scramble.do({|item|
    item.yield; // you can't do this in a Pfunc!!
  })})
 });
 

 
 Pbind(
  \dur, 0.2,
  \note, func
 ).play
)
&lt;/pre&gt;
&lt;p&gt;Note that it does not create an error message, it just behaves in a bizarre way.  Silent errors are the hardest to track down, so beware.&lt;/p&gt;
&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Patterns can behave like numbers for math operations.&lt;/li&gt;
&lt;li&gt;A Routine is a function that can pause&lt;/li&gt;
&lt;li&gt;A Prout is like a Pfunc, except that it can stop in the midst of things and resume.&lt;/li&gt;
&lt;li&gt;Routines can return more than one item, at any point in their execution, whenever you yield a value.&lt;/li&gt;
&lt;li&gt;You can only yield in a Routine or a Prout&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-3981483309629928644?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/3981483309629928644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=3981483309629928644&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/3981483309629928644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/3981483309629928644'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/06/math-with-patterns-prout.html' title='Math with Patterns &amp; Prout'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-6480440427196319821</id><published>2010-06-06T15:23:00.006-04:00</published><updated>2010-06-06T15:45:11.411-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='function'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='pattern'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Pfunc'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Pfunc</title><content type='html'>&lt;p&gt;Let's say you want to control some part of your &lt;b&gt;Pattern&lt;/b&gt; from, say, a task.  For example, we want to execute some block of code, then wait 5 seconds and then casue the amplitude of a Pbind to fade towards zero.  We can do this by using some variables:&lt;/p&gt;
&lt;pre&gt;
(
 var db, pbind, task;
 
 db = -12;
 
 task = Task({
 
  // ...
  
  5.wait;
  
  60.do({
  
   db = db - 1;
   0.1.wait;
  });
  
  "done fading".postln;
 });
 
 // ...
)
&lt;/pre&gt;
&lt;p&gt;&lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;db&lt;/span&gt; will hold our amplitude in decibels.  We're using db because it's logarithmic and will sound right if we just use subtraction to change the value.&lt;/p&gt;
&lt;p&gt;&lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;task&lt;/span&gt; will hold our task.  That "..." near the top represents whatever we wanted to do before starting the countdown to the fade-out.&lt;/p&gt;
&lt;p&gt;After that, we wait for 5 seconds, then we slowly drop 60 db.&lt;/p&gt;
&lt;p&gt;Now for the pbind:&lt;/p&gt;

&lt;pre&gt;
 // ...

 pbind = Pbind(
  
  \dur,   Pseq([0.2, 0.4, 0.6], inf),
  \degree,   Pseq([0, 3, 5, 7, 9, 8, 8, 2].pyramid(1), inf),
  \steapsPerOctave, 10,
  \db,    db
 );
 
 // ...
  
&lt;/pre&gt;

&lt;p&gt;In the line for degree, we see that we're sending the message &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;pyramid&lt;/span&gt; to the array.  It reorders the array in an interesting way.  See the helpfile for Array for more information about it.&lt;/p&gt;
&lt;p&gt;Pbinds understand the symbol &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;\db&lt;/span&gt; and will convert to amp automatically, as needed.  There's a message you can pass to numbers called dbamp. It converts from db to amps.  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;-12.dbamp&lt;/span&gt; is &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;0.25118864315096&lt;/span&gt;.  Or if you want to go the other way, there's a message ampdb.  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;0.25.ampdb&lt;/span&gt; is &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;-12.041199826559&lt;/span&gt;.  However, the Pbind will do this for you, so you don't need to convert ahead of time.&lt;/p&gt;
&lt;p&gt;Now we can try running the task and the pbind simultaneously:&lt;/p&gt;
&lt;pre&gt;
 // ...
 
 pbind.play;
 task.play;
&lt;/pre&gt;
&lt;p&gt;And when you put this all together and try it, "done fading" prints out, without there having been any fade.&lt;/p&gt;
&lt;p&gt;This is because the interpretter evaluates the expression &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;db&lt;/span&gt; and then passes the result of that expression as an argument to the Pbind contructor.  It is only evaluated that one time. In order to get the current value of &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;db&lt;/span&gt;, we need a way to tell the pbind to re-evaluate it every time it comes up.  We can do that with &lt;b&gt;Pfunc&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Pfunc is a wrapper for functions, so they can be used in patterns.  It's constructor takes a function as an argument and then it evaluates that function every time it's asked for a value.  Let's re-write our pbind:&lt;/p&gt;
&lt;pre&gt;
 // ...

 pbind = Pbind(
  
  \dur,   Pseq([0.2, 0.4, 0.6], inf),
  \degree,   Pseq([0, 3, 5, 7, 9, 8, 8, 2].pyramid(1), inf),
  \steapsPerOctave, 10,
  \db,    Pfunc({db});
 );
 
 // ...
&lt;/pre&gt;
&lt;p&gt;Remember that functions return the value of their last line.  Since we only have one line, it returns that. And, indeed, the amplitude fades away to quiet.  However, the Pbind keeps running even after we can't hear it.  We can use an if statement to tell it to stop:&lt;/p&gt;
&lt;pre&gt;
 pbind = Pbind(
  
  \dur,   Pseq([0.2, 0.4, 0.6], inf),
  \degree,   Pseq([0, 3, 5, 7, 9, 8, 8, 2].pyramid(1), inf),
  \steapsPerOctave, 10,
  \db,    Pfunc({
       if(db &gt; -72, {
        db
       }, {
        nil
       })
      })
 );
&lt;/pre&gt;
&lt;p&gt;Pbinds stop running as soon as any symbol is paired with &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;nil&lt;/span&gt;.  Therefore, when &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;db&lt;/span&gt; gets to -72 and the Pfunc returns nil, the whole Pbind stops.  If the Pbind were in a Pseq, it would go on to the next item.&lt;/p&gt;
&lt;p&gt;You may have also noticed that we don't have semicolons everywhere they could be.  This is because they separate lines of code, so it's ok to skip them on the last (or only) line in a block of code.  It makes no difference to the interpretter if there is a semicolon after &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;nil&lt;/span&gt; or not.  If you find it easier to use them everywhere, then you should keep doing that.&lt;/p&gt;
&lt;p&gt;We could also skip the false function for the if, since it will still return nil if we do:&lt;/p&gt;
&lt;pre&gt;Pfunc({ if(db &gt; -72, { db }) })&lt;/pre&gt;
&lt;p&gt;The final version of this example, all together is:&lt;/p&gt;

&lt;pre&gt;
(
 var db, pbind, task;
 
 db = -12;
 
 task = Task({
 
  // ...
  
  5.wait;
  
  60.do({
   db = db - 1;
   0.1.wait;
  });
  
  "done fading".postln;
 });
 
 
 pbind = Pbind(
  
  \dur,   Pseq([0.2, 0.4, 0.6], inf),
  \degree,   Pseq([0, 3, 5, 7, 9, 8, 8, 2].pyramid(1), inf),
  \steapsPerOctave, 10,
  \db,    Pfunc({ if(db &gt; -72, { db }) })
 );
 
 
 pbind.play;
 task.play;
 
)
&lt;/pre&gt;

&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Decibels can be an easier system to use when computing amplitudes&lt;/li&gt;
&lt;li&gt;Pbinds will convert between db and amp&lt;/li&gt;
&lt;li&gt;The messages ampdb and dbamp can convert number values from amps to db or db to amps&lt;/li&gt;
&lt;li&gt;pyramid is an interesting way of shuffling an array&lt;/li&gt;
&lt;li&gt;You can put a function in a pattern with Pfunc&lt;/li&gt;
&lt;li&gt;A Pfunc with get re-evaluated for every event&lt;/li&gt;
&lt;li&gt;A Pbind stops when it gets a nil value&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Problem&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Write a short piece of music where two separate Pbinds both access the same variable.  They can be in the same Ppar or not.&lt;/li&gt;
&lt;li&gt;Write a programme such that one Pbind sets a flag that causes another Pbind to change in some way.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-6480440427196319821?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/6480440427196319821/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=6480440427196319821&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/6480440427196319821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/6480440427196319821'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/06/pfunc.html' title='Pfunc'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-3535346319173812242</id><published>2010-06-05T12:47:00.003-04:00</published><updated>2010-06-05T13:00:01.829-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='timing'/><category scheme='http://www.blogger.com/atom/ns#' term='pattern'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='pbind'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Polyphony and Sequencing</title><content type='html'>&lt;h3&gt;Chords&lt;/h3&gt;
&lt;p&gt;Now that we can use Pbinds to make sure our sounds come on time, let's look about how to order them and play more than one note at once.  The easiest way to do polyphony is with arrays:&lt;/p&gt;

&lt;pre&gt;Pbind(\note, [1, 3, 5]).play&lt;/pre&gt;

&lt;p&gt;The Pbind creates a separate synth for each item in the array.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;\note&lt;/b&gt; determines pitch as a scale degree in an equal tempered scale. It computes the frequency based on the note number and then uses that for the synth's freq argument. \note can be used with any synthdef.&lt;/p&gt;
&lt;p&gt;While note is always equally tempered, it need not be 12-tone ET:&lt;/p&gt;

&lt;pre&gt;
(
 Pbind(
  \note,    [1, 4, 7],
  \stepsPerOctave,  10
 ).play
)
&lt;/pre&gt;

&lt;p&gt;By pairing \stepsPerOctave with 10, the example above gives us 10-tone ET.  We could do 24 for a quatertone scale, or use whatever number we'd like.&lt;/p&gt;
&lt;p&gt;If, for some reason, we wanted to use MIDI note numbers we could do that. We don't need to use whole numbers, but can use Floats to change the tuning.&lt;/p&gt;

&lt;pre&gt;Pbind(\midinote, 60.05).play&lt;/pre&gt;

&lt;p&gt;60.05 is middle C, 5 cents sharp.&lt;/p&gt;
&lt;h3&gt;Rests&lt;/h3&gt;
&lt;p&gt; If we want to rest for a note, we can do that by pairing the symbol &lt;b&gt;\rest&lt;/b&gt; to any of the symbols that control pitch:&lt;/p&gt;
&lt;pre&gt;
(
 Pbind(
  \dur,   0.2,
  \note,    Prand([1, 4, 7, 9, \rest], 15),
  \stepsPerOctave,  10
 ).play
)
&lt;/pre&gt;
&lt;p&gt;We could also pair rest with \freq, \midinote, or \degree - which is the degree in the scale.&lt;/p&gt;
&lt;h3&gt;Ppar&lt;/h3&gt;
&lt;p&gt;If we want to play two Pbinds at the same time, just telling one to play right after the other does not guarantee that they will line up perfectly.  To make sure they start in sync, we can use &lt;b&gt;Ppar&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Ppar takes two arguments, a list and the number of repeats.  Here's an example from the helpfile:&lt;/p&gt;
&lt;pre&gt;
(
 var a, b;
 a = Pbind(\note, Pseq([7, 4, 0], 4), \dur, Pseq([1, 0.5, 1.5], inf));
 b = Pbind(\note, Pseq([5, 10, 12], 4), \dur, 1);
 Ppar([a, b ]).play;
)
&lt;/pre&gt;
&lt;p&gt;a and b play exactly in time with each other.&lt;/p&gt;
&lt;p&gt;If we don't want all the patterns to start right away, we can use &lt;b&gt;Ptpar&lt;/b&gt;, which is the same except that the list contains pairs of times and patterns. Each time is how long to delay before starting the pattern:&lt;/p&gt;
&lt;pre&gt;
(
 var a, b;
 a = Pbind(\note, Pseq([7, 4, 0], 4), \dur, Pseq([1, 0.5, 1.5], inf));
 b = Pbind(\note, Pseq([5, 10, 12], 4), \dur, 1);
 Ptpar([ 0.0, a, 1.3, b ], 2).play;
)
&lt;/pre&gt;
&lt;p&gt;Pbind a starts immediately, because it's time is 0.  Pbind b starts after 1.3 seconds.  The whole thing repeats twice, because of the second argument to Ptpar&lt;/p&gt;
&lt;p&gt;If, instead of playing at the same time, we wanted to play one after the other, we can put the Pbinds into a Pseq:&lt;/p&gt;
&lt;pre&gt;
(
 var a, b;
 a = Pbind(\note, Pseq([7, 4, 0], 2), \dur, Pseq([1, 0.5, 1.5], inf));
 b = Pbind(\note, Pseq([5, 10, 12], 2), \dur, 1);
 Pseq([a, b ]).play;
)
&lt;/pre&gt;
&lt;p&gt;And Pseqs can be passed to Ppars and Ptpars and vice versa.&lt;/p&gt;
&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Pairing an array with a symbol in a Pbind makes it play chords&lt;/li&gt;
&lt;li&gt;\note determines pitch as a scale degree in an equal tempered scale and can be use with any synthdef.&lt;/li&gt;
&lt;li&gt;\degree is the degree in the scale&lt;/li&gt;
&lt;li&gt;\stepsPerOctave set the number of pitches in the scale used by \note or \degree&lt;/li&gt;
&lt;li&gt;\midinote is the midinote number - in Floats&lt;/li&gt;
&lt;li&gt;Pairing \rest with any of pitch-related symbols will cause a rest&lt;/li&gt;
&lt;li&gt;We can start two or more Pbinds at the same time with Ppar&lt;/li&gt;
&lt;li&gt;We can start two or more Pbinds with a pre-set delay between them using Ptpar&lt;/li&gt;
&lt;li&gt;We can start two Pbinds sequentially by putting them in a Pseq&lt;/li&gt;
&lt;li&gt;We can put Pseqs in Ppars and vice versa.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Problems&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Write a short A B A (refrain verse refrain) piece with a higher pitched line and a lower pitched line, with their own rythms. You can use the default synth for Pbind or one (or more) of your own.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-3535346319173812242?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/3535346319173812242/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=3535346319173812242&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/3535346319173812242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/3535346319173812242'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/06/polyphony-and-sequencing.html' title='Polyphony and Sequencing'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-2089897318745858076</id><published>2010-06-04T15:10:00.005-04:00</published><updated>2010-06-04T16:04:17.594-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='pattern'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='pbind'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Pbinds</title><content type='html'>&lt;p&gt;If you've been using tasks to control rhythmic sounds, you may have noticed that sometimes the timing can wander a bit.  If you have two separate tasks running at the same time, they can also get out of sync.  Tasks don't guarantee exact timing.  Also, remember that the language interpreter and the audio server are separate programs.  There is a small delay between telling the server to play something and when it actually plays it.  It's possible to compensate for this, by giving it instructions slightly ahead of time.  &lt;b&gt;Pbinds&lt;/b&gt; compensate automatically.&lt;/p&gt;

&lt;pre&gt;p = Pbind.new.play;&lt;/pre&gt;

&lt;p&gt;That will repeat forever until you stop it.&lt;/p&gt;
&lt;pre&gt;p.stop;&lt;/pre&gt;

&lt;p&gt;A Pbind is a sort of a &lt;b&gt;pattern&lt;/b&gt;.  Patterns use the information that you provide and make assumptions about the information that you don't.  In the above example, we didn't specify anything, so it picked all default values.  Let's change the frequency:&lt;/p&gt;

&lt;pre&gt;Pbind(\freq, 660).play&lt;/pre&gt;

&lt;p&gt;Pbind.new takes an even number of arguments, as many or as few as you would like.  They come in pairs, where the first member is a symbol and the second is an expression. For example:&lt;/p&gt;

&lt;pre&gt;Pbind(\freq, 660, \dur, 0.2 + 0.3.rand).play&lt;/pre&gt;

&lt;p&gt;Note that the expressions are evaluated when the Pbind's constructor is called.  Therefore, whatever value is returned by &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;0.2 + 0.3.rand&lt;/span&gt; will be the duration for every separate &lt;b&gt;event&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Repeating the same note over and over is rather dull, so there are some patterns that can help.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Prand&lt;/b&gt; takes two arguments, an array and the number of times it should run. For example:&lt;/p&gt;

&lt;pre&gt;
(
 Pbind(
  \freq, Prand([330, 440, 660], 6)
 ).play
)
&lt;/pre&gt; 

&lt;p&gt;When the Pbind is playing, Prand picks a frequency from the array and uses that for the event.  The next time, Prand again picks one of the freqs.  It does this 6 times.  Then the Pbind stops playing.&lt;/p&gt;
&lt;p&gt;You can change the number of repeats to any number you would like, including inf.  If you have multiple patterns in your Pbind, it will stop with whichever one ends first:&lt;/p&gt;

&lt;pre&gt;
(
 Pbind(
  \freq, Prand([330, 440, 660], 6),
  \dur, Prand([0.2, 0.4, 0.3], 5)
 ).play
)
&lt;/pre&gt;

&lt;p&gt;That only plays five notes because the second Prand only will return a value 5 times.&lt;/p&gt;

&lt;p&gt;You can also play through a list with &lt;b&gt;Pseq&lt;/b&gt;:&lt;/p&gt;

&lt;pre&gt;
(
 Pbind(
  \freq, Pseq([ 1/1, 3/2, 4/3, 9/8, 16/9, 5/4, 8/5 ] * 440, 1),
  \dur, Prand([0.2, 0.4, 0.3], inf)
 ).play
)
&lt;/pre&gt;

&lt;p&gt;Pseq takes three arguments: a list and the number of times that it should play through the entire list.  The third argument is an optional offset.  Note that in the example, we're multiplying the entire array by 440.  Every single element is multiplied, which gives us frequencies in the audible range.  Note you can do additional math this way also:&lt;/p&gt;
&lt;pre&gt;
(
 Pbind(
  \freq, Pseq(([ 1/1, 3/2, 4/3, 9/8, 16/9, 5/4, 8/5 ] * 440) + 10, 1),
  \dur, Prand([0.2, 0.4, 0.3], inf)
 ).play
)
&lt;/pre&gt;

&lt;p&gt;The lists passed to patterns can contain other patterns:&lt;/p&gt;

&lt;pre&gt;
(
 Pbind(
  \freq, Pseq([ 1/1, 3/2, 4/3, 9/8, 16/9, 5/4, 8/5 ] * 440, inf),
  \dur, Pseq([
     Pseq([0.2, 0.4], 2), 
     Pseq([0.3, 0.3, 0.6], 1)
    ], 3)
 ).play
)
&lt;/pre&gt;

&lt;p&gt;You can change what synthdef the Pbind is playing with \instrument.  First, let's define a synthdef:&lt;/p&gt;
&lt;pre&gt;
(
 SynthDef(\example9, {|out = 0, freq, amp, dur, pan = 0, mod = 50|
  
  var pm, modulator, env, panner;
  
  modulator = SinOsc.ar(mod, 0, 0.2);
  pm = SinOsc.ar(freq, modulator);
  
  env = EnvGen.kr(Env.perc(0.01, dur, amp), doneAction:2);
  panner = Pan2.ar(pm, pan, env);
  
  Out.ar(out, panner);
 }).store
)
&lt;/pre&gt;

&lt;p&gt;Then, specify it:&lt;/p&gt;

&lt;pre&gt;
(
 Pbind(
  \instrument, \example9,
  \freq,  Pseq([ 1/1, 3/2, 4/3, 9/8, 16/9, 5/4, 8/5 ] * 440, inf),
  \dur,  Pseq([
      Pseq([0.2, 0.4], 2), 
      Pseq([0.3, 0.3, 0.6], 1)
     ], 3)
 ).play
)
&lt;/pre&gt;

&lt;p&gt;We can set values for any of the synthdef's arguments:&lt;/p&gt;

&lt;pre&gt;
(
 Pbind(
  \instrument, \example9,
  \mod,  Pwhite(20, 100, inf),
  \freq,  Pseq([ 1/1, 3/2, 4/3, 9/8, 16/9, 5/4, 8/5 ] * 440, inf),
  \dur,  Pseq([
      Pseq([0.2, 0.4], 2), 
      Pseq([0.3, 0.3, 0.6], 1)
     ], 3)
 ).play
)
&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;Pwhite&lt;/b&gt; takes three arguments, a low number, a high number and the number of times to run.  It then picks random numbers between the low and high values.  In the example, we use those to control the modulation frequency of our synthdef.&lt;/p&gt;
&lt;p&gt;Some argument names for synthdefs are quite common, like: amp, freq, pan, and out.  Pbinds expect to see those argument names and will provide reasonable values if you don't specify.  If you have a more original name for an argument, it's a good idea to specify values for it in the Pbind.&lt;/p&gt;
&lt;pre&gt;
(
 SynthDef(\example9a, {|out = 0, freq, amp, dur, pan = 0, mod = 50, modulation_depth = 0.2|
  
  var pm, modulator, env, panner;
  
  modulator = SinOsc.ar(mod, 0, modulation_depth);
  pm = SinOsc.ar(freq, modulator);
  
  env = EnvGen.kr(Env.perc(0.01, dur, amp), doneAction:2);
  panner = Pan2.ar(pm, pan, env);
  
  Out.ar(out, panner);
 }).store
)


(
 Pbind(
  \instrument, \example9a,
  \modulation_depth,
     0.3,
  \mod,  Pwhite(20, 100, inf),
  \freq,  Pseq([ 1/1, 3/2, 4/3, 9/8, 16/9, 5/4, 8/5 ] * 440, inf),
  \dur,  Pseq([
      Pseq([0.2, 0.4], 2), 
      Pseq([0.3, 0.3, 0.6], 1)
     ], 3)
 ).play
)
&lt;/pre&gt;
&lt;p&gt;Do not assume that your default values from your synthdef will be used. If you want it to always be a certain value, specify that value.&lt;/p&gt;
&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Pbinds are more accurate than Tasks for playing in time.&lt;/li&gt;
&lt;li&gt;Pbinds assume several default values, which you can specify if you want to change them.&lt;/li&gt;
&lt;li&gt;Prand(list, n) picks an item from the given list n times.&lt;/li&gt;
&lt;li&gt;Pseq(list, n) plays the entire list n times.&lt;/li&gt;
&lt;li&gt;If you do a math operation with a SimpleNumber and an array, it does the operation for each item of the array and stores the result in an array.&lt;/li&gt;
&lt;li&gt;Pseqs can contain other patterns, including other Pseqs&lt;/li&gt;
&lt;li&gt;You can specify what synthdef to play with \instrument&lt;/li&gt;
&lt;li&gt;Pwhite(lo, hi, n) picks a number between low and high n times&lt;/li&gt;
&lt;li&gt;Symbols in a Pbind can correspond to synthdef argument names&lt;/li&gt;
&lt;li&gt;If you have an unusual argument name, it's a good idea to specify a value for it in the Pbind&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-2089897318745858076?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/2089897318745858076/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=2089897318745858076&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/2089897318745858076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/2089897318745858076'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/06/pbinds.html' title='Pbinds'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-860199756087544946</id><published>2010-05-31T08:36:00.011-04:00</published><updated>2010-05-31T10:26:58.206-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='array'/><category scheme='http://www.blogger.com/atom/ns#' term='data structures'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Arrays</title><content type='html'>&lt;p&gt;As you've heard many times, a list surrounded by square brackets is an &lt;b&gt;Array&lt;/b&gt;.  Specifically, it's a comma delineated list of 0 or more elements. Here are some examples:&lt;/p&gt;
&lt;pre&gt;
[1]
[x, y, z]
["in", "the", "house"]
[]
&lt;/pre&gt;
&lt;p&gt;There is often more than one way to do something in SuperCollider, as in life.  We can also create an Array by using a constructor.  The constructor takes one argument, the size of the array.&lt;/p&gt;
&lt;pre&gt;
a = Array.new(size);
&lt;/pre&gt;
&lt;p&gt;Arrays can hold any kind of object, including numbers, variables, strings or nothing at all.  They can even mix types:&lt;/p&gt;
&lt;pre&gt;
[3, "French hens", 2 "turtledoves", 1 "partridge"]
&lt;/pre&gt;
&lt;p&gt;Arrays can even hold other arrays:&lt;/p&gt;
&lt;pre&gt;
[[1, 2, 3], [4, 5, 6]]
&lt;/pre&gt;

&lt;p&gt;You can also put an &lt;b&gt;expression&lt;/b&gt; in an array.  The interpreter evaluates it and stores the results.  So &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;[ 3 - 1, 4 + 3, 2 * 6]&lt;/span&gt; is also a valid array, stored as &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;[2, 7, 12]&lt;/span&gt;.  &lt;span class="s4" style="font: normal normal normal 9px/normal Monaco; "&gt;[x.foo(2), x.bar(3)]&lt;/span&gt; is also an array.  It passes those messages to the objects and puts the result into the array.  Because commas have extremely low &lt;b&gt;precedence,&lt;/b&gt; they get evaluated after the expressions they separate.&lt;/p&gt;

&lt;p&gt;A variable can be part of an expression that is put into an array:&lt;/p&gt;
&lt;pre&gt;
(
 var foo, bar;
 ...
 [foo + 1 , bar];
)
&lt;/pre&gt;
&lt;p&gt;In that last case, it holds the value of the expressions (including the variables) at the time they became part of the array.  For example:&lt;/p&gt;
&lt;pre&gt;
(
 var foo, arr;
 foo = 2;
 arr = [foo];
 arr.postln;
 foo. postln;

 " ".postln;

 foo = foo + 1;
 arr.postln;
 foo. postln;
)
&lt;/pre&gt;
&lt;p&gt;Outputs:&lt;/p&gt;
&lt;pre&gt;
[ 2 ]
2

[ 2 ]
3
3
&lt;/pre&gt;

&lt;p&gt;This is &lt;i&gt;almost&lt;/i&gt; just what we expected.  From whence did the second 3 at the bottom come?  SuperCollider's interpreter prints out a return value for every code block that it runs.  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;bar&lt;/span&gt; was the last object in the code block, so &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;bar&lt;/span&gt; gets returned.  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;bar&lt;/span&gt;'s value is 3.&lt;/p&gt;

&lt;p&gt;The variables can go on to change, but the array holds the value that was put in, like a snapshot of when the expression was evaluated.&lt;/p&gt;

&lt;p&gt;What if we declare a five element array and want to add something to the array?  We use the Array.add message.&lt;/p&gt;

&lt;pre&gt;
(
 var arr, new_arr;
 arr = ["Mary", "had", "a", "little"];
 new_arr = arr.add("lamb");
 arr.postln;
 new_arr.postln;
)
&lt;/pre&gt;

&lt;p&gt;Outputs:&lt;/p&gt;

&lt;pre&gt;
[ Mary, had, a, little ]
[ Mary, had, a, little, lamb ]
&lt;/pre&gt;

&lt;p&gt;Arrays cannot grow in size once they've been created.  So, as stated in the helpfile, “the 'add' method may or may not return the same Array object. It will add the argument to the receiver if there is space, otherwise it returns a new Array object with the argument added.” Therefore, when you add something to an array, you need to assign the result to a variable.  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;arr&lt;/span&gt; doesn’t change in the example because it is already full.&lt;/p&gt;

&lt;p&gt;There are other messages you can send to Arrays, which are detailed in the Array helpfile and the helpfile for its superclass ArrayedCollection.  Two of my favorite are &lt;b&gt;scramble&lt;/b&gt; and &lt;b&gt;choose&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;The helpfile says that scramble "returns a new Array whose elements have been scrambled. The receiver is unchanged."&lt;/p&gt;

&lt;p&gt;The results of scramble are different each time you run it, because it scrambles in random order.  When it says, "the receiver is unchanged", it means that if we want to save the scrambled Array, we have to assign that output to a new variable.  The &lt;b&gt;receiver&lt;/b&gt; is the object that &lt;b&gt;receives&lt;/b&gt; the message "scramble."  In the following example, the receiver is &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;arr&lt;/span&gt;, which contains &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;[1, 2, 3, 4, 5, 6]&lt;/span&gt;.&lt;/p&gt;

&lt;pre&gt;
(
 var arr, scrambled;
 arr = [1, 2, 3, 4, 5, 6];
 scrambled = arr.scramble;
 arr.postln;
 scrambled.postln;
)
&lt;/pre&gt;

&lt;p&gt;For me, this output:&lt;/p&gt;

&lt;pre&gt;
[ 1, 2, 3, 4, 5, 6 ]
[ 4, 1, 2, 3, 6, 5 ]
&lt;/pre&gt;

&lt;p&gt;Of course, the second array is different every time.  But &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;arr&lt;/span&gt; is always unchanged.&lt;/p&gt;

&lt;p&gt;Choose is similar.  It picks a random element of the Array and outputs it.  The receiver is unchanged.&lt;/p&gt;
&lt;pre&gt;
[1, 2, 3].choose.postln;
&lt;/pre&gt;
&lt;p&gt;Will output 1, 2 or 3 when you run it.&lt;/p&gt;

&lt;p&gt;Arrays are lists, but they are not merely lists.  They are &lt;b&gt;index&lt;/b&gt;ed lists.  You can ask what the value of an item in an array is &lt;b&gt;at&lt;/b&gt; a particular position.&lt;/p&gt;

&lt;pre&gt;
(
 var arr;
 arr = ["Mary", "had", "a", "little"];
 
 arr.at(1).postln;
 arr.at(3).postln;
)
&lt;/pre&gt;

&lt;p&gt;Outputs:&lt;/p&gt;

&lt;pre&gt;
had
little
&lt;/pre&gt;

&lt;p&gt;Array indexes in SuperCollider start with 0.  In the above example, &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;arr.at(0)&lt;/span&gt; is &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;"Mary"&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;You can also put the index number in square brackets.  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;arr[0]&lt;/span&gt; is the same as &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco;"&gt;arr.at(0)&lt;/span&gt;.  If you are using square brackets, you can also modify the contents of the array:&lt;/p&gt;

&lt;pre&gt;
(
 var arr;
 arr = ["Mary", "had", "a", "little", "lamb"];
 
 arr[4] = "giraffe";
 arr.postln;
)
&lt;/pre&gt;



&lt;p&gt;Arrays also understand the message do, but treat it a bit differently than an Integer does.&lt;/p&gt;

&lt;pre&gt;
(
 [3, 4, 5].do ({ arg item, index;
  ("index: " ++ index ++ " item: " ++ item).postln;
 });
)
&lt;/pre&gt;
&lt;p&gt;Outputs:&lt;/p&gt;
&lt;pre&gt;
index: 0 item: 3
index: 1 item: 4
index: 2 item: 5
&lt;/pre&gt;
&lt;p&gt;We've called our arguments in this example &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;item&lt;/span&gt; and &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;index&lt;/span&gt;, but they can have any name we want.  It doesn't matter what we call them.  The first one always gets the value of the array item that the loop is on and the second one always gets the index.&lt;/p&gt;

&lt;p&gt;The ++ means &lt;b&gt;concatenate&lt;/b&gt;, by the way.  You use it to add something to the end of a string or an array.  For example:&lt;/p&gt;
&lt;p&gt;&lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;"foo " ++ 3&lt;/span&gt;  returns the string  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;"foo 3"&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;With arrays, you can use it to add a single item or another array:&lt;/p&gt;
&lt;pre&gt;
(
 var arr1, arr2, arr3;
 
 arr1 = [1, 2, 3];
 arr2 = arr1 ++ 4;
 arr3 = arr2 ++ [5, 6];
 
 arr1.postln;
 arr2.postln;
 arr3.postln;
)
&lt;/pre&gt;
&lt;p&gt;Outputs&lt;/p&gt;
&lt;pre&gt;
[ 1, 2, 3 ]
[ 1, 2, 3, 4 ]
[ 1, 2, 3, 4, 5, 6 ]
&lt;/pre&gt;
&lt;p&gt;Note that the receiver is unchanged.&lt;/p&gt;
&lt;p&gt;Size is a message which gives us the size of the array.  This can be useful, for example, if we have a variable that we want to use as an index, but which might get bigger than the array:&lt;/p&gt;
&lt;pre&gt;
arr.at(index % arr.size);
&lt;/pre&gt;
&lt;p&gt;Remember that the modulus (%) gives us a remainder.  This means that if the count gets to be greater than the number of elements in the array, using a modulus will cause it to wrap around to zero when it exceeds the size of the array.  There is also a message you can send to arrays that does this for you:&lt;/p&gt;
&lt;pre&gt;arr.wrapAt(index);&lt;/pre&gt;
&lt;p&gt;It does the modulus for you.&lt;/p&gt;
&lt;h4&gt;Musical Example&lt;/h4&gt;
&lt;p&gt;In a previous post, I mentioned Nicole, the ex-grad student working at a SuperCollider startup.  Since then, she's gotten another assignment from her boss.  She has to write a function that takes as arguments: an array of tuning ratios, a base frequency and a detuning amount.  It has to figure out the final pitches by first multiplying the base frequency by the ratio and then adding the detuning amount to the result.  It should then play out the resulting scale.&lt;/p&gt;
&lt;p&gt;She's created SynthDef:&lt;/p&gt;
&lt;pre&gt;
(
 SynthDef(\example8, {|out = 0, freq, amp, dur, pan = 0|
  
  var pm, modulator, env, panner;
  
  modulator = SinOsc.ar(50, 0, 0.2);
  pm = SinOsc.ar(freq, modulator);
  
  env = EnvGen.kr(Env.perc(0.01, dur, amp), doneAction:2);
  panner = Pan2.ar(pm, pan, env);
  
  Out.ar(out, panner);
 }).store
)
&lt;/pre&gt;
&lt;p&gt;Since she's been working in the field, she's learned that instead of writing "arg" followed by a list or arguments and then a semicolon, she can just put all her arguments between two vertical bars.  The two versions are exactly identical.&lt;/p&gt;
&lt;p&gt;In the synthdef, one of the SinOscs is modulating the phase of the other SinOsc.&lt;/p&gt;

&lt;p&gt;After learning about Arrays, our hero does a bit of research on tuning ratios and comes up with an array of ratios that she will use to test her function.  It looks like: &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;[ 1/1, 3/2, 4/3, 9/8, 16/9, 5/4, 8/5 ]&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;That is 1 divided by 1, 3 divided by 2, four divided by 3, etc.  Now remember that precedence means that the interpreter evaluates things in a particular order. It looks at / before it looks at commas.  So it seems a bunch of /'s and starts dividing.  Then it looks at the commas and treats it as an array.  The interpreter stores that array as:&lt;/p&gt;

&lt;pre&gt;[ 1, 1.5, 1.3333333333333, 1.125, 1.7777777777778, 1.25, 1.6 ]&lt;/pre&gt;

&lt;p&gt;Nicole's function will contain a task which cycles through the ratios, taking each one and multiplying it by the base frequency and adding the detuning amount.  Remember that SuperCollider is like a cheap calculator and  +, -, *, and / all have the same precedence.  Math is evaluated from left to right.  So &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;ratio * baseFreq + detune&lt;/span&gt; is not equivalent to &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;detune + ratio * baseFreq&lt;/span&gt;, like it would be in algebra.  However, fortunately, she can use parenthesis like we would in algebra.&lt;/p&gt;

&lt;p&gt;She could write out her &lt;b&gt;expression&lt;/b&gt; as &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;(ratio * baseFreq) + detune&lt;/span&gt; or &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;(detune + (ratio * baseFreq))&lt;/span&gt; or in many other ways.  Even though she could get the right answer without using parenthesis at all, it's good programming practice to use them.  &lt;/p&gt;

&lt;p&gt;Nicole has a formula and she has an Array.  She just needs a way to step through it.  Fortunately, she knows that the 'do' method also exists for Arrays.&lt;/p&gt;

&lt;p&gt;She writes her code as follows:&lt;/p&gt;

&lt;pre&gt;

(

  var func, arr;
  
  func = { |ratio_arr, baseFreq = 440, detune = 10, dur  = 0.2|
   Task({
   var freq;

   ratio_arr.do({ |ratio, index|
    freq =  (ratio * baseFreq) + detune;
    Synth(\example8, [\out, 0, \freq, freq, \amp, 0.2, \dur, dur,
       \pan, 0]);
    dur.wait;
   });
  });
 };
 
 arr = [ 1/1, 3/2, 4/3, 9/8, 16/9, 5/4, 8/5];
 
 func.value(arr, 440, 10).play;
)
&lt;/pre&gt;
&lt;p&gt;This is pretty cool, but it always plays out in the same order, so she changes her do loop to: &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;ratio_arr.scramble.do({ |ratio, index|&lt;/span&gt;&lt;/p&gt;

&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;You can declare an array by putting a list in square brackets or by using the constructor Array(size)&lt;/li&gt;
&lt;li&gt;Arrays can hold any types of objects, all mixed together&lt;/li&gt;
&lt;li&gt;You can put an expression into an array.  It will hold the result of evaluating the expression.&lt;/li&gt;
&lt;li&gt;You can add items to an array by using the add message&lt;/li&gt;
&lt;li&gt;The scramble message returns a new array which has the same contents as the receiver, but in a random order&lt;/li&gt;
&lt;li&gt;The choose message will return a single element of the receiver, chosen at random&lt;/li&gt;
&lt;li&gt;You can access elements of an array with their index:  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;arr.at(index)&lt;/span&gt; or  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;arr[index]&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;You can modify a single element of an array with the index: &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;arr[index] = foo&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;You can loop through an array with do:  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;arr.do({|item, index|&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;++ can be used to concatenate strings or arrays&lt;/li&gt;
&lt;li&gt;arr.size returns the size of the array&lt;/li&gt;
&lt;li&gt;In order to make sure your index is not larger than the size of the array, you can use modulus or wrapAt:  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;arr[index % arr.size]&lt;/span&gt; or  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;arr.wrapAt(index)&lt;/span&gt;
&lt;li&gt;arguments can be listed inside vertical bars instead of after the word arg: &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;|arg1, arg2|&lt;/span&gt; is the same as &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;arg arg1, arg2;&lt;/span&gt;
&lt;/ul&gt;

&lt;h4&gt;Problems&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;You can navigate arrays of different length using variables for indexes.&lt;/li&gt;
&lt;pre&gt;
(

 var arr1, arr2, index;

 arr1 = [1, 2, 3];
 arr2 = [3, 4, 5, 6];
 index = 0;

 2.do({
  arr1.do({ arg item;
   ("arr1 " ++ item).postln;
   ("\t arr2 " ++ arr2.wrapAt(index)).postln; //"\t" means tab 
   index = index + 1;
  });
 });
)
&lt;/pre&gt;
Use this idea to create duration, pitch and wait loops of different lengths.  Write a task to pay them&lt;/li&gt;
&lt;li&gt;In the &lt;a href="http://sc3howto.blogspot.com/2010/05/while.html"&gt;previous post&lt;/a&gt;, there was an example that used if statements to control adding to or subtracting from the frequency.  Instead of changing the frequency directly, change an index that will access an array of tuning ratios.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-860199756087544946?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/860199756087544946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=860199756087544946&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/860199756087544946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/860199756087544946'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/05/arrays.html' title='Arrays'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-4335889088626541582</id><published>2010-05-30T13:24:00.003-04:00</published><updated>2010-05-30T14:28:27.166-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='while'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='control structures'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>While</title><content type='html'>&lt;p&gt;We’ve used Boolean expressions to control the flow of execution of a program with if.  Another &lt;b&gt;control structure&lt;/b&gt; is &lt;b&gt;while&lt;/b&gt;.  While is a message passed to a function.  The function must return either true or false.  It is a test function.  There is another function passed in as an argument.  &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;test_function.while(loop_function);&lt;/span&gt;   If the test function is true, the loop function gets run.  Then the test function is run again.  If it returns true again, the loop function is run again.  This continues until the test function returns false.  &lt;i&gt;While&lt;/i&gt; the condition is true, the loop is executed.&lt;/p&gt;
&lt;pre&gt;
(
 var counter;
 
 counter = 0;
 
 {counter &amp;lt; 6}.while ({
  
  counter = counter + 3.rand;
  counter.postln;
  
 })
)
&lt;/pre&gt;

&lt;p&gt;&lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;{counter &amp;lt; 6}&lt;/span&gt; is the test function.  If it is true, we run the next two lines inside the while loop.&lt;/p&gt;
&lt;p&gt;&lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;counter = counter + 3.rand;&lt;/span&gt; adds the result of 3.rand to the variable counter and then stores the result of that in the variable counter.  Recall that in assignment statements (statements where variables get a value), there can only be one thing on the left of the equals sign.  Everything to the right is evaluated and then result of that evaluation is assigned to the variable.  It's ok to have the same variable on both sides of the equal sign.  The value of the variable does not change until everything has already been evaluated.&lt;/p&gt;
&lt;p&gt;If instead of &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;counter = 0;&lt;/span&gt; we had &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;counter = 7;&lt;/span&gt; the test function would have run once, but the loop function would not have run at all.&lt;/p&gt;
&lt;p&gt;As with if, functional notation is also common with while.  Remember that both notations are entirely equivalent.  The following two lines are the same:&lt;/p&gt;
&lt;pre&gt;
test_func.while(loop_func);
while(test_func, loop_func);
&lt;/pre&gt;
&lt;p&gt;Let's have a musical example, where we track elapsed time rather than the number of notes played.  First, we need a synthdef:&lt;/p&gt;
&lt;pre&gt;
(
 SynthDef(\example7, {arg out = 0, freq = 440, dur = 1, amp = 0.2, pan = 0;
  
  var env, form, panner;
  
  env = EnvGen.kr(Env.perc(0.01, dur, amp), doneAction:2);
  form = Formant.ar(freq, freq + 100, freq + 245);
  panner = Pan2.ar(form, pan, env);
  
  Out.ar(out, panner);
 }).load(s);
)
&lt;/pre&gt;
&lt;p&gt;&lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;Formant&lt;/span&gt; is an oscillator that creates formants. You can find out more about it in it's helpfile.&lt;/p&gt;
&lt;p&gt;&lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;Pan2&lt;/span&gt; is a two channel panner which takes three arguments: the signal, the position and the amplitude.  The position can vary from -1 to 1 and 0 is in the center.&lt;/p&gt;
&lt;p&gt;Now, our Task:&lt;/p&gt;
&lt;pre&gt;

(
 Task({
 
  var freq, dur, total_dur, count; 
  
  dur = 0.17;
  total_dur = 0;
  count = 0;
  
  {total_dur &amp;lt; 20}.while({
  
   freq = 400;
   
   (count % 3 == 0).if({   
    freq = freq + 200;
   });
   (count % 4 == 0).if({   
    freq = freq - 100;
   });
   (count % 5 == 0).if({   
    freq = freq + 400;
   });
   
   Synth(\example7, [\out, 0, \freq, freq, \dur, dur, \amp, 0.2, \pan, 0.7.rand2]);
   
   count = count + 1;
   total_dur = total_dur + dur;
   dur.wait;
  });
 }).play
)
&lt;/pre&gt;
&lt;p&gt;(This code is translated to SuperCollider from a &lt;a href="http://www.perl.com/lpt/a/2004/08/31/livecode.html"&gt;tutorial for making music with Perl&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;At the start, we declare our variables and then we initialise them.  This is an important step, because before we assign them a value, they start out with the value &lt;b&gt;nil&lt;/b&gt;.  Nil is not meaningful with a &amp;lt;, nor with any other mathematical or boolean operation.&lt;/p&gt;
&lt;p&gt;In our test function, we see if the elapsed duration is less than 20 seconds.&lt;/p&gt;
&lt;p&gt;Then in our loop, we add and subtract from a given frequency based on the divisors of a counter.&lt;/p&gt;
&lt;p&gt;&lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;rand2&lt;/span&gt; is a message that can be passed to numbers.  It returns a random result between (-1 * this) and this.  So &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;0.7.rand&lt;/span&gt; returns a number between -0.7 and 0.7.  This will cause our sound to random pan from left of center to right of center.&lt;/p&gt;
&lt;p&gt;After we play the synth, we update all our variables.  If we forget to add the dur to the total_dur, the test function will always return true and we will never leave the loop.  I sometimes forget this, as it's a common bug.&lt;/p&gt;
&lt;p&gt;The next example is very similar to one from the &lt;a href="http://sc3howto.blogspot.com/2010/05/boolean-expressions.html"&gt;previous post&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;
(
 SynthDef("example7b", {arg out = 0, freq = 440, amp = 0.1,
       dur = 1, pan = 0;

     var blip, env, panner;

     env = EnvGen.kr(Env.triangle(dur, 1), doneAction:2);
     blip = Blip.ar(freq, env * 3);
     panner = Pan2.ar(blip, pan, env * amp);
     Out.ar(out, panner);
  }).load(s);
)


(
  Task({
     var freq, synth_dur, high_freq;
  
     high_freq = 800;
  
     while({high_freq &amp;gt; 0}, {
  
        freq = 200 + high_freq.rand;
        if((freq &amp;gt;= 600), {
          synth_dur = 0.1 + 1.0.rand;
        } , {
          if ((freq &amp;lt;= 400), {
           synth_dur = 1 + 5.0.rand;
          },{
           synth_dur = 0.1+ 2.0.rand;
          });
        });
        Synth(\example7b, [\out, 0, \amp, 0.1, \freq, freq,
            \dur, synth_dur, \pan, 0.8.rand2]);
        
        high_freq = high_freq - 50.rand;
        (0.01 + 0.4.rand).wait;
     });
  }).play;
)
&lt;/pre&gt;
&lt;p&gt;Because we keep subtracting from high_freq, the highest possible frequency is tending downwards.  We keep subtracting until it gets to zero.  Incidentally, changing allowable ranges of parameters over time is called &lt;b&gt;tendency masking&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;There are other &lt;b&gt;Control Structures&lt;/b&gt; detailed in a help file called Control-Structures.  Highlight "Control-Structures" and press shift-d&lt;/p&gt;
&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;While is a control structure that controls a loop&lt;/li&gt;
&lt;li&gt;The test condition for while is a function which returns a boolean. While is a message passed to that function. It takes a function as an argument.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Problems&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;It is allowable to have two or more tasks going at the same time.  Write a programme that has two tasks, one playing notes tending upwards ans the other downwards.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;Make it such that when one while stops, the other does also.  You may find it helpful if there is a variable that they both can access.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-4335889088626541582?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/4335889088626541582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=4335889088626541582&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/4335889088626541582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/4335889088626541582'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/05/while.html' title='While'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-2741654677628536730</id><published>2010-05-29T08:08:00.008-04:00</published><updated>2010-05-29T09:44:43.501-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='boolean'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='if'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Boolean Expressions</title><content type='html'>&lt;p&gt;&lt;a href="http://sc3howto.blogspot.com/2010/05/if.html"&gt;Last time&lt;/a&gt;, we learned to randomly pick true or false values, however, it would be more useful if we could test to see what's going on and make decisions according to those tests.  Fortunately, we can do that with &lt;b&gt;boolean expressions&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;An &lt;b&gt;expression&lt;/b&gt; is a bit of code that can be evaluated.  2+3 is an expression, who's value is 5.  A boolean expression is an expression that results in a boolean.  Boolean expressions are usually tests.  For example, we can test for equivalency with &lt;b&gt;==&lt;/b&gt;&lt;/p&gt;
&lt;pre&gt;
(
 a = 3;
 if (a == 3, {
  "true".postln;
 }, {
  "false".postln;
 });
)
&lt;/pre&gt;
&lt;p&gt;Note that is two equal signs next to each other when we're testing for equivalency.  If you just use one equal sign, it means assignment.  I often accidentally type one equals sign when I mean to type two.  &lt;/p&gt;

&lt;p&gt;We can test for &lt;b&gt;greater than&lt;/b&gt; or &lt;b&gt;less than&lt;/b&gt;:&lt;/p&gt;
&lt;pre&gt;
(
 a = 3;
 if (a &amp;gt; 4, {
  "true".postln;
 }, {
  "false".postln;
 });
)
&lt;/pre&gt;
&lt;pre&gt;
(
 a = 3;
 if (a &amp;lt; 4, {
  "true".postln;
 }, {
  "false".postln;
 });
)
&lt;/pre&gt;
&lt;p&gt;We can also test for &lt;b&gt;greater than or equals to&lt;/b&gt; and &lt;b&gt;less than or equals to&lt;/b&gt;:&lt;/p&gt;
&lt;pre&gt;
(
 a = 4;
 if (a &amp;gt;= 4, {
  "true".postln;
 }, {
  "false".postln;
 });
)
&lt;/pre&gt;
&lt;pre&gt;
(
 a = 3;
 if (a &amp;lt;= 4, {
  "true".postln;
 }, {
  "false".postln;
 });
)
&lt;/pre&gt;
&lt;p&gt;We can also do boolean operations.  Some of the most important ones are &lt;b&gt;not&lt;/b&gt;, &lt;b&gt;and&lt;/b&gt;, and &lt;b&gt;or&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;The easiest way to illustrate these is with &lt;b&gt;truth tables&lt;/b&gt;.  A truth table shows you all possible combinations of true and false variables and what the results would be.  Any Boolean variable can be either true or false.  This is a truth table for not:&lt;/p&gt;


&lt;table border="1"&gt;&lt;tbody&gt;&lt;/tbody&gt;&lt;caption&gt;&lt;em&gt;not&lt;/em&gt;&lt;/caption&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;true&lt;/th&gt;&lt;th&gt;false&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;false&lt;/td&gt;&lt;td&gt;true&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Not is a &lt;b&gt;unary operator&lt;/b&gt;.  That means it only involves one object.  The top of the table shows a true input and a false input.  The bottom of the table shows the result.  &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;true.not&lt;/span&gt; returns false and &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;false.not&lt;/span&gt; returns true.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;And&lt;/b&gt; is a &lt;b&gt;binary operator&lt;/b&gt;.  Like +, -, *, / and %, it operates on two objects.  Lets’ say we have two variables, &lt;i&gt;a&lt;/i&gt; and &lt;i&gt;b&lt;/i&gt;, and either of them can be true or false.  We can put &lt;i&gt;a&lt;/i&gt; along the top of the table and &lt;i&gt;b&lt;/i&gt; down the left side.  In the middle we put the possible results of a &lt;b&gt;and&lt;/b&gt; b.&lt;/p&gt;





&lt;table border="1"&gt;&lt;caption&gt;&lt;em&gt;and&lt;/em&gt;&lt;/caption&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;       &lt;th&gt;true&lt;/th&gt;&lt;th&gt;false&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;true&lt;/th&gt;&lt;td&gt;true&lt;/td&gt;&lt;td&gt;false&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;false&lt;/th&gt;&lt;td&gt;false&lt;/td&gt;&lt;td&gt;false&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;&lt;b&gt;Or&lt;/b&gt; is also binary:&lt;/p&gt;






&lt;table border="1"&gt;&lt;caption&gt;&lt;em&gt;or&lt;/em&gt;&lt;/caption&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;       &lt;th&gt;true&lt;/th&gt;&lt;th&gt;false&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;true&lt;/th&gt;&lt;td&gt;true&lt;/td&gt;&lt;td&gt;true&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;false&lt;/th&gt;&lt;td&gt;true&lt;/td&gt;&lt;td&gt;false&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;So how do we code these?  Let’s look again at not. Not can be a message sent to a boolean or boolean expression:&lt;/p&gt;
&lt;pre&gt;
(
 if ((a==4).not , {
  "true".postln;
 }, {
  "false".postln;
 });
)
&lt;/pre&gt;

&lt;p&gt;You can combine not and equivalency with not equals: &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;!=&lt;/span&gt;&lt;/p&gt;

&lt;pre&gt;
(
 a = 2;
 
 if (a != 4 , {
  "true".postln;
 }, {
  "false".postln;
 });
)
&lt;/pre&gt;

&lt;p&gt;The last two examples are the same.&lt;/p&gt;
&lt;p&gt;And is represented by &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;
(
 a = 3;
 b = 4;
 
 if ( (a &amp;gt; 2) &amp;amp;&amp;amp; (b &amp;lt; 5), {
  "true".postln;
 }, {
  "false".postln;
 });
)
&lt;/pre&gt;

&lt;p&gt;Both &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;(a &amp;gt; 2)&lt;/span&gt; &lt;b&gt;and &lt;/b&gt;&lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;(b &amp;lt; 5)&lt;/span&gt; must be true for this expression to evaluate as true.  If one of them is false, the whole thing is false.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Or&lt;/b&gt; is represented by &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;||&lt;/span&gt; (Those are vertical lines.  If you have a Macintosh with an American keyboard, they're over the slash \)&lt;/p&gt;

&lt;pre&gt;
(
 a = 3;
 b = 4;
 
 if ( (a &amp;gt; 2) || (b &amp;lt; 5), {
  "true".postln;
 }, {
  "false".postln;
 });
)

(
 a = 3;
 b = 4;
 
 if ( (a &amp;lt; 2) || (b &amp;lt; 5), {
  "true".postln;
 }, {
  "false".postln;
 });
)

(
 a = 3;
 b = 4;
 
 if ( (a &amp;gt; 2) || (b == 5), {
  "true".postln;
 }, {
  "false".postln;
 });
)
&lt;/pre&gt;

&lt;p&gt;For these expressions to evaluate to true, only one part of it needs to be true.    If neither part of an or is true, then the whole thing is false.&lt;/p&gt;
&lt;h4&gt;Musical Example&lt;/h4&gt;
&lt;p&gt;Let's have a musical example.  We'll again generate random pitches, but low pitches will have long durations and high ones will be short.  First, we need a SynthDef:&lt;/p&gt;
&lt;pre&gt;
(
  SynthDef("example6", {arg out = 0, freq = 440, amp = 0.1,
       dur = 1;

     var blip, env_gen, env;

     env = Env.triangle(dur, 1);
     env_gen = EnvGen.kr(env, doneAction:2);
     blip = Blip.ar(freq, env_gen * 3, env_gen * amp);
     Out.ar(out, blip);
  }).load(s);
)
&lt;/pre&gt;
&lt;p&gt;We're trying out a new oscillator called Blip.  The helpfile for it says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;Blip.ar(freq, numharm, mul, add)&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Band Limited ImPulse generator. All harmonics have equal amplitude. This is the equivalent of 'buzz' in MusicN languages. &lt;/p&gt;

&lt;p&gt;WARNING: This waveform in its raw form could be damaging to your ears at high amplitudes or for long periods.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The first argument is the frequency.  The second is the number of harmonics, which is to say the number of overtones and the third is amplitude.  Loud tones with lots of harmonics can hurt our ears! So let's watch out.  I suspect anyhting that's bad for ears is probably also bad for speakers.&lt;/p&gt;
&lt;p&gt;We're going to control the number of harmonics with the envelope, so they change over time.  We're using the same envelope for amplitude as we are for harmonics, so &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;env_gen * 3&lt;/span&gt; gives us a maximum of 3 harmoics at the peak.  If you want more or less, you can change that number.  And, of course,  &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;env_gen * amp&lt;/span&gt; gives us an envelope that goes from 0 to the amp passed in as an argument.&lt;/p&gt;
&lt;p&gt;Ok, now for the Task that will play this&lt;/p&gt;
&lt;pre&gt;

(
  Task({
    var freq, synth_dur;
    50.do({
      freq = 200 + 800.rand;
      if((freq &gt;= 600), {
       synth_dur = 0.1 + 1.0.rand;
      } , {
       if ((freq &lt;= 400), {
        synth_dur = 1 + 5.0.rand;
       },{
        synth_dur = 0.1+ 2.0.rand;
       });
      });
      Synth(\example6, [\out, 0, \amp, 0.05, \freq, freq, 
          \dur, synth_dur]);
      (0.01 + 0.4.rand).wait;
    });
  }).play;
)
&lt;/pre&gt;
&lt;p&gt;Ok, in our first if statement, we test for frequencies that are greater than or equal to 600 Hz.  If they are that high, then we set our variable synth_dur to &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;0.1 + 1.0.rand&lt;/span&gt;.  If the freq is not that high, we go to the false function.  In the false function, we find another if statement.  In this if statement, we test for frequencies that are less than or equal to 400 Hz.  If they are that low, then we set our variable synth_dur to &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;1 + 5.0.rand&lt;/span&gt;.  the the freq is not that low, we go to the false condition and set our variable synth_dur to &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;0.1+ 2.0.rand&lt;/span&gt;.  We only get to that second false function if both true functions are false.  We could re-write those test conditions:&lt;/p&gt;

&lt;pre&gt;
    if((freq &gt;= 600), {
     synth_dur = 0.1 + 1.0.rand;
    });
    if ((freq &lt;= 400), {
     synth_dur = 1 + 5.0.rand;
    });
    if ((freq &lt; 600) &amp;&amp; (freq &gt; 400), {
     synth_dur = 0.1+ 2.0.rand;
    });
&lt;/pre&gt;

&lt;p&gt;The result would be the same.  But if we do it that way, we have to go through three if statements every time through the loop.  If we do it with nested if statements as above, we only have to go through two of them at most.  And, if the frequency is high, we only need to go through the first one.  So the nested if statements are slightly more efficient, however, it's good to figure out exactly what conditions would have to be to get to a particular code block.&lt;/p&gt;
&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;An expression is a snippet of code that has a value or can return a value&lt;/li&gt;
&lt;li&gt;You can test for equivalency with ==&lt;/li&gt;
&lt;li&gt;Greater than is &amp;gt;&lt;/li&gt;
&lt;li&gt;Less than is &amp;lt;&lt;/li&gt;
&lt;li&gt;Greater than or equal to is &amp;gt;=&lt;/li&gt;
&lt;li&gt;Less than or equal to is &amp;lt;=&lt;/li&gt;
&lt;li&gt;Not is &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;boolean.not&lt;/span&gt; and causes things to invert&lt;/li&gt;
&lt;li&gt;Not equals is !=&lt;/li&gt;
&lt;li&gt;And is &amp;&amp;. Both conditions must be true for and to be true.&lt;/li&gt;
&lt;li&gt;Or is ||. One or both conditions must be true for or to be true.&lt;/li&gt;
&lt;li&gt;If statements can be nested&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Problems&lt;/h4&gt;
&lt;li&gt;Write if statements using &lt;b&gt;and&lt;/b&gt;, &lt;b&gt;or&lt;/b&gt;, and &lt;b&gt;not&lt;/b&gt; using Boolean values of true and false to illustrate the truth tables, using all possible combinations of true and false. For example:
&lt;pre&gt;
(
 if (true.not, {
  "true".postln;
 }, {
  "false".postln;
 });
)
&lt;/pre&gt;
What do you expect each of them to print?  Did the results you got from running them match your expectations?&lt;/li&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-2741654677628536730?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/2741654677628536730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=2741654677628536730&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/2741654677628536730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/2741654677628536730'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/05/boolean-expressions.html' title='Boolean Expressions'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-4678286186176915211</id><published>2010-05-28T10:56:00.006-04:00</published><updated>2010-05-28T11:58:59.650-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functional notation'/><category scheme='http://www.blogger.com/atom/ns#' term='boolean'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='control structures'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='if'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>If</title><content type='html'>&lt;p&gt;In our programmes, we need &lt;b&gt;control structures&lt;/b&gt;, that is,  ways to make decisions.  One control structure is &lt;b&gt;if&lt;/b&gt;.  &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;if&lt;/span&gt; has it's own helpfile.  Highlight &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;if&lt;/span&gt; and press apple-d.  If is also explained briefly in the helpfile for &lt;b&gt;Boolean&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;b&gt;Boolean&lt;/b&gt; is a value that is either true or false.  &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;true&lt;/span&gt; and &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;false&lt;/span&gt; are reserved words in SuperCollider.  We can send an &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;if &lt;/span&gt;message to Booleans.&lt;/p&gt;

&lt;pre&gt;
(
 ([true, false].choose).if(
  {
   "true".postln;   
  }, {
   "false".postln;
  }
 );
)
&lt;/pre&gt;
&lt;p&gt;Remember that a list surrounded by square brackets is an Array.  Arrays understand a message called choose.  It randomly picks an item in the array and returns it.&lt;/p&gt;

&lt;p&gt;If you run the above code several times, “true” and “false” should print out about the same number of times in a random order, because &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;[true, false].choose&lt;/span&gt; ought to be true half the time and false the other half.  The result of that expression is a Boolean.  We send an if message to the Boolean, which has two arguments, both functions.  The first function is evaluated if the Boolean is true.  The second function is evaluated if the Boolean is false.&lt;/p&gt;

&lt;pre&gt;boolean.if(trueFunction, falseFunction);&lt;/pre&gt;

&lt;p&gt;You can omit the false function if you want.&lt;/p&gt;

&lt;p&gt;This syntax that we've been using, &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;object.message(argument1, argument2, . . . argumentN);&lt;/span&gt;, is the most commonly used syntax in SuperCollider programs.  It's called &lt;b&gt;receiver notation&lt;/b&gt;.  However, there is more than one correct syntax in SuperCollider.  There also exists a syntax called &lt;b&gt;functional notation&lt;/b&gt;.  It is more commonly used with if messages than receiver notation. When you see if in the helpfiles, the examples almost always use functional notation.  Functional notation is:&lt;/p&gt;

&lt;pre&gt;message(object, argument1, argument2,  . . . argumentN);&lt;/pre&gt;

&lt;p&gt;The two notations are equivalent.  You can replace one with the other at any place in any program and it will not change the program.  The reason that I bring this up is that people very commonly use functional notation for if:&lt;/p&gt;

&lt;pre&gt;if(boolean, trueFunc, falseFunc);&lt;/pre&gt;

&lt;p&gt;So our example would change to:&lt;/p&gt;

&lt;pre&gt;
(
 if([true, false].choose, {
  "true".postln;   
 }, {
  "false".postln;
 });
)
&lt;/pre&gt;

&lt;p&gt;It works in exactly the same way.&lt;/p&gt;

&lt;p&gt;Why are there multiple correct notations?  It's confusing!&lt;/p&gt;

&lt;p&gt;SuperCollider is based on many other programming languages, but the language that it borrows most heavily on is one called Smalltalk.  Smalltalk, like SuperCollider, is an object-oriented language.  When I took Programming Languages at uni, my teacher said that Smalltalk was the best object oriented language and the only reason it wasn't the most popular was that the syntax was insane.&lt;/p&gt;

&lt;p&gt;So rather than force us to use Smalltalk syntax, James McCartney, the author of SuperCollider, allows us multiple legal syntaxes.  Receiver notation is common in several object-oriented languages.  Functional notation, however, persists in if, probably because other languages have different ways of thinking about if.&lt;/p&gt;

&lt;p&gt;Let's code an overtone player that has a 50% chance of resting. First, we need a synthdef:&lt;/p&gt;
&lt;pre&gt;
(
 SynthDef.new("example5", {arg out = 0, freq = 440, amp = 0.2,
     dur = 1;

   var saw, env_gen, env;

   env = Env.triangle(dur, amp);
   env_gen = EnvGen.kr(env, doneAction:2);
   saw = Saw.ar(freq, env_gen);
   Out.ar(out, saw);
 }).load(s);
)
&lt;/pre&gt;
&lt;p&gt;This one uses a sawtooth wave oscillator.  Check out the helpfile for &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;Saw&lt;/span&gt; for more information.&lt;/p&gt;
&lt;p&gt;Then, our player:&lt;/p&gt;
&lt;pre&gt;
(
 var player;
 
 player = { arg baseFreq, numOvertones, dur = 0.2;
  var freq;
  Task({
    (numOvertones + 1).do({ arg index;
    freq = index * baseFreq;
    if ([true, false].choose, {
     Synth(\example5, [\out, 0, \freq, freq, \dur, dur]);
    });
      dur.wait;
     });
   });
  };
  
  player.value(220, 12).play;
)
&lt;/pre&gt;
&lt;p&gt;If you run it several times, it should rest in different spots, about half the time.&lt;/p&gt;

&lt;p&gt;If we want to give it a  33.3% chance of resting (a 66% chance of playing), we could change out if to look like &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;[true, true, false].choose&lt;/span&gt; and expand our array every time we want to change the probability.  But what if we want something to play 99% of the time?  We would have to have 99 trues and one false.  Fortunately, there is a message you can use that returns a Boolean based on percentage.  To play 99% of the time, we would use &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;0.99.coin&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;If you look at the helpfile for float, you learn that coin, "answers a Boolean which is the result of a random test whose probability of success in a range from zero to one is this."  Which means that 0.66.coin has a 66% chance of being true and 0.01.coin has a 1% chance of being true.&lt;/p&gt;
&lt;p&gt;The word "this" in that description refers to the number which received the message.  If you type 0.66.coin, "this" is 0.66.&lt;/p&gt;

&lt;p&gt;Let's give our an example 75% chance of playing a given note:&lt;/p&gt;
&lt;pre&gt;
(
 var player;
 
 player = { arg baseFreq, numOvertones, dur = 0.2;
  var freq;
  Task({
    (numOvertones + 1).do({ arg index;
    freq = index * baseFreq;
    if (0.75.coin, {
     Synth(\example5, [\out, 0, \freq, freq, \dur, dur]);
    });
      dur.wait;
     });
   });
  };
  
  player.value(220, 12).play;
)
&lt;/pre&gt;

&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Booleans are either true or false&lt;/li&gt;
&lt;li&gt;if is a way of controlling programme flow and making decisions&lt;/li&gt;
&lt;li&gt;receiver notation is object.message(argument)&lt;/li&gt;
&lt;li&gt;functional notation is message(object, argument)&lt;/li&gt;
&lt;li&gt;receiver notation and functional notation are only stylistic differences and both do exactly the same thing&lt;/li&gt;
&lt;li&gt;if is often typed as if(boolean, true_function, false_function)&lt;/li&gt;
&lt;li&gt;The fase function is optional&lt;/li&gt;
&lt;li&gt;The choose message causes an array to pick a single element at random&lt;/li&gt;
&lt;li&gt;&lt;i&gt;n&lt;/i&gt;.coin returns a boolean value with &lt;i&gt;n&lt;/i&gt; probability of being true&lt;/li&gt;
&lt;li&gt;In helpfiles and other places, "this" refers to the object that received the message&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Problems&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Re-write  &lt;span class="s2" style="font: normal normal normal 10px/normal Monaco; "&gt;"Hello World".postln&lt;/span&gt; in functional notation.&lt;/li&gt;
&lt;li&gt;Write a programme that has 66% chance of playing the any given note in an arpeggio and a 33% chance of playing a random note instead. You will need to use a false function.&lt;/li&gt;
&lt;li&gt;The functions of ifs can contain other ifs.  Write a programme that has a 50% chance of playing any given note in arpeggio, a 25% chance of playing a random note and a 25% chance of resting.  Remember that if you write if(0.25.coin . . .), it has a 75% chance of picking false and evaluating the false function (if one is present).&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-4678286186176915211?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/4678286186176915211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=4678286186176915211&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/4678286186176915211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/4678286186176915211'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/05/if.html' title='If'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-4167338429183960035</id><published>2010-05-27T09:54:00.014-04:00</published><updated>2010-06-08T13:47:17.192-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='function'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='timing'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='wait'/><category scheme='http://www.blogger.com/atom/ns#' term='task'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Tasks</title><content type='html'>&lt;p&gt;&lt;a href="http://sc3howto.blogspot.com/2010/05/envelopes.html"&gt;Last time&lt;/a&gt;, we learned how to use an envelope to cause synths to stop playing after a set time.  Now we're going to look at one way we can control when they start.  As with any programming language, there are multiple ways to do this in SuperCollider, each with particular strengths and weaknesses.&lt;/p&gt;
&lt;p&gt;We're going to look at something called a &lt;b&gt;Task&lt;/b&gt;:&lt;/p&gt;

&lt;pre&gt;
(
 r  = Task.new ({
 
  5.do({ arg index;
   index.postln;
   1.wait;
  });
 });
 
 r.play;
)
&lt;/pre&gt;
&lt;p&gt;That example prints out:&lt;/p&gt;
&lt;pre&gt;
0
1
2
3
4
&lt;/pre&gt;
&lt;p&gt;With a one second pause between each number.  Try running it.&lt;/p&gt;
&lt;p&gt;Remember that the letters a-z are global variables in SuperCollider.  Also, remember that the class SimpleNumber is a superclass of both Float and Integer.  It can take a message called &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;wait&lt;/span&gt;. That message only works in the context of a task (or it's superclasses, like  Routine).  If we try &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;wait&lt;/span&gt; in a normal function:&lt;/p&gt;

&lt;pre&gt;
(
 f  = {
 
  5.do({ arg index;
   index.postln;
   1.wait;
  });
 };
 
 f.value;
)
&lt;/pre&gt;
&lt;p&gt;We get errors:&lt;/p&gt;
&lt;pre&gt;
• ERROR: yield was called outside of a Routine.
ERROR: Primitive '_RoutineYield' failed.
Failed.
&lt;/pre&gt;

&lt;p&gt;Tasks (which are a subclass of Routine) are one powerful way to add timing to your program.  Task.new takes a function as an argument.  It runs that function when we send it the &lt;b&gt;play&lt;/b&gt; message.  Hence, &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;r.play;&lt;/span&gt; in the Task example.  When we play a Task, it will pause for a duration of SimpleNumber.wait.  If we code &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;5.wait&lt;/span&gt;, it will pause for five seconds.  If we have &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;0.5.wait&lt;/span&gt;, it will pause for half a second.&lt;/p&gt;

&lt;p&gt;Ok, now we know how to control when things happen!  Let's try this to play some notes!  First we need a SynthDef:&lt;/p&gt;

&lt;pre&gt;
(
 SynthDef.new("example4", {arg out = 0, freq = 440, amp = 0.2,
    dur = 1;

  var square, env_gen, env;

  env = Env.triangle(dur, amp);
  env_gen = EnvGen.kr(env, doneAction:2);
  square = Pulse.ar(freq, 0.5, env_gen);
  Out.ar(out, square);
 }).load(s);
)
&lt;/pre&gt;
&lt;p&gt;This is just like our last SynthDef, except that it uses a square wave instead of  a sine wave.  To find out more about the Pulse UGen, read the help file on it.&lt;/p&gt;
&lt;p&gt;Ok, let's play some pitches.  the range of human hearing is 20Hz - 20,000 Hz, but the range of my laptop speakers is somewhat less than that, so let's pick between 200 - 800 Hz.&lt;/p&gt;
&lt;pre&gt;
(
 Task({
  var freq;
  10.do({
   freq = 200 + 600.rand;
   Synth(\example4, [\out, 0, \freq, freq, \dur, 0.5]);
   0.5.wait;
  });
 }).play;
)
&lt;/pre&gt;
&lt;p&gt;When you we that, we get random pitches.&lt;/p&gt;
&lt;p&gt;In the first line, you'll notice that we just have &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;Task({&lt;/span&gt; instead of &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;Task.new({&lt;/span&gt;.  This is a shortcut that SuperCollider allows.  You can just have Class(argument1 , argument2 . . .) in place of Class.new(argument1, argument2 . . .).  The &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;.new&lt;/span&gt; is implied.&lt;/p&gt;
&lt;p&gt;The next line with something new is &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;freq = 200 + 600.rand;&lt;/span&gt;.  You can pass the message &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;rand&lt;/span&gt; so a SimpleNumber.  It will return a random number between 0 and the number that it's passed to.  So &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;600.rand&lt;/span&gt; will return a random number between 0 - 600.  If we add 200 to that number, then we have a random number between 200 - 800, which is the range we want.&lt;/p&gt;
&lt;p&gt;In the past, we &lt;a href="http://sc3howto.blogspot.com/2010/05/numbers-and-math.html"&gt;talked a bit about precedence&lt;/a&gt;.  In SuperCollider, passing messages will be evaluated before math operations like addition, subtraction, etc.  So the interpreter will evaluate 600.rand first and then add 200.  Therefore, we will get the same results if we type &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;freq = 200 + 600.rand;&lt;/span&gt; or if we type &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;freq = 600.rand + 200;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In the next line, we've got &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;Synth(\example4&lt;/span&gt; instead of  &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;Synth.new(\example4&lt;/span&gt;. This is the same shortcut as in the first line.&lt;/p&gt;
&lt;p&gt;In that example, we pass 0.5 to the synth for it's duration and wait 0.5 seconds, so there's no overlap between the notes.  We don't have to do it that way.  We could only wait for 0.25 seconds and let the notes overlap, or we could extend the wait and leave spaces between the notes.  Or we could change the Synth duration. We could use random numbers for waits and durations:&lt;/p&gt;
&lt;pre&gt;
(
 Task({
  var freq;
  10.do({
   freq = 200 + 600.rand;
   Synth(\example4, [\out, 0, \freq, freq, \dur, (0.1+ 2.0.rand)]);
   (0.01 + 0.4.rand).wait;
  });
 }).play;
)
&lt;/pre&gt;
&lt;p&gt;The two parts that have changed are &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;\dur, (0.1+ 2.0.rand)&lt;/span&gt; and &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;(0.01 + 0.4.rand).wait;&lt;/span&gt;.  The reason that we have 2.0.rand is because Integer.rand returns an Integer and Float.rand returns a float.  2 is an integer, so 2.rand will return either 1 or 0 and no other numbers.  2.0.rand, however, will return real numbers and thus can return things like 0.72889876365662 or 1.6925632953644.  Try evaluating 2.rand and 2.0.rand several times and look at the results you get.&lt;/p&gt;
&lt;p&gt;We use parenthesis in &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;(0.01 + 0.4.rand).wait;&lt;/span&gt; so that we sent the wait message to the results of 0.01 + 0.4.rand.  If we were to skip the parenthesis, we would pick a random number between 0 and 0.4 and then wait that long and then add 0.01 to the results of the wait message, which is not what what we want.  We add in that 0.01 to make sure that we never have a wait of 0.  This is an aesthetic decision.  0.wait is perfectly acceptable.&lt;/p&gt;
&lt;p&gt;What if we want to modify the number of times we run through our main loop?  We can't pass arguments to a Task, but fortunately, because of &lt;b&gt;scope&lt;/b&gt; and functions &lt;b&gt;returning&lt;/b&gt; things, there is a clever work around:&lt;/p&gt;
&lt;pre&gt;
(
var func, task;

func = { arg repeats = 10;

 Task({  
  var freq;
  repeats.do({
   freq = 200 + 600.rand;
   Synth(\example4, [\out, 0, \freq, freq, \dur, (0.1+ 2.0.rand)]);
   0.01 + 0.4.rand.wait;
  });
 });
 
};

task = func.value(15);
task.play;
)
&lt;/pre&gt;
&lt;p&gt;First, we write a function that takes an argument.  Then, inside the function, we have a Task.  Because the Task is inside the function's code block, the Task is within the scope of the argument.  And because the Task is the last (and only, aside from the args) thing inside the function, it gets returned when the function gets evaluated.  So &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;task&lt;/span&gt;&lt;span class="s4" style="font: normal normal normal 9px/normal Monaco; "&gt; &lt;/span&gt;gets the Task that is returned by the function.  Then we call &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;task.play;&lt;/span&gt; to run the Task.  It's ok to have a variable called task because SuperCollider is case-sensitive and therefore Task, task, tASK, taSk, etc are all different.&lt;/p&gt;

&lt;p&gt;Remember that functions &lt;b&gt;return&lt;/b&gt; their last value.  And remember that &lt;b&gt;scope&lt;/b&gt; means that inner code blocks can see variables from outer code blocks, but not vice versa.  So the Task can see the args.  And there's nothing after the Task in the function, so it's the last value, so it gets returned when we send a value message to the function.  Then we send a play message to the returned Task.  We could abbreviate the last two lines of our program by just having one line:&lt;/p&gt;
&lt;pre&gt;func.value(15).play;&lt;/pre&gt;

&lt;p &gt;The interpreter, reading from right to left, will pass a value message to the func, with an argument of &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;15&lt;/span&gt;.  That returns a Task, which is then passed a message of play.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Tasks are functions that can pause.&lt;/li&gt;
&lt;li&gt;In a task, &lt;i&gt;number&lt;/i&gt;.wait will pause for that number of seconds.&lt;/li&gt;
&lt;li&gt;You cannot ask a code block to wait unless it is within a a Routine, which is a superclass of Task.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;n&lt;/i&gt;.rand returns a number between 0 and &lt;i&gt;n&lt;/i&gt;. If &lt;i&gt;n&lt;/i&gt; is an integer, it returns an integer.  If &lt;i&gt;n&lt;/i&gt; is a float, it returns a float.&lt;/li&gt;
&lt;li&gt;You cannot pass arguments to Tasks, but you can put them in functions that take arguments and then return the Task from the function.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Problems&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Write a a task that plays an arpeggio of the first &lt;i&gt;n&lt;/i&gt; overtones over a base frequency. Use a wrapper function to pass in both the frequency and the number of overtones.  Give the arguments descriptive names.  (There is an explanation of overtones in the &lt;a href="http://sc3howto.blogspot.com/2010/05/numbers-and-math.html"&gt;post on numbers&lt;/a&gt;.)&lt;/li&gt;

&lt;li&gt;Write a task that produces &lt;i&gt;n&lt;/i&gt; separate sound clusters.  Pass that number as an argument (using functions).  Give the argument a descriptive name.&lt;/li&gt;

&lt;/ol&gt;
&lt;h4&gt;Project&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Write a short piece that uses tone clusters that are in different frequency ranges.  For example, one section might be 100-300 Hz and another might be 600-1200 Hz.  You may wish to vary the timbres by using multiple synthdefs.  You may wish different sections to have different densities, also.&lt;/p&gt;  
&lt;p&gt;You can make a recording of your piece by pressing the "Prepare Record button" on the server window, after you boot it. It will turn red and say "record &amp;gt;".  Press it again to start recording. The button will change color again and say "stop []".  this means it's now recording. Run your piece.  Click the button again when your piece has finished to stop recording.  The Recording will go in to your home directory under Music/SuperCollider Recordings.  It will be a 32 bit aiff, but you can convert it to a 16bit aiff or to mp3 with &lt;a href="http://audacity.sourceforge.net/"&gt;Audacity&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you do this project, please feel free to share your results in the comments!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-4167338429183960035?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/4167338429183960035/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=4167338429183960035&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/4167338429183960035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/4167338429183960035'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/05/tasks.html' title='Tasks'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-3983657316341019929</id><published>2010-05-26T08:43:00.006-04:00</published><updated>2010-05-26T09:20:20.039-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='envelopes'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='synthdef'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Envelopes</title><content type='html'>&lt;p&gt;In the &lt;a href="http://sc3howto.blogspot.com/2010/05/numbers-and-math.html"&gt;last post&lt;/a&gt;,  we wrote a function to play overtones, but it played them all at the same time.   In order to write a piece of music, we need both to be able to tell notes when to start and for how long they should last.  This section will be on the latter part of the problem.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"Just like human beings, sounds are born, reach their prime and die; but the life of a sound, from creation to evanescence last only a few seconds"

Yamaha GX-1 Guide&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; We control this process with a type of UGen called an &lt;b&gt;envelope&lt;/b&gt;. &lt;/p&gt;


&lt;pre&gt;
(
 SynthDef.new("example3", {arg out = 0, freq = 440, amp = 0.2,
       dur = 1;
  var sin, env_gen, env;
  
  env = Env.triangle(dur, amp);
  env_gen = EnvGen.kr(env);
  sin = SinOsc.ar(freq, mul: env_gen);
  Out.ar(out, sin);
 }).load(s);
)

Synth.new("example3");
&lt;/pre&gt;

&lt;p&gt;There are a few things that make that SynthDef different.  One is that it uses variables.  Variables are a good way to keep SynthDefs more readable.  The easier it is to read, the easier it is to understand, to fix and to change.&lt;/p&gt;

&lt;p&gt;The other obvious change is the addition of an envelope.  Envelopes have two parts.  One is &lt;b&gt;Env&lt;/b&gt;.  The Env class lets you describe what shape the envelope should have.  In this case, we're using a &lt;b&gt;fixed duration&lt;/b&gt; envelope shaped like a triangle.  When we use a fixed duration envelope, we know the length of the envelope when we create an instance of the Synth.  There are other envelopes that we will not know the envelope of until we decide to end the note, for instance, in response to a key up on a keyboard.&lt;/p&gt;

&lt;p&gt;&lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;triangle&lt;/span&gt; is a constructor.  It creates a new instance of an Env.  The arguments it takes are the duration and the maximum amplitude.&lt;/p&gt;

&lt;p&gt;The other part of the envelope is the&lt;span class="s7" style="font: normal normal normal 12px/normal Helvetica; "&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;EnvGen&lt;/b&gt;. Since EnvGen is a class, &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;kr&lt;/span&gt; must be a constructor.  The two most common UGen constructors are &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;ar&lt;/span&gt; and &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;kr&lt;/span&gt;.  You may recall that ar stands for “audio rate.”  kr stands for “control rate.”  Because the EnvGen is not actually creating sound, but is controlling the amplitude of a sound, we want the control rate.  Control rate signals change less often than audio rate signals, and so using kr reduces the load on our computer and makes our SynthDef more efficient.  &lt;/p&gt;

&lt;p&gt;EnvGen.kr generates the envelope based on the specifications of its first argument, an instance of Env. So, with Env, we define an Envelope.  We pass that definition to an Envelop Generator, which plays back the envelope that we defined.  We use that envelope to control the amplitude of a SinOsc.  We send the output of the SinOsc to an output bus.  When the envelope is done, the amplitude of it has returned to zero, so the SinOsc is no longer audible.&lt;/p&gt;

&lt;p&gt;With our previous examples, the Synth never ended.  The way to stop sound was to stop execution with apple-. .  With our new SynthDef, the sound goes on for exactly the length of dur and then ends with no way to restart it.  After we create a Synth and play it, there's nothing that can be done with it.&lt;/p&gt;

&lt;p&gt;Try running &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;Synth.new("example3");&lt;/span&gt; several times.  If you look at the localhost server window, you will see the number of UGens and Synths grow every time you run Synth.new.  The Avg and Peak CPU may also increase.&lt;/p&gt;

&lt;p&gt;Every time we create a new instance of Synth, we use up more system resources.  Eventually we will either run out of memory or the CPU will climb over 100%.  We can clear the Synths by hitting apple-., but this still would limit the number of sounds we could play in a row without stopping execution.&lt;/p&gt;

&lt;p&gt;We need an automatic way to remove our synths from the server and &lt;b&gt;deallocate&lt;/b&gt; their resources.  That means that some new Synths would be able to use the resources the old ones were taking up.&lt;/p&gt;

&lt;p&gt;Fortunately, EnvGens can both silence a Synth forever and lay it to rest so iti s deallocated.  EnvGen takes an argument called “doneAction”.  Adding a &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;doneAction&lt;/span&gt; to your EnvGen would look like:&lt;/p&gt;
&lt;pre&gt;env_gen = EnvGen.kr(env, doneAction: 2);&lt;/pre&gt;

&lt;p&gt;Try changing adding a doneAction to the SynthDef and running &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;Synth.new("example3");&lt;/span&gt; a few times.  Notice that now the Synths don’t accumulate.  Now, after a Synth stops making sound, it has ended its useful life and so it gets removed from the server because of the &lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;doneAction: 2&lt;/span&gt;.   However, note that the doneAction removes only instances of the Synth.  The SynthDef persists and can be used as many times as we'd like.&lt;/p&gt;

&lt;p&gt;Envelopes don’t have to only control amplitude, but can control (almost) any aspect of any UGen.  You can’t set the bus on Out.ar with an Envelope, but you can control almost anything else. For example, we can cause the frequency to warble&lt;/p&gt;
&lt;pre&gt;

(
 SynthDef.new("example3a", {arg out = 0, freq = 440, amp = 0.2,
       dur = 1;

  var sin, env_gen, env, freq_env;
  
  env = Env.triangle(dur, amp);
  env_gen = EnvGen.kr(env, doneAction: 2);
  freq_env = EnvGen.kr(Env.sine(dur, 50));

  sin = SinOsc.ar(freq + freq_env, mul: env_gen);
  Out.ar(out, sin);
 }).load(s);
)

Synth.new("example3a");
&lt;/pre&gt;
&lt;p&gt;Note that we only need one of the envelopes to have a doneAction.&lt;/p&gt;


&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Envelopes can be used to control how the amplitude of a Synth changes over time.
&lt;li&gt;&lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;Env&lt;/span&gt; is used to describe the shape of an enevelope.
&lt;li&gt;&lt;span class="s3" style="font: normal normal normal 10px/normal Monaco; "&gt;EnvGen.kr&lt;/span&gt; is what actually plays the envelope.
&lt;li&gt;Synths can be deallocated by using the doneAction argument of EnvGen.
&lt;li&gt;Envelopes can also be used to control frequency and many other parameters of SynthDefs.
&lt;/ul&gt;
&lt;h4&gt;Problems&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Try out the different fixed duration envelopes and try them out with different Oscillators.  Especially try out the Env.perc envelope with different noise generators.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-3983657316341019929?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/3983657316341019929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=3983657316341019929&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/3983657316341019929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/3983657316341019929'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/05/envelopes.html' title='Envelopes'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-6976317234662622355</id><published>2010-05-24T09:55:00.008-04:00</published><updated>2010-05-24T10:52:53.867-04:00</updated><title type='text'>Numbers and Math</title><content type='html'>&lt;p&gt;In the &lt;a href="http://sc3howto.blogspot.com/2010/05/functions.html"&gt;previous post&lt;/a&gt;, we talked a bit about Integers, which, remember are whole numbers, like -1, 0, 1, 2.  And we learned about the do message.&lt;/p&gt;
&lt;p&gt;What are some things you might want to do to a number?  Add, subtract, multiply, divide, modulus.&lt;/p&gt;

&lt;p&gt;Remember algebra where a*b + c*d = (a * b) + (c * d).  And remember how that one cheap calculator just did what you punched in, in the order you punched it in, without respecting order of operations?  SuperCollider is like that cheap calculator.  Mathematical expressions are evaluated left to right.  Addition and subtraction have the same &lt;b&gt;precedence&lt;/b&gt; as multiplication and division.  That means that if you want to do things in some order, you've got to use parenthesis.&lt;/p&gt;

&lt;p&gt;Parentheses are evaluated innermost to outermost:&lt;br /&gt;

(a + (b * (c + d)))&lt;br /&gt;

( 2 + (4 * (3 + 2))) = (2 + (4 *(5))) = (2 + (20)) = 22&lt;/p&gt;

&lt;p&gt;What about order of operations within longer lines of code?  If we have&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;&lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;func.value(3+4)&lt;/span&gt;, it evaluates &lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;3+ 4&lt;/span&gt;&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;to&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;&lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;7&lt;/span&gt;&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;before calling the function.  We can put anything we want inside those parentheses and it will evaluate what's inside until it gets to the outermost parenthesis and then it will call the function.&lt;/p&gt;


&lt;p&gt;One math operation that you might not have seen before is &lt;b&gt;modulus&lt;/b&gt;. It means "remainder" and it's represented by a '%'.&lt;br /&gt;

10 % 3 = 1&lt;br /&gt;

26 % 9 = 8&lt;/p&gt;

&lt;p&gt;Ok, so the output of a modulus between two integers is an integer, by definition.  And if you add or subtract two integers, you get an integer.  As you do if you multiply two integers.  But what is the result of division? &lt;br /&gt;

3 / 2 = 1.5&lt;/p&gt;

&lt;p&gt;1.5 is not an integer.  It's a type of number called a Floating point, or in SuperCollider, a &lt;b&gt;Float&lt;/b&gt;.  A float is a fraction.  1.1, 2.5, -0.2, 5.0 are all Floats.  They also can add subtract, etc.&lt;/p&gt;

&lt;p&gt;You can do more with numbers than simple math and do loops.  There are many interesting and useful messages one can pass to Integer.  It has a help file worth reading.  So type in the word Integer, starting with a capital-I and press apple-d to look at the help file.  The top of that help file says:&lt;/p&gt;
&lt;p class="p3" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-align: justify; font: normal normal normal 12px/normal 'Helvetica Neue'; font-family: Times; font-size: medium; "&gt;&lt;b&gt;superclass: SimpleNumber&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;superclass&lt;/b&gt; is a vocabulary word.  It refers to a concept called &lt;b&gt;inheritance&lt;/b&gt;.  What this superclass designation means is that Integer &lt;b&gt;is a&lt;/b&gt; SimpleNumber.  When you define classes (recall that a class is the definition for an object), you can define &lt;b&gt;subclasses&lt;/b&gt; of any class.  A subclass is a special type of the original class. It &lt;b&gt;inherits&lt;/b&gt; all the properties of its &lt;b&gt;superclass&lt;/b&gt;.  So the subclass is the child and the superclass is the parent.  We'll come back to this.  But what it means for us is that Integer &lt;b&gt;is a&lt;/b&gt; SimpleNumber.  Which means it understands all the messages that you can pass to a SimpleNumber.  So to find out about what these inherited messages are, we should highlight "SimpleNumber" and hit apple-d  Float and Integer both inherit from SimpleNumber, so take a look at that help file.  Looking at help files and trying stuff out will get you learning the language faster than anything else.  They might not make a lot of sense right now, but if you keep looking, you'll get context and be able to figure them out in the future.&lt;/p&gt;


&lt;p&gt;We have one more example that hopefully ties all of this together. Remember our &lt;a href="http://sc3howto.blogspot.com/2010/05/synthdefs.html"&gt;SynthDef from posts past&lt;/a&gt;?  Here's an updated version of it.&lt;/p&gt;

&lt;pre&gt;
(

 SynthDef.new("example2", {arg freq = 440, amp = 0.2;
  Out.ar(0, SinOsc.ar(freq, mul: amp));
 }).load(s);
 
)
&lt;/pre&gt;

&lt;p&gt;We’ve added a field called amp, which indicates the &lt;b&gt;amplitude&lt;/b&gt; or volume at which the sound should play.  In SuperCollider, amplitudes louder than 1 will peak when you listen to them.  Therefore output amplitudes should be between 0, which is silent, and 1, which is as loud as possible.&lt;/p&gt;

&lt;p&gt;Now, lets’ write some code to play &lt;i&gt;N&lt;/i&gt; overtones of 100Hz.  We need to make sure that our overall amplitude doesn’t exceed 1, or else we’ll get peaking.  So, we will divide 1 by the number of overtones into 1 to get the amp value to send to each synth. &lt;/p&gt;


&lt;pre&gt;

(
 var func;
 
 func = { arg repeats = 4;
  repeats.do({ arg index;

    Synth.new("example2", [\freq, (index + 1) * 100,
        \amp, 1 / repeats]);
   });
 };
 func.value;
)
&lt;/pre&gt;

&lt;p&gt;Let's hear what happens when we play this.  All the sounds play at once!  This is because the loop goes through as fast as it can.   We'll cover timing issues very soon.&lt;/p&gt;

&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Whole numbers are Integers
&lt;/li&gt;&lt;li&gt;Real numbers are Floats
&lt;/li&gt;&lt;li&gt;You can indicate order of operations with parenthesis
&lt;/li&gt;&lt;li&gt;Math operations are evaluated innermost to outermost parenthesis and left to right
&lt;/li&gt;&lt;li&gt;Modulus (%) means remainder
&lt;/li&gt;&lt;li&gt;Subclasses inherit the properties of their superclasses - an Integer is a SimpleNumber
&lt;/li&gt;&lt;li&gt;Output amplitudes should be between 0 and 1.
&lt;/li&gt;&lt;/ul&gt;
&lt;h4&gt;Problems&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Translate the following algebraic expressions into proper supercollider syntax, using parenthesis where needed.  Try to make your answers human-readable.
 &lt;ol type="a"&gt;
 &lt;li&gt;3 + 5 * 4
 &lt;/li&gt;&lt;li&gt;7 * 2 + 1
 &lt;/li&gt;&lt;li&gt;6 * (4 + 2)
 &lt;/li&gt;&lt;li&gt;2 * 3 + 4 * 5 + 7 / 2 + 1
 &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;&lt;li&gt;Get yourself familiar with modulus by working out these problems by hand.
 &lt;ol type="a"&gt;
 &lt;li&gt;5 % 4
 &lt;/li&gt;&lt;li&gt;163 % 9
 &lt;/li&gt;&lt;li&gt;20 % 5
 &lt;/li&gt;&lt;li&gt;17 % 6
 &lt;/li&gt;&lt;li&gt;23 % 2
 &lt;/li&gt;&lt;li&gt;3 % 5
 &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;Write a function to print out the first n multiples of 10, starting from 0.  Pass the number of multiples into the function as an argument.  Set the default number to 7.&lt;/p&gt;
&lt;li&gt;&lt;p&gt;Write a function that takes three arguments, &lt;span class="s15" style="font: normal normal normal 12px/normal Courier; "&gt;numberOfOvertones&lt;/span&gt;, &lt;span class="s15" style="font: normal normal normal 12px/normal Courier; "&gt;pitch&lt;/span&gt; and &lt;span class="s15" style="font: normal normal normal 12px/normal Courier; "&gt;amp&lt;/span&gt;.  It should play the number of overtones above &lt;span class="s15" style="font: normal normal normal 12px/normal Courier; "&gt;pitch&lt;/span&gt; specified by the argument &lt;span class="s15" style="font: normal normal normal 12px/normal Courier; "&gt;numberOfOvertones&lt;/span&gt;.  The amplitude of the overtones should be half the amplitude of the fundamentals and the total amplitude for the fundamental plus the overtones should be &lt;span class="s15" style="font: normal normal normal 12px/normal Courier; "&gt;amp&lt;/span&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class="s15" style="font: normal normal normal 12px/normal Courier; "&gt;rand&lt;/span&gt; is a message that you can send to numbers.  &lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;y.rand&lt;/span&gt; returns a number between 0 and y.  Humans are generally able to hear frequencies between 20Hz and 20000Hz (the freq argument for oscillator UGens is in Hz). Write a function that calls your previous function.  You want to play &lt;i&gt;n&lt;/i&gt; random pitches and the first &lt;i&gt;m&lt;/i&gt; overtones of those pitches.  Make sure that the random pitches are all in the audible range.  Pass the number of random pitches and the number of overtones into your new function as arguments.  Set the default number of random pitches to 2 and the default number of overtones to 3.  Make certain that your total amplitude will not peak.  Finally, give the arguments descriptive names.&lt;/p&gt;&lt;/li&gt;
  &lt;ol type="a"&gt;
  &lt;li&gt;Can you figure out a way to make sure that all your pitches, including overtones, are in the audible range?
  &lt;/ol&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-6976317234662622355?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/6976317234662622355/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=6976317234662622355&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/6976317234662622355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/6976317234662622355'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/05/numbers-and-math.html' title='Numbers and Math'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-7067284650440667165</id><published>2010-05-23T10:07:00.009-04:00</published><updated>2010-05-23T14:00:02.334-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='function'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='sc'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Functions</title><content type='html'>&lt;p c=""&gt;After reading the &lt;a href="http://sc3howto.blogspot.com/2010/05/synthdefs.html"&gt;last chapter on SynthDefs&lt;/a&gt; and the one &lt;a href="http://sc3howto.blogspot.com/2009/12/variables.html"&gt;before that on Variables&lt;/a&gt;, Nicole feels like she's got the hang of SuperCollider so she's dropped out of grad school to work for the new SuperCollider start-up company SuperSounds.com.  On her first day, her boss tells her to write a function that prints "hello world" four times.  "No problem," she thinks and goes to look at previous posts.  &lt;b&gt;Functions&lt;/b&gt; are code blocks encased by curly brackets, { } and hello world is easy enough.  So she writes:&lt;/p&gt;
&lt;pre&gt;
(
{

var greet;
greet = "hello world";

greet.postln;
greet.postln;
greet.postln;
greet.postln;
}
)
&lt;/pre&gt;
&lt;p&gt;Then she thinks, "I should have asked for a signing bonus."  She tries running it, by double clicking to the right of the top parenthesis and hitting enter.  In the Untitled output window it says,&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;&lt;span class="s5" style="font: normal normal normal 10px/normal Helvetica; "&gt;"&lt;/span&gt;&lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;a Function&lt;/span&gt;&lt;span class="s5" style="font: normal normal normal 10px/normal Helvetica; "&gt;"&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;What's the problem?  She declared a variable called&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;&lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;greet&lt;/span&gt;&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;.  &lt;/span&gt;&lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;greet&lt;/span&gt;&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;gets&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;&lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; color: rgb(115, 115, 115); "&gt;"hello world"&lt;/span&gt;&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;.  &lt;/span&gt;Then she sends a&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;&lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;postln&lt;/span&gt;&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;message to&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;&lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;greet&lt;/span&gt;&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;four times.  Every line ends with a semicolon . . .&lt;/p&gt;

&lt;p&gt;Then she realizes that she defined a function, but never told the interpreter to run it.  The interpreter saw a code block surrounded by curly brackets and thought "a function!"  Then it thought, "What do you want me to do with this?  Nothing?  Ok, I'll throw it away."  So Nicole modifies her code:&lt;/p&gt;
&lt;pre&gt;
(
var func;

func = {

var greet;
greet = "hello world";

greet.postln;
greet.postln;
greet.postln;
greet.postln;
};

func.value;
)
&lt;/pre&gt;
&lt;p&gt;And then it works great.&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;  &lt;/span&gt;&lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;value&lt;/span&gt;&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;is a message you can send to functions.  It means, "Run yourself!"&lt;/p&gt;

&lt;p&gt;But then Nicole gets a message from her boss saying, "Sometimes, we need to print out hello world five times and once in a while, three times, and rarely, it needs to print out infinite times."  Nicole considers writing a few different versions of the function and calling them func4, func3, etc, but then remembers about &lt;b&gt;arguments&lt;/b&gt; to functions.&lt;/p&gt;
&lt;pre&gt;
(
var func;
func = { arg repeats;

var greet;
greet = "hello world";

repeats.do ({
greet.postln;
});
};

func.value(4);
)
&lt;/pre&gt;
&lt;p&gt;When she writes her function, she &lt;b&gt;declares&lt;/b&gt; to the interpreter that the function takes one argument.  An argument is a special type of variable that gets set when the function is called.  When she calls the function with&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;&lt;/span&gt;&lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;func.value(4);&lt;/span&gt;, she's assigning a value to the argument&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;&lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;repeats&lt;/span&gt;&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Then, inside the function, she's written,&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;&lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;repeats.do&lt;/span&gt;&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt;. &lt;/span&gt;What is 'do'? It's a message.  It takes a function as an argument.   'do' is a message you can send to &lt;b&gt;integers&lt;/b&gt; that runs the function passed as an argument the number of times as the integer that it was called on.  In this example, repeats is 4, so it runs four times.&lt;/p&gt;

&lt;p&gt;What is an integer?  An integer is a whole number.  -2, -1, 0, 1, 2, 3, 4, etc.  There is a special integer in SuperCollider called inf.  It means infinity.  If we try calling our above function, with&lt;/p&gt;

&lt;pre&gt;func.value(inf);&lt;/pre&gt;

&lt;p&gt;hello world will print out forever, or until we stop the program by hitting apple-. .&lt;/p&gt;

&lt;p&gt;Then Nicole's boss sends another email saying that marketing has some changes.  Every line needs to start out with the line number, starting with zero.  So she makes another change:&lt;/p&gt;
&lt;pre&gt;
(
var func;
func = { arg repeats;

var greet;
greet = "hello world";

repeats.do ({ arg index;
index.post;
" ".post;
greet.postln;
});
};

func.value(4);
)
&lt;/pre&gt;

&lt;p&gt;The function called by do takes an argument.  And that argument is the number of times the loop has been run, starting with 0.  So her output from this program is:&lt;/p&gt;
&lt;pre&gt;
0 hello world
1 hello world
2 hello world
3 hello world
&lt;/pre&gt;
&lt;p&gt;&lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;post&lt;/span&gt; just means print without a new line at the end.  &lt;/p&gt;

&lt;p&gt;Almost every time, she runs this function, the argument is going to be 4.  So she can declare a default argument for the function.&lt;/p&gt;

&lt;pre&gt;
(
var func;
func = { arg repeats = 4;

var greet;
greet = "hello world";

repeats.do ({ arg index;
index.post;
" ".post;
greet.postln;
});
};

func.value;
)
&lt;/pre&gt;

&lt;p&gt;When she calls &lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;func.value&lt;/span&gt;, if there's no argument, then the interpreter will assign 4 to repeats by default.  If she calls it with,&lt;span class="s4" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;&lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;func.value(6&lt;/span&gt;&lt;span class="s8" style="font: normal normal normal 10px/normal 'Helvetica Neue'; "&gt;);&lt;/span&gt;&lt;span class="s9" style="font: normal normal normal 9px/normal 'Helvetica Neue'; "&gt; &lt;/span&gt;then repeats gets 6 instead.  What if she accidentally passes in something besides an Integer into her function?  That depends.  If the object she passes in also understands a do message, then it will use that instead, although the result may differ.  Otherwise, she will get an error.&lt;/p&gt;

&lt;p&gt;What if the function took a lot of arguments with default values?&lt;/p&gt;

&lt;pre&gt;
(
var func;
func = { arg foo = 0, bar = 0, baz = 1, repeats = 4;

var greet;
greet = "hello world";

repeats.do ({ arg index;
index.post;
" ".post;
greet.postln;
});
};

func.value;
)
&lt;/pre&gt;


&lt;p&gt;If she wants to pass in arguments, she does it in the order they're declared in.&lt;/p&gt;
&lt;pre&gt;func.value(0 /* foo */, 0 /* bar */, 1 /* baz */, 3 /* repeats */);&lt;/pre&gt;

&lt;p&gt;However, if we're happy with all the default values, there's a way to tell the function just to assign to a particular variable, out of order:&lt;/p&gt;

&lt;pre&gt;func.value(repeats: 3);&lt;/pre&gt;

&lt;p&gt;You can also just pass in the first N arguments and leave the remainder to the default values:&lt;/p&gt;&lt;p class="p4" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-align: justify; font: normal normal normal 12px/normal Helvetica; min-height: 14px; font-family: Times; "&gt;
&lt;/p&gt;&lt;p class="p5" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-align: justify; font: normal normal normal 10px/normal Monaco; font-family: Times; "&gt;func.value(3, 1);&lt;/p&gt;

&lt;p&gt;And you can combine approaches:&lt;/p&gt;

&lt;pre&gt;func.value(2, repeats: 6);&lt;/pre&gt;

&lt;p&gt;Those slash-stars up there are &lt;b&gt;comments&lt;/b&gt;.  The interpreter ignores everything between a forward slash star and a backslash star.  They can span multiple lines.  You can also create single line comment by using forward slash forward slash:&lt;/p&gt;

&lt;pre&gt;// This is a comment&lt;/pre&gt;

&lt;p&gt;Some times it's useful to &lt;b&gt;comment out&lt;/b&gt; a line of code while &lt;b&gt;debugging&lt;/b&gt;.  So you can skip a particular line in order to figure out where your error is.&lt;/p&gt;

&lt;p&gt;The philosophical point of a function is to &lt;b&gt;return&lt;/b&gt; a value.  Doing things within functions, like printing are technically called &lt;b&gt;side effects&lt;/b&gt;.  What the function returns is the value of its last line.  Let's change that function so it returns the number of times that it printed.&lt;/p&gt;

&lt;pre&gt;(
 var func;
 func = { arg repeats = 4;
 
  var greet;
  greet = "hello world";
  
  repeats.do ({ arg index;
   index.post;
   " ".post;
   greet.postln;
  });
  repeats;
 };
 
 func.value;
)
&lt;/pre&gt;

&lt;p&gt;Now, if we create a new variable called &lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;times&lt;/span&gt;, we can assign the output of the function to it.&lt;/p&gt;

&lt;pre&gt;
(
 var func, times;
 func = { arg repeats = 4;
 
  var greet;
  greet = "hello world";
  
  repeats.do ({ arg index;
   index.post;
   " ".post;
   greet.postln;
  });
  repeats;
 };
 
 times = func.value;
 times.postln;
)
&lt;/pre&gt;

&lt;p&gt;Prints out hello world with the line number like before, and then at the bottom, prints out a 4.  Or we could change those last two lines from&lt;/p&gt;

&lt;pre&gt;
 times = func.value;
 times.postln;
&lt;/pre&gt;

&lt;p&gt; to&lt;/p&gt;

&lt;pre&gt;func.value.postln;&lt;/pre&gt;

&lt;p&gt;and the interpreter will read that statement left to right, first finding the value of the function and then sending that value a postln message.&lt;/p&gt;

&lt;p&gt;Ok, what happens if we take the above function and write some code below it that looks like this:&lt;/p&gt;

&lt;pre&gt;
(
 var func, times;
 func = { arg repeats = 4;
 
  var greet;
  greet = "hello world";
  
  repeats.do ({ arg index;
   index.post;
   " ".post;
   greet.postln;
  });
  repeats;
 };
 greet.postln;
)
&lt;/pre&gt;

&lt;p&gt;We get errors.&lt;/p&gt;

&lt;pre&gt;
• ERROR: Variable 'greet' not defined.
 in file 'selected text'
 line 14 char 6 :
 greet•.postln;
&lt;/pre&gt;


&lt;p&gt;This is because of something called &lt;b&gt;scope&lt;/b&gt;.  Variables only exist in the code block in which they are declared.  Code blocks are zero or more lines of code surrounded by curly braces or highlighted by the user.  This means that variables and arguments declared inside a function only exist inside that function.  &lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;index&lt;/span&gt; does not exist outside of its function, which is the function passed as an argument to &lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;repeats.do&lt;/span&gt;.  &lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;greet&lt;/span&gt; does not exist outside of it's function.  None of these variables exist of the text we highlight.&lt;/p&gt;

&lt;p&gt;Variables in outer blocks are accessible within inner blocks.  For example,&lt;/p&gt;

&lt;pre&gt;
(
 var func, times;
 times = 0;
 func = { arg repeats = 4;
 
  var greet;
  greet = "hello world";
  times.postln;
  
  repeats.do ({ arg index;
   index.post;
   " ".post;
   greet.postln;
  });
  repeats;
 };
)
&lt;/pre&gt;


&lt;p &gt;Is fine because &lt;span class="s6" style="font: normal normal normal 10px/normal Monaco; "&gt;times&lt;/span&gt; exists in the outer most block.  In the same way, we can use greet inside our repeats.do function.&lt;/p&gt;

&lt;p&gt;There are, however, a few variables that can be used everywhere.  The interpreter gives us 26 &lt;b&gt;global variables&lt;/b&gt;.  Their scope is all of SuperCollider.  They are single letter variable names, a, b, c, d, e, f, etc.  You don't need to declare them and they keep their value until you change it again, even in different code blocks.  This is why the variable 's' refers to the Server.  You can change that, but you might not want to. &lt;/p&gt;

&lt;p&gt;If you have any questions about functions, you can look at the &lt;span class="s11" style="font: normal normal normal 9px/normal Monaco; "&gt;Function&lt;/span&gt; help file for more information.  The most useful message you can send to a function is value, but there are a few others, which you can read about. You may not understand everything you see in the helpfiles, but it’s good to keep reading them.&lt;/p&gt;

&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Blocks of code surrounded by curly brackets are functions.
&lt;/li&gt;&lt;li&gt;Functions do not run unless you tell the interpreter to run them, which you can do with the message "value".
&lt;/li&gt;&lt;li&gt;You can declare arguments to function. That argument can have a default value.
&lt;/li&gt;&lt;li&gt;An integer is a whole number
&lt;/li&gt;&lt;li&gt;If you pass the message "do" to an integer with a function as an argument, that function will run as a loop.
&lt;/li&gt;&lt;li&gt;Functions can have many arguments. You must pass arguments in the correct order or list them by name.
&lt;/li&gt;&lt;li&gt;Comments are either surrounded by /* and */ or are on a single line, preceded by //
&lt;/li&gt;&lt;li&gt;All functions return a value, which is the result of the last line of code in the function
&lt;/li&gt;&lt;li&gt;Variable names are only valid in the block of code in which they were declared, and within blocks of code contained within that block.
&lt;/li&gt;&lt;li&gt;There are 26 global variables, each a single lowercase letter a-z.
&lt;/li&gt;&lt;/ul&gt;
&lt;h4&gt;Problems&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Write a function with nested do-loops, so that there is one loop inside the other.
&lt;/li&gt;&lt;li&gt;If x and y are intergers and the inner loop is x.do and the outer loop is y.do, how many total times with the inner loop be run?
&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-7067284650440667165?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/7067284650440667165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=7067284650440667165&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/7067284650440667165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/7067284650440667165'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/05/functions.html' title='Functions'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-6901315274496749760</id><published>2010-05-22T17:06:00.006-04:00</published><updated>2011-05-16T13:12:16.935-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='synthdef'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>SynthDefs</title><content type='html'>&lt;p&gt;&lt;a href="http://sc3howto.blogspot.com/2009/12/variables.html"&gt;Last time&lt;/a&gt;, I promised we would cover sound-making.  First, make sure to boot the localhost server.  The localhost server is one of the two small gray boxes at the bottom left of your screen.  Press the “Boot” button.  When it's booted, the window will say "running" in it and the  "Boot" button will turn green and change to say "Quit." &lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_2MW4T3cBz8I/S_hIqNjEplI/AAAAAAAAANs/-35Tlj5WvWE/s1600/server.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 288px; height: 120px;" src="http://3.bp.blogspot.com/_2MW4T3cBz8I/S_hIqNjEplI/AAAAAAAAANs/-35Tlj5WvWE/s400/server.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5474205237097309778" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, select this code and press enter (not return!).  You can select it by double-clicking to the right of the open parenthesis.&lt;/p&gt;

&lt;pre&gt;
 (

  var syn, sound;

  syn = SynthDef.new("example1", {
   Out.ar(0, SinOsc.ar(440));
  });
 
  syn.load(s);

  sound = Synth.new("example1");
 )
&lt;/pre&gt;
&lt;p&gt;When you want to stop the program, press apple-period.&lt;/p&gt;
&lt;p&gt;What's going on here?  Our program first declares a variable, and then it defines a SynthDef and loads it on the server, then creates a Synth object that plays the sound.  This is a complicated example, but I wanted to get you making sounds as soon as possible.  Let's look at the example line by line.&lt;/p&gt;
&lt;p&gt;The first line is &lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; "&gt;var syn, sound;&lt;/span&gt; We are declaring two variables.  One is called syn and the other is called sound.&lt;/p&gt;
&lt;p&gt;The next line, translated into English, means "I want to create a new &lt;b&gt;SynthDef&lt;/b&gt; called 'example1' and store it in the variable syn."  Whoa, what's a SynthDef?  The SynthDef help file told me that a SynthDef is a "definition of a synth architecture."  I got to the help file by highlighting the word SynthDef and pressing apple-d.  When I see a term like that, which I don't understand, I can always get help by highlighting it and typing apple-d.&lt;/p&gt;
&lt;p&gt;Recall that SuperCollider is not just one program; it is two.  One part of the program is the interpreter, which is what we've been talking about so far.  The other part of the program is &lt;b&gt;audio server&lt;/b&gt;, which is what actually makes the sound. It does not know anything but what it needs to know.  This makes it run much faster and more efficiently.  You can tell it to make certain kinds of sounds, but in order to run quickly, it wants to know what kinds of sounds you want before you actually make them.  You write a description of what you want the server to do.  This description, or definition, is called a SynthDef.&lt;/p&gt;
&lt;p&gt;When we run SynthDef.new, we get back a new SynthDef, which we're stroing in the variable named syn. Inside the parenthesis are some &lt;b&gt;arguments&lt;/b&gt;.  &lt;span class="s13" style="font: normal normal normal 10px/normal Monaco; color: rgb(17, 0, 207); "&gt;SynthDef&lt;/span&gt;&lt;span class="s14" style="font: normal normal normal 9px/normal Monaco; color: rgb(17, 0, 207); "&gt; &lt;/span&gt;is the class.&lt;span class="s3" style="font: normal normal normal 12px/normal Helvetica; "&gt;  &lt;/span&gt;&lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; "&gt;new&lt;/span&gt;&lt;span class="s3" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;is the message.  And&lt;span class="s3" style="font: normal normal normal 12px/normal Helvetica; "&gt; &lt;/span&gt;&lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; "&gt;"example1"&lt;/span&gt; and the stuff in between the curly brackets are the two arguments.  &lt;/p&gt;
&lt;p&gt;The stuff in the curly brackets is telling the SynthDef what to play. Things between curly brackets {} are called &lt;b&gt;functions&lt;/b&gt;.  A function is a special type of object that is made up of a code block that you can run.  We'll come back to this later.&lt;/p&gt;
&lt;p&gt;Out is a &lt;b&gt;UGen&lt;/b&gt;.  The help file for UGens says, "A UGen or &lt;b&gt;unit generator &lt;/b&gt;is an object for generating or processing audio or control signals." UGens exist in SynthDefs.  They are what make up a SynthDef.  Out is a UGen that writes a signal to a &lt;b&gt;bus&lt;/b&gt;, which, in this case, sends it's output to the left channel.  .ar is a type of constructor.  So Out.ar creates a new instance of a an Out UGen running at the &lt;b&gt;audio rate&lt;/b&gt;.  ar stands for "audio rate" and is a common constructor name for UGens.  &lt;/p&gt;
&lt;p&gt;Looking at the arguments to Out.ar, 0 means left channel.  If that were a 1, it would mean right channel.  And the next thing is what gets sent out, which is a sine tone generator.  The argument to SinOsc.ar, 440, is the frequency to play.  So SinOsc.ar(440) creates a sine wave at 440 Hz.  Out.ar takes that sine wave and sends it out to the left channel, which is channel 0.&lt;/p&gt;
&lt;p&gt;The next line, is a closing curly bracket, a close paren and a semicolon.  It's the end of the function, the end of the SynthDef and the end of a statement.  We've created a new SynthDef that includes in it a function describing what the SynthDef should do when it gets instantiated.&lt;/p&gt;
&lt;p&gt;The next line says, take that SynthDef and load it on the server.  We're sending a message to syn, saying load.  The argument, s, is the server to send it to.  In SuperCollider, a lowercase s by itself refers to the audio server.&lt;/p&gt;
&lt;p&gt;The next line asks to create a new Synth. The interpreter sends a message to the server, saying, "Hey, could you make a synth that plays the SynthDef called 'example1'?"  The server looks and says, "oh yeah, I have a SynthDef called that" and makes a new instance of a Synth, which is running the function that we defined.&lt;/p&gt;
&lt;p&gt;We get a new Synth object back from this and store it in "sound."&lt;/p&gt;
&lt;p&gt;Let's say we don't want to play an A.  Let's say we want to play an E.  We can change 440 to 660.&lt;/p&gt;
&lt;pre&gt;

(
 var sound;
 SynthDef.new("example1a", {
 
  Out.ar(0, SinOsc.ar(660));
 }).load(s);
 
 sound = Synth.new("example1a");
)
&lt;/pre&gt;
&lt;p&gt;You'll note that we have one fewer variable in that example. Messages are evaluated left to right.  So the interpreter first figures out the result of &lt;span class="s13" style="font: normal normal normal 10px/normal Monaco; color: rgb(17, 0, 207); "&gt;SynthDef&lt;/span&gt;&lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; "&gt;.new(&lt;/span&gt;&lt;span class="s11" style="font: normal normal normal 10px/normal Monaco; color: rgb(115, 115, 115); "&gt;"example1a"&lt;/span&gt;&lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; "&gt; ... ). &lt;/span&gt;Then, it takes that new SynthDef and sends it the message &lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; "&gt;load. &lt;/span&gt;  We can keep adding on messages at the end as long as we'd like:&lt;/p&gt;
&lt;p&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt; &lt;/span&gt;object.message1.message2(arg1).message3.message4(arg2)&lt;/p&gt;
&lt;p&gt;Of course, this gets silly and difficult to read after a while, but it's legal.&lt;/p&gt;
&lt;p&gt;When we're writing a piece, we don't want to have to write a new SynthDef for every note that we're going to play.  We can create our own argument, which will tell the SynthDef what frequency to play.&lt;/p&gt;
&lt;pre&gt;

(

 var sound;

 SynthDef.new("example1", { arg freq;
   Out.ar(0, SinOsc.ar(freq));
  }).load(s);

  sound = Synth.new("example1", [\freq, 440]);
)
&lt;/pre&gt;
&lt;p &gt;We call that argument “freq.”  An argument is a special kind of variable.  You declare then at the top of a code block by using the reserved word “arg.”  So the &lt;span class="s13" style="font: normal normal normal 10px/normal Monaco; color: rgb(17, 0, 207); "&gt;arg&lt;/span&gt;&lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; "&gt; freq;&lt;/span&gt;&lt;span class="s6" style="font: normal normal normal 9px/normal 'Helvetica Neue'; "&gt; &lt;/span&gt;part of &lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; "&gt;syn = &lt;/span&gt;&lt;span class="s13" style="font: normal normal normal 10px/normal Monaco; color: rgb(17, 0, 207); "&gt;SynthDef&lt;/span&gt;&lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; "&gt;.new(&lt;/span&gt;&lt;span class="s11" style="font: normal normal normal 10px/normal Monaco; color: rgb(115, 115, 115); "&gt;"example1"&lt;/span&gt;&lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; "&gt;, { &lt;/span&gt;&lt;span class="s13" style="font: normal normal normal 10px/normal Monaco; color: rgb(17, 0, 207); "&gt;arg&lt;/span&gt;&lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; "&gt; freq;&lt;/span&gt;tells SuperCollider that our SynthDef function takes a single argument called freq.  We can then use freq like we would any other variable.  Here, we’re passing to SinOsc.ar, to use for the frequency.&lt;/p&gt;
&lt;p&gt;Passing variables to Synths is a bit different than normal variable passing.  The interpreter has to communicate with the audio server.  They use a protocol called OSC.  The Synth object will handle the OSC for you, but the server does not know which argument you’re trying to pass a value to unless you specifically tell it.  So Synth.new takes an optional second argument, which is an &lt;b&gt;Array&lt;/b&gt;.  An array is a list separated by commas and surrounded by square brackets.  When you are passing arguments to the server via a synth, the array must be made up of pairs.  The first item in a pair is a &lt;b&gt;symbol&lt;/b&gt; or a string and the second is a value.  The symbol or string must match the name of the argument.  So for an argument called freq, we use the symbol \freq or the string “freq”.  If we had an argument called amp, we would use the symbol \amp or the string "amp".  A symbol starts with a forward slash: ‘\’.  So to pass a value of 440 to the argument freq, our array contains [\freq, 440].  If we had two arguments, one freq and the other amp, we could pass values to freq and amp with an array that looks like [\freq, 440, \amp,0.2]. The array is made up of pairs, to the 440 is paired with freq and 0.2 is paired with amp.  The symbols or strings must match the names of the arguments taken by the SynthDef function. &lt;/p&gt;
&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;You must boot the server in order to play sounds.
&lt;li&gt;There is a variable called "s" which always refers to the server
&lt;li&gt;The sounds you want to play must be defined on the server before you play them. They are defined in SynthDefs.
&lt;li&gt;Get help by highlighting a class name with the mouse and typing apple-d
&lt;li&gt;Blocks of code surrounded by curly braces are functions
&lt;li&gt;You play SynthDefs by using Synth
&lt;li&gt;You can declare arguments to a function with the word arg: &lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; "&gt;{ arg agrument1, argument2;&lt;/span&gt;
&lt;li&gt;Comma-separated lists surrounded by square brackets are Arrays
&lt;li&gt;Synths use arrays to pass arguments: &lt;span class="s7" style="font: normal normal normal 10px/normal Monaco; "&gt;Synth.new(name, [\symbol, argument])&lt;/span&gt;
&lt;/ul&gt;
&lt;h4&gt;Problems&lt;/h4&gt;
&lt;p&gt;When you are writing code, if you want to syntax colorize it, so that reserved words are blue, strings are grey, symbols are green, and so on, you can find that in the Format menu or just type apple-‘ (apple-single quote).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write your own version of “hello world.”
&lt;li&gt;Write your own SynthDefs, using some of the oscillator UGens.  To find a list of them, highlight the word “UGens” and type apple-d.  Some oscillators to try are Saw and Pulse.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-6901315274496749760?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/6901315274496749760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=6901315274496749760&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/6901315274496749760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/6901315274496749760'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2010/05/synthdefs.html' title='SynthDefs'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_2MW4T3cBz8I/S_hIqNjEplI/AAAAAAAAANs/-35Tlj5WvWE/s72-c/server.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-7153796415930839309</id><published>2009-12-11T19:46:00.003-05:00</published><updated>2010-05-17T14:38:45.861-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='sc'/><category scheme='http://www.blogger.com/atom/ns#' term='variables'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Variables</title><content type='html'>&lt;p&gt;In previous posts, like, &lt;a href="http://sc3howto.blogspot.com/2005/02/object-oriented-programming.html"&gt;Object Oriented Programming&lt;/a&gt;, we talked a bit about objects and variables, but in an abstract way.  Now, let's get more specific.&lt;/p&gt;
&lt;p&gt;A variable is a name for an object.  For example, let's think of a person, Nicole, as an object. Now, Nicole, herself is an object, but the word "Nicole" is a name that refers to Nicole the person. Similarly, we can give names to our objects. These names are called &lt;b&gt;variables&lt;/b&gt;. Let's see an example:&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
(
  var greeting; 
  greeting = "hello world";
  greeting.postln;
)
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;To run this code, copy it into a new window in Supercollider and then double click just inside the opening parenthesis to highlight all of it.  Then, click the enter key.  (Not the return key.)  (see also: &lt;a href="http://www.youtube.com/watch?v=Q7OIWcLvmmE"&gt;this video&lt;/a&gt; for help.)  If you look in the Post window, it should say, "hello world."&lt;/p&gt;
&lt;p&gt;What's going on there? The first word, "&lt;span style="font-family: courier new;"&gt;var&lt;/span&gt;," is short for variable. A variable is a storage location. It's a place to store a piece of data. The contents of data stored may vary, which is why it's called a variable. The second word "&lt;span style="font-family: courier new;"&gt;greeting&lt;/span&gt;" is a name. It is the name of the variables. Here we are &lt;b&gt;declaring&lt;/b&gt; to the &lt;b&gt;interpreter&lt;/b&gt; that we will have a variable named "&lt;span style="font-family: courier new;"&gt;greeting&lt;/span&gt;." The interpreter is the part of SuperCollider that reads and runs our programs. So, when the interpreter is reading our program and sees the word "&lt;span style="font-family: courier new;"&gt;greeting&lt;/span&gt;" it will know that greeting is a variable that we've declared. Otherwise, it wouldn't know what we were talking about.&lt;/p&gt;
&lt;p&gt;All variable names in SuperCollider must start with a lowercase letter and cannot be a &lt;b&gt;reserved word&lt;/b&gt;. You cannot have a variable called "var" because var already has a special meaning to the interpreter.&lt;/p&gt;
&lt;p&gt;Next we are &lt;b&gt;assigning&lt;/b&gt; a value to the variable. &lt;span style="font-family: courier new;"&gt;greeting&lt;/span&gt; gets &lt;span style="font-family: courier new;"&gt;"hello world"&lt;/span&gt;. The variable is on the left of the equal sign. It must always be on the left. There can only ever be one thing on the left of an equals sign. That sign is saying, 'hey, take whatever is on the right of this equals sign and store it under the variable name on the left.'&lt;/p&gt;
&lt;p&gt;In the last line, we're sending a &lt;span style="font-family: courier new;"&gt;postln message&lt;/span&gt; to the variable. The SuperCollider interpreter sends that &lt;b&gt;message&lt;/b&gt; to &lt;span style="font-family: courier new;"&gt;greeting&lt;/span&gt;. &lt;span style="font-family: courier new;"&gt;greeting&lt;/span&gt; is a String. Strings print themselves with the postln message. So because &lt;span style="font-family: courier new;"&gt;greeting&lt;/span&gt; is a
String, the contents of &lt;span style="font-family: courier new;"&gt;greeting&lt;/span&gt;, &lt;span style="font-family: courier new;"&gt;"hello world"&lt;/span&gt;, print out. &lt;/p&gt;
&lt;p&gt;On the left is the variable name, an object. Then is a period. Then is the name of the message. There are a few different coding styles allowable in SuperCollider, but we're going to focus on receiver notation because it is common across many programming languages.  That is:
&lt;pre&gt;
object.message;
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Notice the semi-colons. In Supercollider, all instructions must be separated with a semi-colon. A single instruction can span many lines, so the interpretter needs the semi colon to know when one thing is done and another is starting. Later on, when you're trying to figure out why some program isn't working, you're going to discover a missing semicolon. To be on the safe side, it's good practice to put one at the end of every instruction, as in the example.&lt;/p&gt;
&lt;h4&gt;Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Variables are named bits of memory which can store objects.&lt;/li&gt;
&lt;li&gt;Variables must be declared. Their names must start with lowercase letters&lt;/li&gt;
&lt;li&gt;You can assign data to a variable by putting it alone on the left side of an equals sign.&lt;/li&gt;
&lt;li&gt;We send messages to objects with the notation &lt;span style="font-family: courier new;"&gt;object.message&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Lines of code must be separated with semicolons&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The next chapter will make sounds.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-7153796415930839309?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/7153796415930839309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=7153796415930839309&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/7153796415930839309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/7153796415930839309'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2009/12/variables.html' title='Variables'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-3617856863426831556</id><published>2008-04-07T17:22:00.004-04:00</published><updated>2010-05-21T18:17:29.868-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conductor'/><category scheme='http://www.blogger.com/atom/ns#' term='example'/><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='gui'/><category scheme='http://www.blogger.com/atom/ns#' term='sc'/><category scheme='http://www.blogger.com/atom/ns#' term='SuperCollider'/><title type='text'>Conductors: a fast GUI</title><content type='html'>&lt;p&gt;I usually use Conductors because they're quick and dirty and can very easily be used to control a synth or a pbind.  This class is from Ron Kuivila and it's included in the Wesleyan build or else available as quark. (See the Quarks helpfile for more on how to get it.)&lt;/p&gt;


&lt;p&gt;Here's a quick example:&lt;/p&gt;

&lt;p&gt;
&lt;span style="font-family: courier new;"&gt;SynthDef("sin", {arg freq = 440;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;Out.ar(0, SinOsc.ar(freq))&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;}).store;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;Conductor.make({arg this_conductor, freq;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;freq.spec_(\freq);&lt;/span&gt;&lt;br /&gt;
   &amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;this_conductor.synth_(&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;( instrument: "sin" ),&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[freq: freq]&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;}).show&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;The constructor method for a conductor is make, which takes a function for an argument.  The first argument to the function refers to the freshly-created conductor.  Then, for the rest of the arguments, list things you want to control.  So I put here "freq".  freq is initalised as something called a CV.&lt;/p&gt;

&lt;p&gt;CVs are very handy for scaling things.  They have a low value, a high value, an initial value and can be linear or exponential.  So a fader with a CV can slide back and forth and give you meaningful numbers in the range that you want.  There's a bunch of pre-defined CV settings that can be useful for certain applications.  Like here, the freq CV is being set to a pre-defined specification for audible frequencies.&lt;/p&gt;

&lt;p&gt;Next, we're telling the conductor that it should be controlling a synth.&lt;/p&gt;

&lt;p&gt;The first argument here is a list. We tell it which synth to use.  We could also say which server to send it to and it's group and things like that.&lt;/p&gt;

&lt;p&gt;The second argument is an array of name: value pairs.  &lt;span style="font-family: courier new;"&gt;[name_of_synth_arg: name_of_cv, name_of_another_synth_arg: name_of_another_CV]&lt;/span&gt; This usage here ties the CV freq to the synth argument freq.&lt;/p&gt;

&lt;p&gt;Finally we show the whole thing and you get a box with some buttons on it and a slider.  The syntax of of the Conductor is slightly obtuse, but, as you can see from the box that popped up, you get a lot of stuff for free.  If you click on the &amp;gt; button, it will start playing.  Wiggle the fader.  [] stops it.&lt;/p&gt;

&lt;p&gt;We can modify the above example a little bit to see this maybe a bit clearer:&lt;/p&gt;

&lt;p&gt;&lt;span style="font-family: courier new;"&gt;SynthDef("sin2", {arg freq1 = 440, freq2 = 10;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;Out.ar(0, SinOsc.ar(freq1, SinOsc.ar(freq2)))&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;}).store;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;Conductor.make({arg this_conductor, freq, pm;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;freq.spec_(\freq);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;pm.spec_(\widefreq);&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;   
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;this_conductor.synth_(&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;( instrument: "sin2" ),&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[freq1: freq, freq2: pm]&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;)&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;}).show;&lt;/span&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Ok, so the newer synth does some silly phase modulation.&lt;/p&gt;

&lt;p&gt;The conductor now has two CVs called freq and pm.  We set pm to have the pre-definied spec for frequencies that include the sub-audible range.  Other such specs include:  &lt;span style="font-family: courier new;"&gt;unipolar, bipolar, freq, lofreq, midfreq, widefreq, phase, rq, audiobus, controlbus, midi, midinote, midivelocity,&lt;/span&gt;&lt;span style="font-family: courier new;"&gt; db, amp, boostcut, pan, detune, rate, beats, delay&lt;/span&gt;  If you want to see what those other ones are like, you can create a bunch of Conductors with them and wiggle the sliders around and see what you get for values.&lt;/p&gt;

&lt;p&gt;And finally, if you look at the array to attach the synth, it's a bit clearer that freq1 belongs to the synth and freq comes from the conductor.  freq2 belongs to the synth and pm comes from the conductor.  And when you show it, you get two sliders.&lt;/p&gt;

&lt;p&gt;Using a Conductor with a pattern is really straight forward:&lt;/p&gt;

&lt;p&gt;
&lt;span style="font-family: courier new;"&gt;Conductor.make({arg this_conductor, freq, amp;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;freq.spec_(\freq);&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;amp.spec_(\amp);&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;   
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;this_conductor.pattern_(Pbind(\freq, freq, \amp, amp));&lt;/span&gt;
&lt;span style="font-family: courier new;"&gt;}).show&lt;/span&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;When you play it, you'll have to turn up the amp.  And you can put anything you want in that Pbind.  It's just like any other Pbind. Anything you want on a gui, you can put in the argument for the Conductor.  You can also do things like:&lt;/p&gt;

&lt;p&gt;
&lt;span style="font-family: courier new;"&gt;Conductor.make({arg this_conductor, freq, amp;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;freq.sp(3, 0, 5, 1, 'linear');&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;amp.spec_(\amp);&lt;/span&gt;&lt;br /&gt;
   &amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;this_conductor.pattern_(&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;Pbind(&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\amp, amp,&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\freq, Pfunc({[100, 250, 374, 580, 687, 910].at(freq.value)})&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;));&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;}).show&lt;/span&gt;&lt;br /&gt;
&lt;/p&gt;

&lt;p&gt;Here, the freq can be integers between 0 and 5.  In the Pbind, a Pfunc uses the value of the freq slider as the index for an array.  You need to do a &lt;span style="font-family: courier new;"&gt;whatver_cv.value&lt;/span&gt; to get the value that the slider is giving you.  You can also set the value with &lt;span style="font-family: courier new;"&gt;whatever_cv.value_&lt;/span&gt;, which can make your sliders wiggle themselves around.  If you want to wiggle them with a joystick or something, you might use &lt;span style="font-family: courier new;"&gt;whatever_cv.input_&lt;/span&gt; and pass in a value between 0-1.  This helps with the scaling.&lt;/p&gt;

&lt;p&gt;So, for example, here's a change to the amp:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family: courier new;"&gt;Conductor.make({arg this_conductor, freq, amp;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;freq.sp(3, 0, 5, 1, 'linear');&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;amp.spec_(\amp);&lt;/span&gt;&lt;br /&gt;
   &amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;amp.value_(0.2);&lt;/span&gt;
   &amp;nbsp;&amp;nbsp;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;this_conductor.pattern_(&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Pbind(&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\amp, amp,&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;\freq, Pfunc({[100, 250, 374, 580, 687, 910].at(freq.value)})&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;));&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: courier new;"&gt;}).show&lt;/span&gt;&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-3617856863426831556?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/3617856863426831556/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=3617856863426831556&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/3617856863426831556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/3617856863426831556'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2008/04/conductors-fast-gui.html' title='Conductors: a fast GUI'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-114460240021485665</id><published>2006-04-09T12:52:00.000-04:00</published><updated>2006-05-09T11:37:26.040-04:00</updated><title type='text'>Fast Pbind-based Introduction for Experienced Programmers</title><content type='html'>&lt;p&gt;You may wish to quickly scan the &lt;a href="http://sc3howto.blogspot.com/2005/02/introduction.html"&gt;first post&lt;/a&gt; to find a bit of background&lt;/p&gt;
&lt;h3&gt;Online resources&lt;/h3&gt;
&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://supercollider.wesleyan.edu/"&gt;http://supercollider.wesleyan.edu/&lt;/a&gt;
 &lt;li&gt;&lt;a href="http://swiki.hfbk-hamburg.de:8888/MusicTechnology/6"&gt;http://swiki.hfbk-hamburg.de:8888/MusicTechnology/6&lt;/a&gt;
 &lt;li&gt;&lt;a href="http://www.audiosynth.com/"&gt;http://www.audiosynth.com/&lt;/a&gt;
&lt;/ul&gt;

&lt;h3&gt;The program&lt;/h3&gt;
&lt;a href="http://photos1.blogger.com/blogger/6345/108/1600/desktop.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/6345/108/200/desktop.jpg" border="0" alt="starting SuperCollider" /&gt;&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Once the program is downloaded and running, it should look like the image at left.
&lt;li&gt;Boot a server by clicking on the boot button of the localhost server or the internal server
&lt;li&gt;Put your code in a new window
 &lt;li&gt;run code by selecting it and hitting enter (not return)
 &lt;li&gt;stop code by hitting command-.
 &lt;li&gt;get help by selecting the name of a class (or help topic) and typing command-?
 &lt;li&gt;if you enclose code in parenthesis, you can click on the parenthesis to select a block
 &lt;li&gt;SuperCollider is a dialect of SmallTalk
 &lt;li&gt;the server is a different process than the language.  they communicate via a protocol called OSC
&lt;/ul&gt;
 
&lt;h3&gt;Code examples&lt;/h3&gt;
&lt;h4&gt;First Program&lt;/h4&gt;
 &lt;pre&gt;
 Pbind.new.play
&lt;/pre&gt;
&lt;ul&gt;
  &lt;li&gt;Pbind is a class.  All class names start with capital letters and nothing else can.  
  &lt;li&gt;new is a message, which, by convention, causes a new instance of the class (an object) to be returned.  
  &lt;li&gt;play is a message passed to the new object.
  &lt;li&gt;&lt;pre&gt;object.message&lt;/pre&gt; is the most common syntax in supercollider and is called receiver notation.  Other notations are allowed, including normal small talk notation and something called functional notation, which we'll talk about later
  &lt;li&gt;everything in Supercollider is an object
  &lt;li&gt;Pbind is part of a set of related classes called patterns
&lt;/ul&gt;
&lt;h4&gt;Symbols and Patterns&lt;/h4&gt; 
&lt;pre&gt;
 Pbind(\dur, 0.5, \freq, 660).play
&lt;/pre&gt;
&lt;ul&gt; 
  &lt;li&gt;If you don't specify a message to a class, but pass it arguments, it's assumed you're calling new (this is confusing, but you'll see it all the time in help files)
  &lt;li&gt;Pbinds work by creating a type of object called an event.  Events are kind of like the makenote in MAX.  It has a bunch of possible parameters and handles a bunch of stuff for you, like computing midinote number based on a supplied frequency or vice versa.  It also handles timings by keeping track of server latency (the delay between asking for something to happen and it happening) and sending OSC messages ahead of time
  &lt;li&gt;Pbinds take as arguments a comma separated list of symbols (which correspond to parameter names) and Patterns (or constant values)
&lt;/ul&gt;  
 &lt;h4&gt;Pfunc&lt;/h4&gt;
 &lt;pre&gt;   
 (
  Pbind(
   \dur, 0.4,
   \note, Pfunc({
   
      12.rand
     })
  ).play
 )
&lt;/pre&gt; 
&lt;ul&gt;
  &lt;li&gt;Pfunc starts with a capital letter, therefore, it must name a class
  &lt;li&gt;Pfunc is a class, since it's got an argument, there's a constructor being called
  &lt;li&gt;it takes a function as an argument.  functions are declared by code surrounded by curly braces
  &lt;li&gt;the last line in a function is the value it returns
  &lt;li&gt;Pfunc is a subclass of Pattern
  &lt;li&gt;Pbind calls the Pfunc for every event and uses the return value to specify what value goes with \note
  &lt;li&gt;rand is a message sent to 12, which is an object and an instance of Integer, which is a subclass of SimpleNumber.  objects understand all the messages that their class and superclasses understand.  When an instance of SimpleNumber (or one of it's subclasses) receives a message of rand, it returns a number between 0 and the object
&lt;/ul&gt;  
&lt;h4&gt;Declaring Variables and if&lt;/h4&gt;
&lt;pre&gt;
 (
  Pbind(
   \dur, 0.4,
   \note, Pfunc({
      var rand_num;
      
      rand_num = 13.rand;
      (rand_num &amp;gt;= 12). if ({
       rand_num = \rest;
      });
      
      rand_num;
     })
  ).play
 )
&lt;/pre&gt; 
&lt;ul&gt;  
  &lt;li&gt;variables are named bits of memory which can store objects.  they must be declared.  their name must start with a lowercase letter.  They only exist within their code block.  rand_num only exists in it's Pfunc
  &lt;li&gt;SuperCollider gives you 26 variables wich it keeps track of all the time.  They are named a - z.  s holds a pointer to the server
  &lt;li&gt;= is an assignment so that rand_num holds the result of 13.rand
  &lt;li&gt;statements have to be separated by semicolons
  &lt;li&gt;(rand_num &gt;= 12) is an expression which is either true of false.  Therefore, it is a type of object called a Boolean.  Booleans can take a message of if.  If the boolean is true, it will evaluate the function passed as the first argument to if.  If it's false, it will evaluate the second function, which is optional.  If you don't tell it about second function, it does nothing.
  &lt;li&gt;\rest tells the Pbind to rest
  &lt;li&gt;the function returns rand_num, which has in it either an integer or \rest
  &lt;li&gt;you sometimes also see if with functional notation, which is message(object, arguments) so that would look like &lt;pre&gt;if((rand_num &gt;= 12), { rand_num = \rest });&lt;/pre&gt;  This is not for any particular reason except that visually, it looks more like C or C++
&lt;/ul&gt;
&lt;h4&gt;Prout&lt;/h4&gt; 
&lt;pre&gt;  
 ( 
  Pbind(
   \dur,  0.4,
   \note,  Prout({
      var bangs, note;
      
      bangs = (4 * 3 * 7 * 2) -1;
      // do full loop twice
     
      bangs.do({ arg index;
    
       note = 10;  
      
       (index % 4 == 0).if ({
        note = note + 5;
       });
       (index % 3 == 0).if ({
        note = note - 3;
       });
       (index % 7 == 0).if ({
        note = note + 6;
       });
      
       note.yield;
      });
    })
  ).play;

  // code stolen from &lt;a href="http://www.perl.com/lpt/a/2004/08/31/livecode.html"&gt;http://www.perl.com/lpt/a/2004/08/31/livecode.html&lt;/a&gt;
 )
&lt;/pre&gt;
&lt;ul&gt; 
  &lt;li&gt;Prouts are like Pfuncs, except they treat their function as a Routine.  A Routine is a kind of function which can pause and restart.
  &lt;li&gt;math operations go form left to right, like a cheap calculator.  + and - have the same precedence as * and /, so use parenthesis to specify order of operations
  &lt;li&gt;// indicates a comment as does /* comment is in between these */
  &lt;li&gt;giving the message do to an object which is an instance of SimpleNumber causes the function it gets as an argument to be evaluated object+1 times.  When it evaluates the function, it gives it an argument the number of iteration it's on, from 0 - object
  &lt;li&gt;% is modulus, which is the remainder when doing division: 13 % 5 = 3 because 13 = (5 * 2) + 3
&lt;li&gt;== tests for equivalency
  &lt;li&gt;yield is a message which you can pass to any object within a Routine.  That object is then returned from the routine, so in this case, Pbind can use it for a note number.  When the routine is restarted, it picks up from where it left off.
  &lt;li&gt;When the Prout eventually runs out, after going through the loop bangs times, it will return nil, which will cause the Pbind to stop playing
&lt;/ul&gt; 
&lt;h4&gt;Ptpar&lt;/h4&gt; 
 &lt;pre&gt;
 (
 
  Ptpar([0, 
   Pbind(\dur, 0.8,
    \octave, 4,
    \degree, [1, 3, 5],
    \amp, 0.2),
   0, Pbind(\dur, 0.4,
    \octave, 5,
    \degree, Pseq([1, 4, 5, 7, 8, \rest, 5, 7, 5, 5, 6], inf),
    \amp, 0.3)
   ]).play
 )
&lt;/pre&gt;
&lt;ul&gt; 
  &lt;li&gt;Ptpar takes an array as an argument to it's constructor.  Arrays can be declared by putting a list inside square brackets, so [1, 3, 5] is an array.  Ptpar's array is made up of pairs of times and patterns.  This synchronizes multiple patterns
  &lt;li&gt;\octave and \degree are just other ways of naming notes
  &lt;li&gt;if you list an array as one of the value pairs in a pattern, it will create multiple events, one for each item in the array, so the top Pbind sends three sets of OSC messages to the server every time it makes a note
  &lt;li&gt;Pseq steps through an array, returning each item in turn.  It takes two arguments, the first is the array and the second is the number of times to step through it
  &lt;li&gt;inf is a reserved word which means infinite, so the Pseq never stops stepping through the array.  If we gave a 2, instead, it would step through the array twice and then return nil, which will stop the Pbind it is inside, but not the other Pbind, which will keep running forever
&lt;/ul&gt;  
&lt;h4&gt;Tying things together&lt;/h4&gt; 
 &lt;pre&gt; 
   (
    Pbind(
     [\freq, \dur], Pfunc({
     
       var pitch, dur;
       
       pitch = (10.rand * 44) + 440;
       if ((pitch &amp;lt; 660), {
        dur = 0.45;
       } , {
        dur = 0.25;
       });
       
       [pitch, dur]
      })
     ).play
   )
&lt;/pre&gt;
&lt;ul&gt;   
    &lt;li&gt;You can put symbols in arrays and then give them an array of values.  The symbol at index n is tied to the value at index n.
    &lt;li&gt;This lets you tie related parameters together
    &lt;li&gt;Make sure your Pfunc or Prout or other Pattern returns an array when an array is expected
 &lt;/ul&gt;
 &lt;h4&gt;Accessing Events&lt;/h4&gt; 
 &lt;pre&gt;
  
   (
    Pbind(
    
     \freq, Pwhite(440, 880),
     \dur, Pfunc({arg evt;
          
        (evt.at(\freq) &amp;lt; 660).if ({
         0.45;
        } , {
         0.25;
        });
     })
  ).play
 )
&lt;/pre&gt; 
&lt;ul&gt;
  &lt;li&gt;Pwhite is a Pattern which returns a value between it's first argument and it's second argument
  &lt;li&gt;Pfuncs and Prouts can have an argument to their function which is the event as it's been constructed so far.  This gives you access to all the parameters which have already been set
  &lt;li&gt;ifs return the result of the function which they evaluated
  &lt;li&gt;You can find more Pthings in the help file for Patterns
&lt;/ul&gt;   
&lt;h4&gt;Array.do and while&lt;/h4&gt;
&lt;pre&gt;
   (
    Pbind(
     \dur,  0.25,
     [\freq, \amp], Prout({
     
        var arr, amps;
        
        arr = [];
        amps = [0.2, 0.3, 0.4];
        
        {arr.size &lt; 10}. while({
        
         arr = arr.add((10.rand * 44) + 440);
           arr.do({ arg item, index;
        
          [item, amps.wrapAt(index)].yield;
         })
         
        })
       })
    ).play
   )
&lt;/pre&gt;
&lt;ul&gt;
   &lt;li&gt;functions understand the message while.  the function is evaluated, if it returns true, the function passed as an argument to the while loop runs once.  Then the receiver is evaluated again.  This repeats until the receiver evaluates to false.
   &lt;li&gt;Array.size returns the size of the receiver
   &lt;li&gt;Array.do is a way to step through an array.  The function takes as an argument the array item and the index of the item
   &lt;li&gt;Array.add is a message which adds an item to an array.  Arrays cannot grow in size beyond what they were originally allocated.  Therefore, the receiver may be unchanged, although the action returns a new array with the added item.  Therefore, if you want to add an item to an array, assign the result to a variable
   &lt;li&gt;wrapAt is a way to access the contents of the array such, that indexes "wrap around" &lt;pre&gt;amps.wrapAt(index)&lt;/pre&gt; is equivalent to &lt;pre&gt;amps.at(index % amps.size)&lt;/pre&gt;
   &lt;li&gt;Arrays can be accessed by index
&lt;/ul&gt;
&lt;h4&gt;Arrays&lt;/h4&gt;
&lt;p&gt;   Arrays can take other messages, like scramble, which returns a reordered array but does not change the receiver of the message.  Choose returns a single randomly chosen item from an array.  Many other messages can be found in the helpfiles for Array and it's super classes.&lt;/p&gt;
&lt;h4&gt;A quick GUI Example&lt;/h4&gt;
&lt;pre&gt;
   
   (
   c = Conductor.make({arg thisConductor, arrSize, vol, freq, dur;
    
    vol .spec_(\db);
    freq.spec_(\freq);
   arrSize.sp(10, 1, 50, 1); // sp( val, min, max, step, warp)
    dur.sp(0.45, 0.1, 1, 0);
     
    thisConductor.pattern_(Pbind (
     \db,  vol, 
     \dur, dur,
     \freq, Prout ({
     
         var arr, diff;
        
       arr = [];
       
        
       {arr.size &lt; arrSize.value}. while({
        
        arr = arr.add(freq.value);
          arr.do({ arg item, index;
        
         item.yield;
      });
     });
    })
   ));
  });
  
  c.show;
  )
&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Conductor is a graphical class which gives you some gui widgets.  It is included in the Wesleyan build.
  &lt;li&gt;the first argument is the conductor itself.  we can't call it "this" because that's a reserved word
  &lt;li&gt;the additional arguments are control values, instances of CV.  they get GUIS assigned to them usually
  &lt;li&gt;CV.spec_(\symbol) gives you a predefined ControlSpec which is is designed for a particular type of CV
  &lt;li&gt;Otherwise, you can define your own.  step refers to how big the steps are between values
  &lt;li&gt;You can give the Conductor a pattern (such as a Pbind) and use the CVs as Patterns
  &lt;li&gt;If you have to refer to CV in a function or a routine and you want the value that the slider is currently at, use CV.value
&lt;/ul&gt;      
&lt;p&gt;&lt;small&gt;&lt;a href="http://technorati.com/tag/SuperCollider" rel="tag"&gt;SuperCollider&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-114460240021485665?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/114460240021485665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=114460240021485665&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/114460240021485665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/114460240021485665'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2006/04/fast-pbind-based-introduction-for.html' title='Fast Pbind-based Introduction for Experienced Programmers'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-110853523454349712</id><published>2005-02-16T01:22:00.000-05:00</published><updated>2005-02-16T01:27:14.553-05:00</updated><title type='text'>Server</title><content type='html'>&lt;p&gt;In the &lt;a href="http://sc3howto.blogspot.com/2005/02/introduction.html"&gt;introduction&lt;/a&gt;, we executed some code:&lt;/p&gt;

&lt;pre&gt; Sever.local.boot&lt;/pre&gt;

&lt;p&gt;Server is a class.  We can tell it is a class because in SuperCollider, all class names start with capital letters.  Nothing else may start with a capital letter.&lt;/p&gt;

&lt;p&gt;local is a message.  Supercollider uses a syntax called &lt;b&gt;receiver notation&lt;/b&gt;, which looks like:&lt;/p&gt;

&lt;pre&gt; object.message(argument1, argument2, . . . argumentN)&lt;/pre&gt;
&lt;p&gt;Or&lt;/p&gt;
&lt;pre&gt; Class.message(argument1, argument2, . . . argumentN)&lt;/pre&gt;

&lt;p&gt;The arguments are optional.  So “Server.local” takes the class “Server” and passes the message “local” to it.&lt;/p&gt;

&lt;p&gt;When we send a message to an object or a class, we get a &lt;b&gt;return value&lt;/b&gt;.  The object or class gives us something back.  Often, but not always, what we get back is the object or class that we just sent the message to.  Sometimes, however, we get back something else.  Server.local returns an object that refers to the localhost server. &lt;/p&gt;

&lt;p&gt;Server.local is a &lt;b&gt;getter&lt;/b&gt; message.  The Server class contains some data that belongs to the class rather than to any particular instance of the class.  We can get at that data by using a getter message.  Getter messages return data stored within an object or a class.  &lt;b&gt;Setter&lt;/b&gt; messages have a similar concept.  They set a piece of data within an object or a class.  We’ll talk about them more later.&lt;/p&gt;

&lt;p&gt;We then take the result of Server.local (which is an object that refers to the localhost server) and send that object the message “boot.”  &lt;b&gt;Expressions&lt;/b&gt; are evaluated left to right, so Server.local.boot is equivalent to (Server.local).boot.  An expression is a bit of code that returns a value.  Server.local is an expression because it returns something.  Server.local.boot is also an expression because it also returns something.&lt;/p&gt;

&lt;p&gt;Server.local is not, itself, the localhost server, as that is a separate process.  However, Server.local contains information about the localhost server.  The object knows how to communicate with the Server via OSC.  So when we tell it “boot”, it translates that for us into an OSC message and sends that message to the separate Server process.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Class names must start with capital letters and are the only things that start with capital letters.
&lt;li&gt;We pass messages in receiver notation as object.message(argument) or Class.message(argument)
&lt;li&gt;Classes and objects return something when you send them messages.
&lt;li&gt;Getter messages return data stored within an object or a class.
&lt;li&gt;Expressions are bits of code that return something.  They are evaluated from left to right.
&lt;li&gt;Server.local is an object which can do OSC communication for us.
&lt;/ul&gt;
&lt;p&gt;&lt;small&gt;&lt;a href="http://technorati.com/tag/SuperCollider" rel="tag"&gt;SuperCollider&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-110853523454349712?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/110853523454349712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=110853523454349712&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/110853523454349712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/110853523454349712'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2005/02/server.html' title='Server'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-110853432727783248</id><published>2005-02-16T00:54:00.000-05:00</published><updated>2005-02-16T01:30:59.156-05:00</updated><title type='text'>Object Oriented Programming</title><content type='html'>&lt;h3&gt;Programs and Algorithms&lt;/h3&gt;
&lt;p&gt;An &lt;b&gt;algorithm&lt;/b&gt; is a step-by-step way to solve a problem or complete a task.  You can think of it like a musical score. You play a score in order from left to right, playing each note or rest one after each other, jumping backwards in case of repeats and forwards in cases of things like second endings or codas.  In the same way, you can tell your computer to play a B for two seconds and then an A and tell it to repeat back and so on.  You're able to tell your computer to do more complicated things, like play a C if you move your mouse to the upper right hand corner and a D in the left hand corner.
&lt;/p&gt;
&lt;p&gt;For example, imagine making a toasted bagel with cream cheese.  Your algorithm might go like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get a bagel
&lt;li&gt;Cut bagel in half
&lt;li&gt;Toast the bagel
&lt;li&gt;Spread cream cheese on each half, on the side that was cut.
&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;Programs&lt;/b&gt; are coded according to algorithms. A program is a series of instructions that a computer follows to complete a task. In order to communicate instructions to your computer, you need to be able to speak a language in common with it.  The native language of computers is called machine code and is made up of nothing but ones and zeros.  Every kind of computer speaks a different dialect of machine code.  Fortunately, there exist programming languages that are easier for humans to learn.  You write your instructions (or code) in the SuperCollider language and when you evaluate them (by highlighting them and pressing enter), the interpreter translates them to machine code.  Your program is made up of the lines of code that you write.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You start by thinking of your algorithm and then create a program to implement it.
&lt;/ul&gt;
&lt;h3&gt;Objects and Classes: a theoretical example&lt;/h3&gt;
&lt;p&gt;Let’s use our bagel algorithm to create &lt;b&gt;pseudo-code&lt;/b&gt; that looks like &lt;b&gt;object-oriented&lt;/b&gt; code.  Pseudo-code is a mockup of a program.  It will look like a SuperCollider program would look if it dealt with food instead of sounds.  
&lt;/p&gt;
&lt;p&gt;Our algorithm starts with:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get a bagel
&lt;/ol&gt;
&lt;p&gt;In real life, we would get a bagel from a bag of bagels.  In an object-oriented language, we would think of the bagel as an &lt;b&gt;object&lt;/b&gt; that we could manipulate. An object is an entity containing data and &lt;b&gt;methods&lt;/b&gt; for accessing that data.  The definition of a type object is called a &lt;b&gt;class&lt;/b&gt;.  &lt;/p&gt;

&lt;p&gt;A bagel object would probably contain information about whether it was cut or toasted and what toppings it would have.  Classes define objects and are a blueprint for object creation.  They also can create objects. Classes contain methods called &lt;b&gt;constructors&lt;/b&gt; that create new instances of the class and initialize them.  We would send a &lt;b&gt;message&lt;/b&gt; to the Bagel class asking it to make us a bagel object.  &lt;/p&gt;

&lt;pre&gt; Bagel.new;&lt;/pre&gt;

&lt;p&gt;Bagel is the class.  new is the message.  Once we have the new object, we need to remember it, so let’s change that to give it a name:&lt;/p&gt;

&lt;pre&gt; my_bagel = Bagel.new;&lt;/pre&gt;

&lt;p&gt;my_bagel is the name of the newly created bagel.  The equals sign is an &lt;b&gt;assignment&lt;/b&gt; statement.  my_bagel gets the new bagel.  We’ll come back to this later.&lt;/p&gt;
&lt;ol start=2&gt;
&lt;li&gt;Cut bagel in half
&lt;/ol&gt;
&lt;p&gt;In real life, we would do this with a knife.   In object oriented programming, objects provide their own methods for changing their state.  We send a message to the bagel saying we want it cut.&lt;/p&gt;

&lt;pre&gt; my_bagel.cut;&lt;/pre&gt;

&lt;p&gt;my_bagel is the object.  cut is the message.&lt;/p&gt;
&lt;ol start=3&gt;
&lt;li&gt;Toast the bagel
&lt;/ol&gt;
&lt;p&gt;Again, in real life, we would put the bagel in a toaster.  But, since this is an object, we send a message telling it we want it toasted.&lt;/p&gt;

&lt;pre&gt; my_bagel.toast;&lt;/pre&gt;
&lt;ol start=4&gt;
&lt;li&gt;Spread cream cheese on each half, on the side that was cut.
&lt;/ol&gt;
&lt;p&gt;The bagel will know what to do.  The author of the class has already written a method that applies a topping to each half.  We just have to specify which topping we want, by using an argument.  Arguments are additional data we pass along while sending a message to an object.&lt;/p&gt;

&lt;pre&gt; my_bagel.spread(cream_cheese);&lt;/pre&gt;

&lt;p&gt;So, adding in the cream_cheese creation, our pseudo-code bagel program would look like:&lt;/p&gt;
&lt;pre&gt;
 (

  var my_bagel, cream_cheese;
 
  my_bagel = Bagel.new;
  cream_cheese = Cheese.new(\cream);
 
  my_bagel.cut;
  my_bagel.toast;
  my_bagel.spread(cream_cheese);
 
 )
&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Objects are instances of the Classes that define them.
&lt;li&gt;Objects contain data and methods to access them.
&lt;li&gt;Classes are factories for creating new instances of objects.
&lt;li&gt;We communicate with objects and classes by sending them messages.
&lt;li&gt;We can specify additional information by providing arguments with our messages.
&lt;/ul&gt;


&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Algorithm"&gt;Additional reading on programs, algorithms and pseudo-code&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;small&gt;&lt;a href="http://technorati.com/tag/SuperCollider" rel="tag"&gt;SuperCollider&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-110853432727783248?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/110853432727783248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=110853432727783248&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/110853432727783248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/110853432727783248'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2005/02/object-oriented-programming.html' title='Object Oriented Programming'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10668379.post-110773570590359850</id><published>2005-02-06T19:14:00.000-05:00</published><updated>2005-02-15T21:56:07.806-05:00</updated><title type='text'>Introduction</title><content type='html'>&lt;h4&gt;What is SuperCollider?&lt;/h4&gt;
&lt;p&gt;According to &lt;a href="http://supercollider.sf.net/"&gt;http://supercollider.sf.net/&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;SuperCollider is a state of the art, realtime sound synthesis server as well as an interpreted Object Oriented language which is based on Smalltalk but with C language family syntax. The language functions as a network client to the sound synthesis server.
&lt;/p&gt;
&lt;p&gt;SC was written by James McCartney over a period of many years. It is now an open source GPL'd project maintained and developed by James and a few others.
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which is to say that SuperCollider is a tool to help you use your computer to make sounds.  It’s free and open source.  That means that you can look at how SuperCollider was written and modify it, share it with other people and use it any way you want.
&lt;/p&gt;
&lt;p&gt;SuperCollider has a steeper learning curve than some other music programs like MAX, but it is more flexible and more powerful.  This book is written for people who have not programmed before.  If you can use your computer to do things like edit a document and surf the web, you can learn to program.
&lt;/p&gt;
&lt;h4&gt;What Can You Do With It?&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;Digital synthesis&lt;/b&gt;&lt;br /&gt;
Supercollider can make any sound that can be created by DSP. 
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;FX processing&lt;/b&gt;&lt;br /&gt;
SC can do delays, filters, etc and can tweak a line-in or a pre-existing sound file in any way that you can think to program
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Algorithmic composition&lt;/b&gt;&lt;br /&gt;
Supercollider can generate sounds and play them, and it can also generate MIDI files that can be opened by Finale, Sibelius or other notation software and arranged for real instruments
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Two Applications for the Price of One&lt;/h4&gt;

&lt;p&gt;SuperCollider is actually two applications.   One application is an interpreter: an application designed to execute your Object Oriented programs written in the SuperCollider language.
&lt;/p&gt;
&lt;p&gt;The other program is an extremely fast and efficient sound synthesizer, which makes all the sound.  This program is called a server.  It can run from within the interpreter or as a separate process.  An internal server (one run within SuperCollider) has a small speed advantage over a separate process.  Also, there are some things that can only be run from an internal server, such as an oscilloscope plug in which lets you view the waveforms produced by the server.  However, if you crash the server, the interpreter will also crash and vice versa.
&lt;/p&gt;
&lt;p&gt;A server run as a separate process is called the localhost server.  Because the process is separate, there is a stability advantage because a server crash does not also crash your interpreter or vice versa.  You can run a server on a separate computer, if you’d like and even communicate with it via Rendezvous.  The interpreter client and audio server communicate via a network protocol called &lt;b&gt;OSC&lt;/b&gt;.  The interpreter sends OSC messages to the server based on your programs and the server sends messages back, based on what it’s doing.
&lt;/p&gt;
&lt;h4&gt;About this book&lt;/h4&gt;

&lt;p&gt;Explanatory text looks like all the text we have seen so far. &lt;p&gt;

&lt;pre&gt;Code examples look like this.&lt;/pre&gt;

&lt;p&gt;Vocabulary words are in &lt;b&gt;bold&lt;/b&gt; and are usually followed by a definition.  They can also be found in the glossary.&lt;/p&gt;

&lt;p&gt;Key points are summarized at the end of every section in a bulleted list.&lt;/p&gt;

&lt;p&gt;The first part of this book is about the interpreter and the programming language it uses.  The second part of this book is about the server and sound design.&lt;/p&gt;

&lt;h4&gt;Getting Started&lt;/h4&gt;

&lt;p&gt;First, you need a copy of SuperCollider 3, otherwise known as SC3.  You can download it from &lt;a href="http://sf.net/project/showfiles.php?group_id=54622"&gt;http://sf.net/project/showfiles.php?group_id=54622&lt;/a&gt;.   SC3 exists for Mac OSX, Windows and Linux.  The Mac version is the most developed and the most stable and the version referred to by this book.  However, aside from the appearance and the key-shortcuts, the Windows and Linux versions should be virtually the same.
&lt;/p&gt;
&lt;p&gt;There are some websites designed to help SuperCollider users, including the SC home page at &lt;a href="http://www.audiosynth.com/"&gt;http://www.audiosynth.com/&lt;/a&gt;, the SWIKI at &lt;a href="http://swiki.hfbk-hamburg.de:8888/MusicTechnology/6"&gt;http://swiki.hfbk-hamburg.de:8888/MusicTechnology/6&lt;/a&gt;, and the Electronic Life SC Forum at &lt;a href="http://electroniclife.co.uk/scforum/index.php"&gt;http://electroniclife.co.uk/scforum/index.php&lt;/a&gt;
&lt;/p&gt;
&lt;h4&gt;Using SuperCollider&lt;/h4&gt;

&lt;p&gt;Once you have downloaded SuperCollider and installed it, double click on the icon. Three windows should open on your screen. A big text window called "Untitled" should print out some information and there should be two smaller windows below it called "localhost server" and "internal server."  If there is an error in the Untitled window, the two server windows will not open.  Try downloading a different build of SuperCollider or running it on a different machine.&lt;/p&gt;


 

&lt;p&gt;The Untitled window is where text output goes.  The other two windows control two different versions of the audio Server.  The examples in this document use the localhost server.  If you want to hear audio, you must boot the audio server, which you can do by pressing the "Boot" button.  When you press the “Boot” button on the audio server, the interpreter starts up the server application.  When the server is finished booting, it sends an OSC message to the interpreter saying that it booted.  Then the interpreter changes the color of the word “localhost” to red and the “Boot” button changes to say “Quit.”  You can also boot a server from within a program, as we will see shortly. &lt;/p&gt;

 

&lt;p&gt;To run code, you highlight it with the mouse and then press the Enter key, NOT the return key.  (The enter key may be located next to your arrows or in your number pad.) To stop code that is running, hit apple-period.&lt;/p&gt;

&lt;p&gt;To get help, hit apple-shift-?.  To get help on a specific topic, for instance on Synth, highlight the word Synth and hit apple-shift-?.&lt;/p&gt;

&lt;h4&gt;Your First Program&lt;/h4&gt;

&lt;p&gt;Open a new window, which you can do under the File menu or by typing apple-n.  &lt;/p&gt;
&lt;p&gt;Boot the localhost server.  You can do this from within the interpreter.  To do this, type in the new window:&lt;/p&gt;
&lt;pre&gt; Sever.local.boot&lt;/pre&gt;

&lt;p&gt;Highlight the code you just typed with the mouse and then press the enter key.  Then, after the server finishes booting, type:&lt;/p&gt;
&lt;pre&gt; Event.default.play&lt;/pre&gt;

&lt;p&gt;Highlight the code you just typed with the mouse and then press the enter key.  You should hear a single short A.  If you do not hear a sound, make sure that you can hear other sounds from computer and the volume is turned up.  Make sure the localhost server is booted (and not the internal server).  If you are still having trouble, try downloading a different build of SuperCollider or asking somebody knowledgeable for help.&lt;/p&gt;

&lt;h4&gt;Chapter Summary&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;SuperCollider is a free tool for making music that can do DSP and algorithmic composition.&lt;/li&gt;
&lt;li&gt;SuperCollider is a synthesis server and an interpreter than can run together or separately.&lt;/li&gt;
&lt;li&gt;You must run a server (either internal, localhost or on another computer) to hear sound.&lt;/li&gt;
&lt;li&gt;Highlight code and press enter to execute it.&lt;/li&gt;
&lt;li&gt;Press apple-period to stop execution&lt;/li&gt;
&lt;li&gt;Press apple-question to get help&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;small&gt;&lt;a href="http://technorati.com/tag/SuperCollider" rel="tag"&gt;SuperCollider&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10668379-110773570590359850?l=sc3howto.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sc3howto.blogspot.com/feeds/110773570590359850/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10668379&amp;postID=110773570590359850&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/110773570590359850'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10668379/posts/default/110773570590359850'/><link rel='alternate' type='text/html' href='http://sc3howto.blogspot.com/2005/02/introduction.html' title='Introduction'/><author><name>Charles Céleste Hutchins</name><uri>http://www.blogger.com/profile/18123138871494922485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2MW4T3cBz8I/SfhqnvbYJYI/AAAAAAAAAMQ/MPOHNc_N5aM/S220/2732905093_8a88fd9d78.jpg'/></author><thr:total>2</thr:total></entry></feed>
