From Fedora Project Wiki
(page creation)
 
(initial content dump)
Line 1: Line 1:
Address: User:Crantila/FSC/Synthesizers/SuperCollider/Basic_Programming
Address: User:Crantila/FSC/Synthesizers/SuperCollider/Basic_Programming


=== Functions, Variables, and Assignment ===
As with any programming language, you will start learning SuperCollider with the basic commands, that are of little use by themselves.  However, since the language is so flexible, even the most basic commands can be combined in ways that create highly complex behaviours.  The example program, "Method One," was written with the goal of illustrating how a single sound-generating object can be used to create an entire composition.  This tutorial does not begin with audio-generating code, which helps to emphasize that SuperCollider is primarily a programming language.


=== Sound-Making Functions ===
This portion of the Guide is designed as a "reference textbook," which you can use both to learn the SuperCollider language in the first place, and to remind yourself about the language's features afterwards.


=== ArrayedCollections and Multichannel Audio ===
The Guide will probably be most effective when read only in small portions at once.


=== The Mixer?? ===
<!--
Term
Definition
Example
Explanation
(Exploration)
-->


=== How to Get Help ===
== First Steps ==
=== The Different Parts of SuperCollider ===
As you discovered when installing SuperCollider, there are actually many different components involved with SuperCollider.  Here is a list of some of them, with brief descriptions of their purpose:
* Programming language: this is an abstract set of rules and guidelines that allow you to write down instructions for producing sounds.
* Interpreter: this is what is run in GEdit; it transforms the "programming language" instructions written by you into useful instructions for the server; also called the "client."
* Server: this is what synthesizes the sound, according to instructions sent to it by the interpreter.
* Library: these contain commands and the instructions to be executed when you call the commands; the interpreter looks up commands in the library when you call them.


=== SynthDefs and Synths ===
This modular design allows for several advanced capabilities and features.  Any particular element could theoretically be replaced without affecting other elements, as long as the methods of communication remain the same.  As long as the programming language is the same, portions of the library can be modified, removed, or added at will; this happens often, and Planet CCRMA at Home provides a collection of library extensions.  One of the most exciting capabilities is the ability to run the interpreter and server on different physical computers.  The networking component is built into these components - they always communicate by UDP or TCP, even when run on the same computer!  Although this ability is not used in this Guide, it is not difficult.


=== Busses ===
The most important thing to remember is that the SuperCollider interpreter is what deals with the programs you write.  The SuperCollider server is controlled by the interpreter, but is an independent program.  For simple things, like the Hello World Programs below, the server is not even used - after all, there is no audio for it to synthesize.


=== Groups, Nodes, and Ordering ===
=== "Hello, World!" ===
The first program that one traditionally makes when learning a new programming language is called "The Hello World Program."  This is a simple and trivial application that simply prints outs the phrase, "Hello, World!" (or any variation of it).  It might seem useless at first, but the ability to provide feedback to an application's user is very important, and this is essentially what the Hello World Program does.


=== Buffers?? ===
Here is the program in SuperCollider:
<pre>
"Hello, World!".postln;
</pre>


=== Scheduling and Clocks ===
Here is an extension to that program:
<pre>
"Hello, World!".postln;
"Hello, SC!".postln;
</pre>


=== Routines and Tasks ===
As with all examples in this Guide, you should paste these programs into GEdit, and execute them with SuperCollider.  Look at the output produced by the programs, but don't worry about it for now.


=== Patterns ===
These programs are very small, but it highlights some key concepts of the SuperCollider language, described below.
 
=== Return Values ===
Every SuperCollider program must provide the interpreter with a value (some information) when it has carried out all of its instructions.  This value is called a "return value," because it is the value given by a program when it "returns" control to the interpreter.  In a SuperCollider program, it is the last value stated in a program that automatically becomes the return value - no special command is required.  When program execution ends, and control is returned to the SuperCollider interpreter, the interpreter outputs the return value in the "SuperCollider output" pane.
 
In the single-line Hello World Program above, the program produces the following output:
<pre>Hello, World!
Hello, World!</pre>
The program appears to have been executed twice, but that is not the case.  The first "Hello, World!" is printed by the program.  The second "Hello, World!" appears because <code>"Hello, World!.postln</code> is the last (in this case, the only) value of the program.  It is "returned" by the program, and the interpreter prints it.
 
In the two-line Hello World Program above, the program produces the following output:
<pre>
Hello, World!
Hello, SC!
Hello, SC!
</pre>
This makes it more clear that the program is not being executed twice, and that it is the last value of a program that is returned to the interpreter.
 
Try executing the following single-line programs.  Look at the output produced by each, and determine whether it is printed by the program itself, the interpreter, or both.
* <code>"Hello, World!".postln;</code>
* <code>"Hello, World!";</code>
* <code>5.postln;</code>
* <code>5;</code>
Can you modify the two-line Hello World Program so that each line is printed only once?
 
Note: In reality, every "function" must return a value.  Functions are described later in this Guide; the difference is not yet important.
 
=== Statements ===
A "statement" is a single instruction, which is always ended with a semicolon.  Exactly what constitutes a statement will become clear as you gain experience, and including semicolons will quickly become an automatic action.
 
In the Hello World Programs above, all of the statements contain the single instruction to post a line to the output screen.  What happens when you remove the first semicolon, which marks the end of the first statement?  The SuperCollider interpreter produces an unhelpful error message, and tells you that an error occurred ''after'' the forgotten semicolon.  This is why it is important to always remember statement-concluding semicolons.
 
=== Data Types: Numbers and Strings ===
In many programming languages, it is the programmer's responsibility to determine the type of data that is being used, and how it should be stored.  The SuperCollider interpreter takes advantage of the power of modern computers, and deals with this on our behalf.  This greatly simplifies basic tasks, because there are only two kinds of data to worry about, and they make perfect sense:
* Numbers: These are numbers, written simply as numbers.  Anything that can be done with real-world numbers can also be done with SuperCollider's numbers.  They can be as large or small, positive or negative as you want.  They can have any number of digits on either side of the decimal point.
* Strings: These are a string of characters, written between two double-quote characters like "this."  The double-quote characters are required so that SuperCollider knows where to begin and end the string of characters.  A string of character can contain as many characters as you like, including one character and no characters.  If you want to include a double-quote character in a string, you should put a blackslash before it.  The following is interpreted by SuperCollider as a string with only a double-quote character: <code>"\""</code>
 
Here are some examples of numbers and strings:
* <code>5;</code>
* <code>18920982341;</code>
* <code>0.00000000000001;</code>
* <code>"characters";</code>
* <code>"@";</code>
* <code>"";</code>
* <code>"6";</code>
 
Is the last example a number or a string?  You and I recognize that it is a number inside a string, but SuperCollider will only treat it as a string.  You can do string things with it, but you cannot do number things with it.  You cannot add <code>"6"</code> to something, for example.  Notice also that each example ends with a semicolon, which makes them complete statements.  The statements don't do anything but represent themselves.
 
Try executing the following single-line programs.  Think about why the SuperCollider interpreter produces the output that it does.
* <code>6 + 3;</code>
* <code>"6" + 3;</code>
* <code>"six" + 3;</code>
 
=== Simultaneous Execution ===
Complex SuperCollider programs contain many parts, which all do different things.  Sometimes, executing all of these together doesn't make sense, and it can be difficult to know which portions of the program are supposed to be executed when.  To help with this, the interpreter allows you to mark portions of your program between ( and ) so that you will know to execute them together.
 
Here is an example:
<pre>
(
  "Hello, Fred!".postln;
  "Hello, Wilma!".postln;
)
(
  "Goodbye, Fred!".postln;
  "Goodbye, Wilma!".postln;
)
</pre>
It doesn't make sense to say "hello" and "goodbye" at the same time, so separating these sections with parentheses will serve as a reminder.  In case we try to execute all of the code at once, the SuperCollider interpreter will give us an error.
 
== Variables and Functions ==
The concepts in this section are related to the mathematical terms with the same names.  This is a modern-day result of the first uses of computers and programming languages: the calculation of complex mathematical problems.
 
=== Variables ===
A variable is a symbol that can be assigned an arbitrary value.  A "symbol" is a series of alphabetic and numeric characters, separated by whitespace (a space, a line-break, or the end of the file).  When a variable is "assigned" a value, the variable name (the symbol) is understood to be a substitute for the assigned value.
 
Consider a traffic light, which has three possible symbols: green, yellow, and red.  When you are driving, and you encounter a traffic light, you might see that its red symbol is activated (the red light is illuminated).  What you see is a red light, but you understand that it means you should stop your car.  Red lights in general do not make you stop - it is specifically red traffic lights, because we know that it is a symbol meaning to stop.
 
SuperCollider's variables work in the same way: you tell the interpreter that you want to use a symbol, like <code>cheese</code>.  Then you assign <code>cheese</code> a value, like <code>5</code>.  After that point, whenever you use <code>cheese</code>, the interpreter will automatically know that what you really mean is <code>5</code>.
 
Run the following two programs.  They should result in the same output.
<pre>
(
  5 + 5;
)
</pre>
<pre>
(
  var cheese;
  cheese = 5;
  cheese + cheese;
)
</pre>
 
In the first example, the program calculates the value of <code>5 + 5</code>, which is <code>10</code>, and returns that to the interpreter, which prints it out.  In the second example, the program tells the interpreter that it wants to use a variable called <code>cheese</code> then it assigns cheese the value <code>5</code>.  Finally, the program calculates <code>cheese + cheese</code>, which it understands as meaning <code>5 + 5</code>, and returns <code>10</code> to the interpreter, which prints it out.
 
This trivial use of a variable does nothing but complicate the process of adding 5 to itself.  Soon you will see that variables can greatly simplify your programs.
 
=== Using Variables ===
There are three words that describe the key stages of using a variable: declaration, initialization, and assignment.
 
A variable must be declared before use, so that the interpreter knows that you want to use that symbol as a variable.  All variables must be declared before any statement that does not declare a variable; in other words, you should declare your variables before doing anything else.  Variable names are declared like this:
<pre>var variableName;</pre>
Variables can also be declared in lists, like this:
<pre>var variableOne, variableTwo;</pre>
 
Variables can be assigned a value at any time after they have been declared.  Any single object can be assigned to a variable.  If a variable is already assigned a value, any subsequent assignment will erase the previous assignment; the previously-assigned value will is not retrievable.
 
The first assignment to a variable is said to "initialize" the variable.  Initialization is a special kind of assignment, because a variable cannot be used before it is initialized.  If a program attempts to use an un-initialized variable, the SuperCollider interpreter will cause an error.  For this reason, you should always initialize a variable when you declare it.  There is a special way to do this:
<pre>var variableName = nil;</pre>
Since you can't always assign a useful value, you can pick an arbitrary one.  Assigning "nil" is common practice, because it means "nothing," but without actually being nothing (this avoids ''some'' errors).  Assigning zero is another possibility; it is standard practice in many programming languages, and will avoid most errors, even if the variable is eventually supposed to hold another kind of object.  Intialization and declaration of multiple variables can also be done as a list:
<pre>var variableOne = 0, variableTwo = 0;</pre>
 
Single-letter variable names have a special purpose in SuperCollider.  They are already declared, so you don't have to declare them.  They are also already initialized to "nil", so you don't have to do that either.  These variable names are intended to be used as a quick fix, while you're experimenting with how to make a program work.  You should not use them in good-quality programs.
 
The single-letter variable "s" is automatically assigned to the server on the computer running the interpreter.  You should avoid re-assigning that variable.
 
Variable names should always begin with a lower-case letter.
 
Use variables to write programs that do the following tasks:
# Perform arithmetic with an uninitialized variable.  An error should appear when the program is executed.
<!--
(
  var ten;
  5 + 10;
) -->
# Calculate the value of <code>y</code>, if all other values are known, for the quadratic equation: <code>y = a * x * x + b * x + c</code>
<!--
(
  var a = 5, b = 2, c = 0.1;
  var x = 12;
  a * x * x + b * x + c;
) -->
# Re-write the Hello World Program so that it will say "Hello" to a name stored in a variable.  Remember that you can use the interpreter to automatically output the last line of a function.
<!--
(
  var name = "Jessica";
  "Hello" + name;
) -->
 
=== Functions ===
A Function is a statement, or a series of statements, that we want to use many times.  When a Function is assigned to a variable, you can execute the Function as many times as you wish.  Any statements that happen between braces { like this; } are treated as a Function.  Functions are executed by passing them the "value" message, as in the following example.
 
Here is a Function that is not assigned to a variable, and is executed once.
<pre>{ "Hello, World!".postln; }.value;</pre>
Notice that there are two semicolons: one after the statement within the Function, and one after the "value" message that tells the Function to execute.
 
Here is a Function with identical function, assigned to a variable, and executed twice.
<pre>
var myFunction = { "Hello, World!".postln; }; // note two semicolons
myFunction.value;
myFunction.value;
</pre>
 
=== Function Arguments ===
The most useful aspect of Functions is that they can produce varying results, depending on their input.  For whatever reason, the input accepted by a Function is called an "argument."  SuperCollider's Functions can accept any number of arguments - zero, one, or many.  Argument values (called "parameters") are provided to a Function by adding them in parentheses after the name of the Function, separated with commas, like this: <code>exampleFunction( 5, 7, 9 );</code>  Argument variables are declared as the first statement in a Function, like this: <code>arg oneNumber, twoNumber;</code>
 
This program is significantly more complicated than previous examples, but it shows how useful Functions can be.  Notice how the braces in that example are on different lines than the rest of the Function, which gives us more space within the Function to complete some useful work.
<pre>
(
  var greeter =
  {
      arg name;
      ( "Hello" + name ).postln;
  };
 
  greeter.value( "Samantha" );
  greeter.value( "Jermain" );
  nil;
)
</pre>
Here is how the program works:
# A variable named <code>greeter</code> is declared, and assigned a Function.
# The Function contains an argument called <code>name</code>, and outputs "Hello" plus the name given to it.
# The parentheses here <code>( "Hello" + name )</code> ensure that the two strings are added together ''before'' the "postln" message prints them out.
# The <code>greeter</code> variable is used to call the Function with two different names.
# The <code>nil;</code> statement is optional, and does not affect the operation of the program.  What it does is return a "nothing" value to the interpreter after program execution completes, so that the last message is not repeated.
 
Since every argument has a name, SuperCollider allows you to use that name when executing the Function.  This example executes the <code>greeter</code> Function from the last example:
<pre>greeter.value( name:"Myung-Whun" );</pre>  This is more useful if there are many arguments, and you do not remember the order that they appear in the Function's definition.
 
SuperCollider also allows you to specify default values for arguments, so that they do not need to be specified.  This allows optional customization of a Function's behaviour, and is therefore very powerful.
 
This example modifies the one above by adding default-value arguments, and by calling arguments with their name.
<pre>
(
  var greeter =
  {
      arg name, greeting = "Hello";
      ( greeting + name ).postln;
  };
 
  greeter.value( "Samantha" );
  greeter.value( "Jermain", "Goodbye" );
  greeter.value( name:"Myung-Whun" );
  greeter.value( greeting:"Bienvenue", name:"Marcel" );
  nil;
)
</pre>
 
Any value can be used as a parameter, as long as the Function expects it.  In fact, even Functions can be used as parameters for Functions!
 
=== Function Return Values ===
All SuperCollider Functions return a value to the interpreter when they have finished execution.  As with programs, the value returned is the value of the last statement in the Function.  The return value of a Function can be captured, assigned to a variable, and used again later.
 
This example assigns the result of a Function to a variable.
<pre>
(
  var mysticalMath =
  {
      arg input = 0;
      input * 23;
  };
  var someNumber = 9;
 
  someNumber = mysticalMath.value( someNumber );
  someNumber.postln;
  nil;
)
</pre>
Here is how the program works:
# A Function and variable are created, and assigned values.
# This line <code>someNumber = mysticalMath.value( someNumber );</code> executes the <code>mysticalMath</code> Function, which multiplies its argument by 23 and returns the value.  Then, it assigns the return value of the Function to <code>someNumber</code>.  In any statement that contains an assignment, the assignment is always done last.  In other words, the Function in this example will ''always'' be given an argument of <code>9</code>, and only ''after'' the Function completes execution and returns a value will that value be assigned to <code>someNumber</code>.
# The new value of <code>someNumber</code> is displayed.
 
The program could have been shortened like this:
<pre>
(
  var mysticalMath =
  {
      arg input = 0;
      input * 23;
  };
 
  var someNumber = mysticalMath.value( 9 );
  someNumber.postln;
  nil;
)
</pre>
 
It could have been shortened even more like this:
<pre>
(
  var mysticalMath =
  {
      arg input = 0;
      input * 23;
  };
 
  mysticalMath.value( 9 ).postln;
  nil;
)
</pre>
 
Experiment with the shortened versions of the program, ensuring that you know why they work.
 
=== Variable Scope ===
A variable is only valid within its "scope."  A variable's scope is determined by where it is declared.  It will always last between either ( and ) or { and }.
 
<!-- START HERE -->
 
== Sound-Making Functions ==
 
== ArrayedCollections and Multichannel Audio ==
 
== The Mixer?? ==
 
== How to Get Help ==
 
== SynthDefs and Synths ==
 
== Busses ==
 
== Groups, Nodes, and Ordering ==
 
== Buffers?? ==
 
== Scheduling and Clocks ==
 
== Routines and Tasks ==
 
== Patterns ==

Revision as of 07:54, 5 July 2010

Address: User:Crantila/FSC/Synthesizers/SuperCollider/Basic_Programming

As with any programming language, you will start learning SuperCollider with the basic commands, that are of little use by themselves. However, since the language is so flexible, even the most basic commands can be combined in ways that create highly complex behaviours. The example program, "Method One," was written with the goal of illustrating how a single sound-generating object can be used to create an entire composition. This tutorial does not begin with audio-generating code, which helps to emphasize that SuperCollider is primarily a programming language.

This portion of the Guide is designed as a "reference textbook," which you can use both to learn the SuperCollider language in the first place, and to remind yourself about the language's features afterwards.

The Guide will probably be most effective when read only in small portions at once.


First Steps

The Different Parts of SuperCollider

As you discovered when installing SuperCollider, there are actually many different components involved with SuperCollider. Here is a list of some of them, with brief descriptions of their purpose:

  • Programming language: this is an abstract set of rules and guidelines that allow you to write down instructions for producing sounds.
  • Interpreter: this is what is run in GEdit; it transforms the "programming language" instructions written by you into useful instructions for the server; also called the "client."
  • Server: this is what synthesizes the sound, according to instructions sent to it by the interpreter.
  • Library: these contain commands and the instructions to be executed when you call the commands; the interpreter looks up commands in the library when you call them.

This modular design allows for several advanced capabilities and features. Any particular element could theoretically be replaced without affecting other elements, as long as the methods of communication remain the same. As long as the programming language is the same, portions of the library can be modified, removed, or added at will; this happens often, and Planet CCRMA at Home provides a collection of library extensions. One of the most exciting capabilities is the ability to run the interpreter and server on different physical computers. The networking component is built into these components - they always communicate by UDP or TCP, even when run on the same computer! Although this ability is not used in this Guide, it is not difficult.

The most important thing to remember is that the SuperCollider interpreter is what deals with the programs you write. The SuperCollider server is controlled by the interpreter, but is an independent program. For simple things, like the Hello World Programs below, the server is not even used - after all, there is no audio for it to synthesize.

"Hello, World!"

The first program that one traditionally makes when learning a new programming language is called "The Hello World Program." This is a simple and trivial application that simply prints outs the phrase, "Hello, World!" (or any variation of it). It might seem useless at first, but the ability to provide feedback to an application's user is very important, and this is essentially what the Hello World Program does.

Here is the program in SuperCollider:

"Hello, World!".postln;

Here is an extension to that program:

"Hello, World!".postln;
"Hello, SC!".postln;

As with all examples in this Guide, you should paste these programs into GEdit, and execute them with SuperCollider. Look at the output produced by the programs, but don't worry about it for now.

These programs are very small, but it highlights some key concepts of the SuperCollider language, described below.

Return Values

Every SuperCollider program must provide the interpreter with a value (some information) when it has carried out all of its instructions. This value is called a "return value," because it is the value given by a program when it "returns" control to the interpreter. In a SuperCollider program, it is the last value stated in a program that automatically becomes the return value - no special command is required. When program execution ends, and control is returned to the SuperCollider interpreter, the interpreter outputs the return value in the "SuperCollider output" pane.

In the single-line Hello World Program above, the program produces the following output:

Hello, World!
Hello, World!

The program appears to have been executed twice, but that is not the case. The first "Hello, World!" is printed by the program. The second "Hello, World!" appears because "Hello, World!.postln is the last (in this case, the only) value of the program. It is "returned" by the program, and the interpreter prints it.

In the two-line Hello World Program above, the program produces the following output:

Hello, World!
Hello, SC!
Hello, SC!

This makes it more clear that the program is not being executed twice, and that it is the last value of a program that is returned to the interpreter.

Try executing the following single-line programs. Look at the output produced by each, and determine whether it is printed by the program itself, the interpreter, or both.

  • "Hello, World!".postln;
  • "Hello, World!";
  • 5.postln;
  • 5;

Can you modify the two-line Hello World Program so that each line is printed only once?

Note: In reality, every "function" must return a value. Functions are described later in this Guide; the difference is not yet important.

Statements

A "statement" is a single instruction, which is always ended with a semicolon. Exactly what constitutes a statement will become clear as you gain experience, and including semicolons will quickly become an automatic action.

In the Hello World Programs above, all of the statements contain the single instruction to post a line to the output screen. What happens when you remove the first semicolon, which marks the end of the first statement? The SuperCollider interpreter produces an unhelpful error message, and tells you that an error occurred after the forgotten semicolon. This is why it is important to always remember statement-concluding semicolons.

Data Types: Numbers and Strings

In many programming languages, it is the programmer's responsibility to determine the type of data that is being used, and how it should be stored. The SuperCollider interpreter takes advantage of the power of modern computers, and deals with this on our behalf. This greatly simplifies basic tasks, because there are only two kinds of data to worry about, and they make perfect sense:

  • Numbers: These are numbers, written simply as numbers. Anything that can be done with real-world numbers can also be done with SuperCollider's numbers. They can be as large or small, positive or negative as you want. They can have any number of digits on either side of the decimal point.
  • Strings: These are a string of characters, written between two double-quote characters like "this." The double-quote characters are required so that SuperCollider knows where to begin and end the string of characters. A string of character can contain as many characters as you like, including one character and no characters. If you want to include a double-quote character in a string, you should put a blackslash before it. The following is interpreted by SuperCollider as a string with only a double-quote character: "\""

Here are some examples of numbers and strings:

  • 5;
  • 18920982341;
  • 0.00000000000001;
  • "characters";
  • "@";
  • "";
  • "6";

Is the last example a number or a string? You and I recognize that it is a number inside a string, but SuperCollider will only treat it as a string. You can do string things with it, but you cannot do number things with it. You cannot add "6" to something, for example. Notice also that each example ends with a semicolon, which makes them complete statements. The statements don't do anything but represent themselves.

Try executing the following single-line programs. Think about why the SuperCollider interpreter produces the output that it does.

  • 6 + 3;
  • "6" + 3;
  • "six" + 3;

Simultaneous Execution

Complex SuperCollider programs contain many parts, which all do different things. Sometimes, executing all of these together doesn't make sense, and it can be difficult to know which portions of the program are supposed to be executed when. To help with this, the interpreter allows you to mark portions of your program between ( and ) so that you will know to execute them together.

Here is an example:

(
  "Hello, Fred!".postln;
  "Hello, Wilma!".postln;
)
(
  "Goodbye, Fred!".postln;
  "Goodbye, Wilma!".postln;
)

It doesn't make sense to say "hello" and "goodbye" at the same time, so separating these sections with parentheses will serve as a reminder. In case we try to execute all of the code at once, the SuperCollider interpreter will give us an error.

Variables and Functions

The concepts in this section are related to the mathematical terms with the same names. This is a modern-day result of the first uses of computers and programming languages: the calculation of complex mathematical problems.

Variables

A variable is a symbol that can be assigned an arbitrary value. A "symbol" is a series of alphabetic and numeric characters, separated by whitespace (a space, a line-break, or the end of the file). When a variable is "assigned" a value, the variable name (the symbol) is understood to be a substitute for the assigned value.

Consider a traffic light, which has three possible symbols: green, yellow, and red. When you are driving, and you encounter a traffic light, you might see that its red symbol is activated (the red light is illuminated). What you see is a red light, but you understand that it means you should stop your car. Red lights in general do not make you stop - it is specifically red traffic lights, because we know that it is a symbol meaning to stop.

SuperCollider's variables work in the same way: you tell the interpreter that you want to use a symbol, like cheese. Then you assign cheese a value, like 5. After that point, whenever you use cheese, the interpreter will automatically know that what you really mean is 5.

Run the following two programs. They should result in the same output.

(
  5 + 5;
)
(
  var cheese;
  cheese = 5;
  cheese + cheese;
)

In the first example, the program calculates the value of 5 + 5, which is 10, and returns that to the interpreter, which prints it out. In the second example, the program tells the interpreter that it wants to use a variable called cheese then it assigns cheese the value 5. Finally, the program calculates cheese + cheese, which it understands as meaning 5 + 5, and returns 10 to the interpreter, which prints it out.

This trivial use of a variable does nothing but complicate the process of adding 5 to itself. Soon you will see that variables can greatly simplify your programs.

Using Variables

There are three words that describe the key stages of using a variable: declaration, initialization, and assignment.

A variable must be declared before use, so that the interpreter knows that you want to use that symbol as a variable. All variables must be declared before any statement that does not declare a variable; in other words, you should declare your variables before doing anything else. Variable names are declared like this:

var variableName;

Variables can also be declared in lists, like this:

var variableOne, variableTwo;

Variables can be assigned a value at any time after they have been declared. Any single object can be assigned to a variable. If a variable is already assigned a value, any subsequent assignment will erase the previous assignment; the previously-assigned value will is not retrievable.

The first assignment to a variable is said to "initialize" the variable. Initialization is a special kind of assignment, because a variable cannot be used before it is initialized. If a program attempts to use an un-initialized variable, the SuperCollider interpreter will cause an error. For this reason, you should always initialize a variable when you declare it. There is a special way to do this:

var variableName = nil;

Since you can't always assign a useful value, you can pick an arbitrary one. Assigning "nil" is common practice, because it means "nothing," but without actually being nothing (this avoids some errors). Assigning zero is another possibility; it is standard practice in many programming languages, and will avoid most errors, even if the variable is eventually supposed to hold another kind of object. Intialization and declaration of multiple variables can also be done as a list:

var variableOne = 0, variableTwo = 0;

Single-letter variable names have a special purpose in SuperCollider. They are already declared, so you don't have to declare them. They are also already initialized to "nil", so you don't have to do that either. These variable names are intended to be used as a quick fix, while you're experimenting with how to make a program work. You should not use them in good-quality programs.

The single-letter variable "s" is automatically assigned to the server on the computer running the interpreter. You should avoid re-assigning that variable.

Variable names should always begin with a lower-case letter.

Use variables to write programs that do the following tasks:

  1. Perform arithmetic with an uninitialized variable. An error should appear when the program is executed.
  2. Calculate the value of y, if all other values are known, for the quadratic equation: y = a * x * x + b * x + c
  3. Re-write the Hello World Program so that it will say "Hello" to a name stored in a variable. Remember that you can use the interpreter to automatically output the last line of a function.

Functions

A Function is a statement, or a series of statements, that we want to use many times. When a Function is assigned to a variable, you can execute the Function as many times as you wish. Any statements that happen between braces { like this; } are treated as a Function. Functions are executed by passing them the "value" message, as in the following example.

Here is a Function that is not assigned to a variable, and is executed once.

{ "Hello, World!".postln; }.value;

Notice that there are two semicolons: one after the statement within the Function, and one after the "value" message that tells the Function to execute.

Here is a Function with identical function, assigned to a variable, and executed twice.

var myFunction = { "Hello, World!".postln; }; // note two semicolons
myFunction.value;
myFunction.value;

Function Arguments

The most useful aspect of Functions is that they can produce varying results, depending on their input. For whatever reason, the input accepted by a Function is called an "argument." SuperCollider's Functions can accept any number of arguments - zero, one, or many. Argument values (called "parameters") are provided to a Function by adding them in parentheses after the name of the Function, separated with commas, like this: exampleFunction( 5, 7, 9 ); Argument variables are declared as the first statement in a Function, like this: arg oneNumber, twoNumber;

This program is significantly more complicated than previous examples, but it shows how useful Functions can be. Notice how the braces in that example are on different lines than the rest of the Function, which gives us more space within the Function to complete some useful work.

(
   var greeter =
   {
      arg name;
      ( "Hello" + name ).postln;
   };
   
   greeter.value( "Samantha" );
   greeter.value( "Jermain" );
   nil;
)

Here is how the program works:

  1. A variable named greeter is declared, and assigned a Function.
  2. The Function contains an argument called name, and outputs "Hello" plus the name given to it.
  3. The parentheses here ( "Hello" + name ) ensure that the two strings are added together before the "postln" message prints them out.
  4. The greeter variable is used to call the Function with two different names.
  5. The nil; statement is optional, and does not affect the operation of the program. What it does is return a "nothing" value to the interpreter after program execution completes, so that the last message is not repeated.

Since every argument has a name, SuperCollider allows you to use that name when executing the Function. This example executes the greeter Function from the last example:

greeter.value( name:"Myung-Whun" );

This is more useful if there are many arguments, and you do not remember the order that they appear in the Function's definition.

SuperCollider also allows you to specify default values for arguments, so that they do not need to be specified. This allows optional customization of a Function's behaviour, and is therefore very powerful.

This example modifies the one above by adding default-value arguments, and by calling arguments with their name.

(
   var greeter =
   {
      arg name, greeting = "Hello";
      ( greeting + name ).postln;
   };
   
   greeter.value( "Samantha" );
   greeter.value( "Jermain", "Goodbye" );
   greeter.value( name:"Myung-Whun" );
   greeter.value( greeting:"Bienvenue", name:"Marcel" );
   nil;
)

Any value can be used as a parameter, as long as the Function expects it. In fact, even Functions can be used as parameters for Functions!

Function Return Values

All SuperCollider Functions return a value to the interpreter when they have finished execution. As with programs, the value returned is the value of the last statement in the Function. The return value of a Function can be captured, assigned to a variable, and used again later.

This example assigns the result of a Function to a variable.

(
   var mysticalMath =
   {
      arg input = 0;
      input * 23;
   };
   var someNumber = 9;
   
   someNumber = mysticalMath.value( someNumber );
   someNumber.postln;
   nil;
)

Here is how the program works:

  1. A Function and variable are created, and assigned values.
  2. This line someNumber = mysticalMath.value( someNumber ); executes the mysticalMath Function, which multiplies its argument by 23 and returns the value. Then, it assigns the return value of the Function to someNumber. In any statement that contains an assignment, the assignment is always done last. In other words, the Function in this example will always be given an argument of 9, and only after the Function completes execution and returns a value will that value be assigned to someNumber.
  3. The new value of someNumber is displayed.

The program could have been shortened like this:

(
   var mysticalMath =
   {
      arg input = 0;
      input * 23;
   };
   
   var someNumber = mysticalMath.value( 9 );
   someNumber.postln;
   nil;
)

It could have been shortened even more like this:

(
   var mysticalMath =
   {
      arg input = 0;
      input * 23;
   };
   
   mysticalMath.value( 9 ).postln;
   nil;
)

Experiment with the shortened versions of the program, ensuring that you know why they work.

Variable Scope

A variable is only valid within its "scope." A variable's scope is determined by where it is declared. It will always last between either ( and ) or { and }.


Sound-Making Functions

ArrayedCollections and Multichannel Audio

The Mixer??

How to Get Help

SynthDefs and Synths

Busses

Groups, Nodes, and Ordering

Buffers??

Scheduling and Clocks

Routines and Tasks

Patterns