/* Example 1a, heavily commented! */
/* in general (for now) we will avoid global variables in our work with one exception. Management of the Server usually needs attention that is independent of the rest of our coding work, so we will use the a global variable for it. Below, we will assign the 'internal' Server to the variable 's'. The 'internal' server allows for synthesis data to be shared with the language (so 'scope' works), BUT there is a small danger. If you do something that could possibly crash the Server, you could crash the app and lose work. Chances are, you won't be in danger of this for some time, but now is a good time to get into good saving habits. */
// assign the internal Server to 's'
s = Server.internal;
// tell s to start by sending it the 'boot' message
s.boot;
/* assign s to the Server classes 'default' class variable. This is done to let make things easier for the Ctk library which we will use for course examples */
Server.default = s;
// send the 'scope' message to the internal Server
s.scope;
/* Parenthesis can be used to create a single block of executable code. Double click the opening or closing parens to select ALL the code in the block */
(
/* The first part of a code block MUST be any variables you will use inside the code block. The scope of these variables will only be INSIDE this code block. Nothing outside of the code block will know what these variables are. Use the 'var' keyword to declare a single variable, or a comma separated list of vars. You can have multiple lines of variables, but all declarations must happen first. We'll have two things to refer to in this example:
noteObject will be a CtkSynthDef
note will be a CtkNote that is created from the prototype
*/
var noteObject, note;
/* Ctk is a library of tools that make note prototyping and creation easier in SuperCollider. The basis of all synthesis in SC is the SynthDef . A CtkSynthDef works in much the same way (sorry... no helpfile for CtkSynthDef... but you should look at SynthDef). For now, a CtkSynthDef takes two parameters. a symbol (which starts with a '\') and a function that describes a synthesis process. Functions are created with curly braces. Arguments can be passed into a function, and a function block can have its own set of local variables */
/* create a CtkSynthDef, and assign it to the variable 'noteObject'. The label of the CtkSynthDef is \oscili. The function has two arguments that can be passed into it, a frequency value for the sine tone inside the function, and an amp value */
noteObject = CtkSynthDef(\oscili, {arg freq, amp;
// the variable declarations
var osc, env;
/* the var 'osc' will represent the output of a SinOsc UGen. SinOsc is table lookup oscillator, with its own built in table of 8192 samples.
Sample values are linearly interpolated.
SinOsc takes two parameters, a frequency to oscillate at, and an
initial phase. In addition, SinOsc, like MOST UGens, also takes a 'mul'
and an 'add' argument. The .ar message to SinOsc tells the UGen to run
at the audio rate */
osc = SinOsc.ar(freq, 0, amp);
/* env will take the output of the Line UGen, this time running at the
'k-rate', or control rate. This rate runs MUCH slower then audio rate.
By default, it will calculate one sample for every 64 samples of audio
information. For slow moving signals, these can be more efficient for
data calculation. Below, the UGen will create a line that goes from 1
to 0 over 2 seconds. */
env = Line.kr(1, 0, 2);
/* Finally, we want to write or output. Out.ar writes data to an audio
bus. It takes a bus to write to (here, 0 is the '0th' bus, or left
channel), and it will write the result of our SinOsc, times the output
of the envelope. The multiplier will take every sample of audio data,
and multiply it by a linearly interpolated value from the k-rate data
of the env */
Out.ar(0, osc * env);
// close off the CtkSynthDef function, and the CtkSynthDef itself
}); // this is the end of a statement, so a semi-colon is needed
/* calling 'new' on our CtkSynthDef will create a new 'note' instance of process described in the synthesis function (or graph). The first two arguments that are passed into the 'new' instance method are the note's starttime and duration */
note = noteObject.new(1.0, 2.0);
/* the arguments you provided in the CtkSynthDef function can have their parameters set here as well. Use the name of the arg, with an underscore and parens. The underscore is a 'setter' symbol, and is used in the SC language quite a bit. It also lets you string messages together (making more compact code). Below, the freq is set to 440 Hz, and the amp set to 0.5 (half of the linear amplitude) */
note.freq_(440).amp_(0.5);
// finally... tell the note to play!
note.play;
// close off the code block
);