by Barry Vercoe, Massachusetts Institute of Technology
Csound runs from two basic files: an orchestra file and a score file. The orchestra file is a set of instruments that tell the computer how to synthesize sound; the score file tells the computer when. An instrument is a collection of modular statements which either generate or modify a signal; signals are represented by symbols, which can be "patched" from one module to another. For example, the following two statements will generate a 440 Hz sine tone and send it to an output channel:
asig oscil 10000, 440, 1 out asig
The first line sets up an oscillator whose controlling inputs are an amplitude of 10000, a frequency of 440 Hz, and a waveform number, and whose output is the audio signal asig. The second line takes the signal asig and sends it to an (implicit) output channel. The two may be encased in another pair of statements that identify the instrument as a whole:
instr 1 asig oscil 10000, 440, 1 out asig endin
In general, an orchestra statement in Csound consists of an action symbol followed by a set of input variables and preceded by a result symbol. Its action is to process the inputs and deposit the result where told. The meaning of the input variables depends on the action requested. The 10000 above is interpreted as an amplitude value because it occupies the first input slot of an oscil unit; 440 signifies a frequency in Hertz because that is how an oscil unit interprets its second input argument; the waveform number is taken to point indirectly to a stored function table, and before we invoke this instrument in a score we must fill function table #1 with some waveform.
The output of Csound computation is not a real audio signal, but a stream of numbers which describe such a signal. When written onto a sound file these can later be converted to sound by an independent program; for now, we will think of variables such as asig as tangible audio signals.
Let us now add some extra features to this instrument. First, we will allow the pitch of the tone to be defined as a parameter in the score. Score parameters can be represented by orchestra variables which take on their different values on successive notes. These variables are named sequentially: p1, p2, p3, ... The first three have a fixed meaning (see the Score File), while the remainder are assignable by the user. Those of significance here are:
p3 - duration of the current note (always in seconds).
p5 - pitch of the current note (in units agreed upon by score and orchestra).
Thus in
asig oscil 10000, p5, 1
the oscillator will take its pitch (presumably in cps) from score parameter 5.
If the score had forwarded pitch values in units other than cycles-per-second (Hertz), then these must first be converted. One convenient score encoding, for instance, combines pitch class representation (00 for C, 01 for C#, 02 for D, ... 11 for B) with octave representation (8. for middle C, 9. for the C above, etc.) to give pitch values such as 8.00, 9.03, 7.11. The expression
cpspch(8.09)
will convert the pitch A (above middle C) to its cps equivalent (440 Hz). Likewise, the expression
cpspch(p5)
will first read a value from p5, then convert it from octave.pitch-class units to cps. This expression could be imbedded in our orchestra statement as
asig oscil 10000, cpspch(p5), 1
to give the score-controlled frequency we sought.
Next, suppose we want to shape the amplitude of our tone with a linear rise from 0 to 10000. This can be done with a new orchestra statement
amp line 0, p3, 10000
Here, amp will take on values that move from 0 to 10000 over time p3 (the duration of the note in seconds). The instrument will then become
instr 1 amp line 0, p3, 10000 asig oscil amp, cpspch(p5), 1 out asig endin
The signal amp is not something we would expect to listen to directly. It is really a variable whose purpose is to control the amplitude of the audio oscillator. Although audio output requires fine resolution in time for good fidelity, a controlling signal often does not need that much resolution. We could use another kind of signal for this amplitude control
kamp line 0, p3, 10000
in which the result is a new kind of signal kamp. Signal names up to this point have always begun with the letter a (signifying an audio signal); this one begins with k (for control). Control signals are identical to audio signals, differing only in their resolution in time. A control signal changes its value less often than an audio signal, and is thus faster to generate. Using one of these, our instrument would then become
instr 1 kamp line 0, p3, 10000 asig oscil kamp, cpspch(p5), 1 out asig endin
This would likely be indistinguishable in sound from the first version, but would run a little faster. In general, instruments take constants and parameter values, and use calculations and signal processing to move first towards the generation of control signals, then finally audio signals. Remembering this flow will help you write efficient instruments with faster execution times.
We are now ready to create our first orchestra file. Type in the following orchestra using the system editor, and name it "intro.orc".
sr = 20000 ; audio sampling rate is 20 kHz kr = 500 ; control rate is 500 Hz ksmps = 40 ; number of samples in a control period (sr/kr) nchnls = 1 ; number of channels of audio output instr 1 kctrl line 0, p3, 10000 ; amplitude envelope asig oscil kctrl, cpspch(p5), 1 ; audio oscillator out asig ; send signal to channel 1 endin
It is seen that comments may follow a semi-colon, and extend to the end of a line. There can also be blank lines, or lines with just a comment. Once you have saved your orchestra file on disk, we can next consider the score file that will drive it.