Keith Hamel's Csound Course

Week 3

In this tutorial:


Index Next Week Previous Week


Arithmetic Operators

Like all computer languages, Csound includes arithmetic operators so that numerical values can be added, subtracted, multiplied and so on...


The most important operators are:

+     add
-     subtract
*     multiply     (N.B. NOT x)
/     divide

These operators are used in expressions with numbers (sometimes called constants) or variables (which are simply a storage locations for numerical values). An expression using these operators may appear anywhere that a simple numerical constant can appear (i.e. as an argument in a function).

We assume the variables (kenv and asig) have been defined in a previous line.

14 / 9
2000 + kenv
p3 - 1.0
asig * .5
p3 * .5

Parentheses ( and ) are used to control the order of computation in expressions. Without them, multiplication and division are performed before addition and subtraction, and similar operations are performed left-to-right.

6 * 4 + 5                 ; result is 29
(6 * 4) + 5               ; result is 29
6 * (4 + 5)               ; result is 54
((6 + (2 * 4)) / 7) - 1   ; result is 1

Whenever in doubt, use cautionary parentheses.

The Simple Assignment Function: =

The equal sign is the simplest function in Csound. It should NOT be understood as equals, but by the term gets or gets-the-value-of. When we write a statements such as:

ivar   =   2000;

we should read this as " ivar gets-the-value-of 2000" and not as "ivar equals 2000". The reason for this is that the equal sign constitutes an assignment statement; the value on the right is passed to the variable on the left -- 2000 is passed to the variable ivar. Assignment statements can be used to set the contents of any i-, k- or a- variable to any numerical value. Most often, assignment statements are used to set up i- variables (when the instrument is first called) or to modify the contents of an existing variable:

ivar   =   2000               ; ivar set to 2000
icps   =   cpspch(p5)         ; icps set to cps value of pitch
ivib   =   icps * .01         ; ivib (vibrato speed) is set to 1/100 of cps
kenv   linseg 1, p3, 0        ; ramp from 1 to 0 in duration p3
kenv   =   kenv * ivar        ; increase the amplitude of the envelope


goto top Index


GEN routines

The f1 0 512 10 1 statement that you have been writing in your scores is in fact a directive to the program to create (or Generate) a table of values which can be used by your orchestra. The values in the f- statement are:

function_num starting_time table_size GEN_type other_parameters...

Essentially, GEN routines are mathematical procedures which create useful tables. The table size varies depending on how the function will be used, but it normally is a power of 2 or a power of 2 plus 1. (For now we will use power-of-two tables).

Possible tables sizes are: 128 129 256 257 512 513 1024 1025 2048 2049 ...

There are a wide range of GEN-types that are available for a wide range of uses within Csound. At present, we are concerned mainly with GEN routines that can be used to produce useful audio waveforms (i.e. that deal with sine waves). The two types in this category are GEN-9 and GEN-10.

The GEN number appears as the 4th value in the f- statement).

GEN-10:

The parameters in Gen-10 (the values following the 10 in the f-statement) specify the relative strengths of harmonic partials. Normally, 1 is used as the largest value, and decimal values for weaker partials.

f1  0  256  10  1                           ; a sine wave
f2  0  256  10  1 0 .4 0 .2 0 .1 0 .05      ; odd partials in diminishing strength
f3  0  256  10  .1 .2 .3 .4 .5 .6 .7 .8 .9  ; all partials with increasing strength
f4  0  256  10  1 0 0 0 1 0 0 0 1 0 0 0 1   ; only partials 1, 5, 9 and 13

GEN-9:

The parameters in Gen-9 (the values following the 9 in the f-statement) are groups of 3 values which specify the partial, the strength and the phrase (in degrees). If you are using harmonic partials and normal phrase, use Gen-10, but if you want ot specify phase differences in the partials, or you want inharmonic paritals use Gen-9.

The f- statement f1 0 256 9 1 1 0 is identical to f1 0 256 10 1.

f1  0  256  9  1 1 90                ; a sine wave out of phase
f2  0  256  9  1 .5 0 2.2 .5 90      ; fundamental and inharmonic partial
f3  0  256  9  1 .5 0 2 .5 180       ; waveform with destuctive interference

GEN-7:

Another useful Gen-routine is Gen-7 which can be used to create tables of linear ramps. It is easy to specify square waves, triangle waves, sawtooth waves etc. with this function. The parameters consist of a value followed by the number of points in the table to the next value and so on. The total number of points must be equal to the table size.

f1  0  256  7  1 127 1 1 -1 127 -1 1 1     ; a square wave
f2  0  256  7  0 64 1 128 -1 64 1          ; a triangle wave
f3  0  256  7  1 256 0                     ; a sawtooth wave

Gen-5 is similar to Gen-7 except it uses exponential curves between points rather than straightlines.

goto top Index


line, expon, linseg, expseg

One of the most powerful controls in Csound are the line, expon, linseg and expseg
generators. Essentially they return values that are interpolated between fixed points in time. line and expon take as arguments a starting value, a duration, and a final value and produce values that would fall on a straight line (line) or exponential curve (expon) between the two values. linseg (not lineseg) and expseg take as arguments a starting value, and a series of duration and next value pairs. (The number of arguments is always odd since they must have both a starting and ending value.

The expon and expseg generators cannot have 0 as a value. Replace 0 with a very small number such as .0001

k1  line   1, p3, 0       ; moves linearly from 1 to 0 in the duration p3
k2  expon  1, p3, .0001   ; moves exponentially from 1 to (almost 0) in p3
k3  linseg 100, p3*.5, 0, p3*.5, 100     ; moves linearly from 100 to 0 and back to 100
k4  expseg 100, p3*.5, .0001, p3*.5, 100 ; moves exponentially from 100 to 0 and back to 100
k5  linseg 0, .25, 1, .25, .3, .5, .7, .5, .2, .75, .9, .75, .1 ; a complex linseg (3 seconds)


Using linseg and expseg in envelopes

Although there are many uses for these generators, an important one is as a control on the amplitude of an audio generator - in other words as an amplitude envelope. Although there are generators specially designed for generating envelopes, these routines are more flexible, and, I think, give better results. When linseg or expseg is used as amplitude envelope, the returned k- value is passed to the amplitude argument of the audio generating routine (i.e. oscil). For flexibily (and simplicity?) the maximum value of the envelope is set to 1.0, and the k- value is multiplied by the maximum amplitude (usually p4) later in the instrument (usually in the audio generator (i.e. oscil)). For example, the following fragments produce exactly the same results:

1.
kenv  linseg  0, .05, p4, p3-.05, 0        ; envelope with sharp attack
asig  oscil   kenv, cpspch(p5), 1          ; an oscilator outs asig, asig

2.
kenv  linseg  0, .05, 1, p3-.05, 0         ; envelope scaled to 1
kenv  =   kenv * p4                        ; envelope * max amplitude
asig  oscil   kenv, cpspch(p5), 1          ; an oscilator  
outs  asig, asig

3.
kenv  linseg  0, .05, 1, p3-.05, 0         ; envelope scaled to 1
asig  oscil   kenv * p4, cpspch(p5), 1     ; amp argument has envelope multiplied 
outs  asig, asig                           ; by max amplitude


Scaling the amplitude envelope to 1, allows the envelope to be used more easily for other controls (i.e. to alter some other component of the sound).

Normally, you will want your envelopes to take place over the complete duration of the sound, and thus they will usually involve p3 in the duration arguments. There are two common types of envelopes:

1) those in which p3 is divided into fractions and placed in the various duration arguments:

kenv   linseg   0, p3*.3, 1, p3*.5, .2, p3*.2, 0 
kenv2  linseg   0, p3/2, 1, p3/2, 0 

Notice that the entire duration of p3 is specified in both of the above.

In this type of envelope, the segments of time are all stretched and compressed uniformly as the duration (p3) is altered.

2) those in which values of time are placed in some of the duration arguments, and the remainder of the total duration in others:

kenv   linseg   0, .09, 1, .06, .6, p3-.15, 0

In this type, some durations (the attack and first decay in the above example) are fixed (at .09 and .06 seconds). The last segment is specified as the remaining duration of the sound ( p3 - .15 OR p3 - (.09 + .06) ). In this type, the first two segments will take the exact durations specified and the final decay will be adjusted for longer or shorter note durations. Generally, this type of envelope is a better instrumental envelope since the speed of the attack does not normally vary with the duration of the note.

Of course, an amplitude envelope is only one of the many uses for the line, expon, linseg and expseg generators. Their output can be used as a control on almost anything.

goto top Index


Using Oscil as an Audio Generator

We have already looked at using oscil as an audio generator -- it is one of the important building blocks of CSound. It takes three arguments (with an option 4th argument) to control its ampitude, frequency, and waveform (i.e. what wave table it uses). Normally, the frequency argument is passed from the score (often as a conversion of a from pch to cps representation with cpspch(p5) ) and the amplitude contains the maximum amplitude (passed from the score as p4) mulitplied by the envelope (which is a k- variable defined in a previous line). The waveform refers to the f- numbers defined in the score;

kenv  line   1, p3, 0                       ; envelope - ramp from 1 to 0
asig  oscil  p4 * kenv, cpspch(p5), 1       ; audio oscilator
outs  asig, asig 


goto top Index


Formatting and Documenting Your Code

It is very important to organize your files so that you can understand them when you come back to them later, and so that others can understand what you are doing. Your code will be easier to read if it is formated (with Tabs) so that all variables, function names, and arguments are vertically aligned.

variable function arguments.... comments

(TAB) kenv (TAB) linseg (TAB) 1, p3, 0          (TAB) ; a ramp from 1 to 0
(TAB) asig (TAB) oscil  (TAB) kenv *p4, p5, 1   (TAB) ; an oscilator

In the score file, a comment line should be inserted to list your parameters. This will become increasingly important as more parameters are used.

;i#   start   dur   amp     ptch   func
i1    0      .25    10000   9.00   1 

goto top Index


Suggested Assignment

Design the following instruments:

1) instrument 1 uses a single oscilator and has a envelope with an attack, initial decay, steady state and final decay. The longer the note as determined by p3 in the score, the longer the steady state should be.

2) instrument 2 is a percussive instrument to be used with a fixed duration. It uses a single oscilator with a waveform rich in harmonics. The instrument should be passed a parameter (or some parameters) from the score to control where it sounds in stereo space.

3) write a score (approx. 30 seconds) to demonstrate the two instruments. The score can be original or copied from an existing source.

Both orchestra and score should be fully documented (i.e. commented).


goto top Index Next Week Previous Week