Main Index
Tutorials Index

PART 3
Signal Processing:

Envelopes
Chorusing
Freq Mod
Ring Mod
Buzz

PART 1
Origins of Csound

PART 2
Simple Guide to Csound


CDP Logo

~ GETTING STARTED WITH CSOUND ~
by Andy Hunt

PART 3 – Signal Processing

In Section 2 we studied the 'OSCIL' unit generator. This was created in an orchestra file. We then made several different score files to use this orchestra to do additive synthesis, create beat frequencies and complex frequencies.

We shall now turn our attention to some common signal processing techniques:

  • A – Amplitude Envelopes – the 'ADSR' shapes found on synthesisers
  • B – Chorusing – a means of enriching a sound
  • C – Frequency Modulation – the basis of the Yamaha synthesis technique (FM)
  • D – Ring Modulation – multiplying two oscillators to distort the harmonic ratios
  • E – Buzz – generating partials using a 'complex oscil' unit generator


A – Amplitude Envelopes

We are probably familiar with the enveloping functions on many synthesisers: Attack-Decay-Sustain-Release (ADSR):

  • Attack – the time from the start to the peak of a sound;
  • Decay  – the loss of volume from the initial peak.
    The speed at which this happens very much influences the sound. For example, a quick decay after a fast attack can result in a bell-like sound, but if this decay is slowed down, the bell-like effect is gradually lost.
  • Sustain – the continuation level of the sound until the key is released;
  • Release – the speed at which the sound dies away after the key has been released.

The following diagram summarises this:

The Csound signal processing unit LINEN models this process in software. This is a three-part time-based amplitude envelope, in which the:

  • the attack period is called 'rise time',
  • the 'decay time' comes last and takes the amplitude back down to 0. 'Release time' is not meaningful in this context because there isn't anything to release. (Csound isn't associated with key presses in the same way as synthesizers are.)
  • the sustain period is what is left after subtracting the rise time and the decay time from the total duration; the 'amplitude' is the level reached during the sustain period. The program calculates this.

The following diagram illustrates the data flow of the LINEN generator:

The following is an orchestra which uses LINEN:

;toot3.orc
sr     =  22050
kr     =   1470
ksmps  =     15
nchnls =      1
instr 3

;output generator ampl rise dur decay
k1      linen     p4,  p6,  p3, p7
a1      oscil     k1,  p5,  1
out    a1
endin

The following is a score to provide some notes and other data for this orchestra:


;toot3.sc

f1  0  4096  10  1	;sine wave made with GEN10

;p1    p2    p3   p4     p5      p6     p7
;instr start dur  ampl   freq    rise   decay
i3     0     1    10000  440     .5     .7
i3     1.5   1    10000  440     .9     .1
i3     3     1    5000   880     .02    .99
i3     4.5   1    5000   880     .7     .01
i3     6     2    20000  220     .5     .5
e

OK – this gives us the general idea, but too many different parameters are changing at once. Try the following score, which keeps all the parameters the same except 'rise' (which gets shorter) for the first 7 notes, then holds that steady while 'decay' starts to get longer for the next 7 notes. The procedure here is important. It's 'scientific method' procedure, where one tries to keep all the variables the same except one, so that one can clearly observe what happens when that one variable alters.


;toot3.sc - alternative version no.1

f1  0  4096  10  1

;p1    p2    p3   p4     p5    p6   p7
;instr start dur  ampl   freq  rise decay
i3     0     1.5  10000  440   .9   .7
i3     2     1.5  10000  440   .7   .7
i3     4     1.5  10000  440   .5   .7
i3     6     1.5  10000  440   .3   .7
i3     8     1.5  10000  440   .15  .7
i3     10    1.5  10000  440   .04  .7
i3     12    1.5  10000  440   .02  .7
i3     14    1.5  10000  440   .02  .02
i3     16    1.5  10000  440   .02  .1
i3     18    1.5  10000  440   .02  .3
i3     20    1.5  10000  440   .02  .6
i3     22    1.5  10000  440   .02  .8
i3     24    1.5  10000  440   .02  1.0
i3     26    1.5  10000  440   .02  1.5
i3     28    1.5  10000  440   .02  2.0
e

The next version illustrates psycho-acoustic phenomena associated with the attack ('rise') period of a sound. As the attack gets shorter and shorter the whole character of the sound alters, sounding like breath, or a 'tut', or a click, with areas of overlap. See if you agree with the designations in comments.


;toot3.sc - alternative version 2

f1  0  4096  10 1

;p1    p2    p3   p4    p5    p6     p7
;instr start dur  ampl  freq  rise   decay  perception
i3   0     1.5  10000   440   .9     .5     ;long
i3   2     1.5  10000   440   .7     .5     ;long
i3   4     1.5  10000   440   .5     .5     ;long
i3   6     1.5  10000   440   .3     .5     ;long
i3   8     1.5  10000   440   .15    .5     ;long/short
i3   10    1.5  10000   440   .07    .5     ;long/short
i3   12    1.5  10000   440   .04    .5     ;short
i3   14    1.5  10000   440   .02    .5     ;short/breath
i3   16    1.5  10000   440   .015   .5     ;breath
i3   18    1.5  10000   440   .01    .5     ;breath
i3   20    1.5  10000   440   .005   .5     ;breath/'tut'
i3   22    1.5  10000   440   .004   .5     ;'tut'
i3   24    1.5  10000   440   .003   .5     ;'tut'
i3   26    1.5  10000   440   .002   .5     ;'tut'/spit
i3   28    1.5  10000   440   .001   .5     ;click
i3   30    1.5  10000   440   .0005  .5     ;click
e

B – Chorusing

This is a technique by which the sound of a note or chord is enriched and made to sound fuller. It is actually done by creating beat frequencies, that is, by making several copies of the note at slightly different frequencies.

In Part 2, we did this by creating a score which had separate but simultaneous notes, each on a different frequency. We are now going to create beats in the orchestra itself. This means that every note of the score which uses this orchestra will have beats.

The schematic diagram of an orchestra which does this looks like this:

This diagram shows that the orchestra has three simultaneous oscillators, each one tuned slightly differently. The one in the middle is the unchanged frequency; the one on the left tunes down slightly by multiplying the input frequency by 0.99, and the one on the right tunes up slightly by multiplying the input frequency by 1.01.

The orchestra text file looks like this:


;chorus.orc
sr =   22050
kr =    1470
ksmps =   15
nchnls =   1

instr 4

inote = cpspch(p5)               ;convert octave.00 pitch notation to cps
k1  linen  10000,  p6,  p3,  p7  ;envelope shape each note
a1  oscil  k1,  inote * .99, 1	 ;pitch detuned down slightly
a2  oscil  k1,  inote * 1.01, 1  ;pitch detuned up slightly
a3  oscil  k1,  inote, 1         ;pitch unchanged
a1  = (a1+a2+a3)		 ;combine the 3 pitch variants
    out  a1
endin

In case of amplitude overload, the line which sums the outputs could be divided by 3: a1 = (a1+a2+a3)/3


Csound Pitch Notation

In the octave.00 pitch notation, the 'octave' means which octave (middle C is octave 8); the '.00' notations are semitones between the octaves, from 0 (.00 = C) to 11 (.11 = B-natural).

This chart will help orientate you:

Csound pitch

MIDI note

Freq

8.09

69

440 Hz

3.00

0

8 Hz

12.09

127

7040 Hz

1.00

-

2 Hz

0.00

-

1 Hz

The sound is enriched by the combination of the original pitch with the versions detuned above and below. It is possible for the amplitude to get out of hand when combining pitches like this, so it would be wise to add something to the orchestra to handle this:

iamp = ampdb(p4) ;get amp from p4 and convert decibel notation to linear amplitude

iscale = iamp*.333 ;pre-divide (multiply *.333) each by a third so that when added together they do not exceed the maximum value

The resulting changing amplitude value, 'iscale', is placed in the LINEN generator in place of a fixed amplitude value. Thus, instead of a single fixed amplitude value there is a changing set of values comprising the rise and fall of the envelope shape. Try to think about this for a moment and actually picture the whole envelope shape in place of the single value. Understanding how and where you can position whole shapes in place of single values is one of the keys to opening up the potential of Csound.


Csound Rates of Operation

The i of 'iamp', 'iscale' and 'inote' means 'initialisation'. This means that Csound will do this operation at the beginning of each note of the score so that it will take on a single value. This is a good place to mention that Csound has three 'rates'. The other two are audio a and control k. In the audio rate, there is a value for every sample of sound. In the control rate, there is one value for a whole group of sound samples ksmps. A number of operations, such as envelopes, work perfectly well at this slower rate, and therefore save memory and processing time. Look back at the orchestras we've met so far and notice how some variables begin with the letter a (meaning 'audio rate') and others with k (meaning 'control rate').

When we create the score for this orchestra, there is another way that we can enrich the sound, and that is by enriching the partials of the sine wave generator. Up until now, we have only used the fundamental, thereby creating the purest of sine waves:

f1 0 4096 10 1

But GEN10 also allows us to set the harmonics, giving them an amplitude value relative to 1. So the next version of our score does this, giving the first harmonic a value of .1 and the second harmonic a value of .025. The first harmonic is an octave above the fundamental, and the second harmonic is a fifth above that (in line with the harmonic series):

f1 0 4096 1 .1 .025

One could take this process further, and also experiment with changing the weighting, making certain harmonics stronger and others weaker (in amplitude).

The score that follows plays a series of separate notes and then a series of chords. Note how the chorusing effect becomes richer with the chords.


;chorus2.sc 

f1  0  4096  10  1  .1  .025  ;sine wave with 3 partials

;p1    p2    p3   p4    p5    p6     p7 
;instr start dur  ampl  freq  attack release
i4     0     1    75    8.04  .1     .7
i4     1     1    70    8.02  .07    .6
i4     2     1    75    8.00  .05    .5
i4     3     1    70    8.02  .05    .4
i4     4     1    85    8.04  .1     .5
i4     5     1    80    8.04  .05    .5
i4     6     1    85    8.04  .03    .9
;chords begin here
i4     8     3    70    8.04  .03    .5
i4     8     3    72    8.00  .04    .5 

i4     11    3    70    8.07  .03    .5
i4     11    3    72    8.04  .04    .5

i4     14    4    73    8.09  .03    .5
i4     14    4    72    8.05  .04    .5
i4     14    4    74    8.00  .05    .5

i4     18    4    73    8.07  .03    .5
i4     18.1  4    72    8.04  .04    .5
i4     18.2  4    74    8.00  .05    .5
e


C – Frequency Modulation

Frequency Modulation ('FM') has proven to be a very effective method of enriching sound: it achieves remarkably complex results in a very simple way, though the predictability factor is not very high: small changes can result in dramatic, unexpected results.

Frequency modulation is a form of non-linear (ie irregular) audio distortion at higher frequencies and amplitudes. We are familiar with instrumental vibrato at low frequencies and amplitudes: a pitch wavers slightly up and down a few times a second. The perceived pitch is the relatively steady part of what we hear and is called, in this context, the 'carrier': because it 'carries' the slower, wavering component. The latter is called the 'modulator'.

First, a generic flow diagram for frequency modulation:

The orchestra for frequency modulation, really a simple vibrato instrument, is correspondingly straightforward:


;fm1.orc
sr  = 22050
kr   =  1470
ksmps = 15
nchnls =  1

instr 1
avib  oscil  p7, p6, 1		;p7 = modulation vibrato depth
		;p6 = modulation vibrato rate
aout  oscil  p4, p5 + avib, 1	;p4 = note amplitude ('carrier' volume) 
		;p5 = note frequency ('carrier' pitch)
         out    aout
endin

If we revise what the components of the oscil generator are, we can see what's happening here. The three fields are amplitude, frequency and wavetable. We create the vibrato oscillation when we make 'avib', giving separate pfields in the score to hold the amplitude and frequency information. This is the modulator. We have to apply this to (combine this with) the carrier. This we do simply by adding it to the frequency field of the carrier. Thus the faster wave of the carrier has added to it the slower amplitude-frequency pattern of the modulator, and the modulator movement is heard to wobble the steadier carrier wave.

And now the score, using a simple sine wave, changing one parameter only in each group of notes:


;fm1.sc

f1 0 4096 10 1

;first, gradually increase the vibrato depth

;p1    p2    p3   p4     p5     p6       p7
;instr start dur  ampl   freq	vib.frq  vib.amp
i1      0    4    10000  440    5        0
i1      5    4    10000  440    5        3
i1     10    4    10000  440    5        6
i1     15    4    10000  440    5        10
i1     20    4    10000  440    5        15
;now hold vibrato depth steady and increase vibrato rate
i1     25    4    10000  440    2        4
i1     30    4    10000  440    5        4
i1     35    4    10000  440    7        4
i1     40    4    10000  440    12       4
i1     45    4    10000  440    20       4
i1     50    4    10000  440    100      4
;now we can seriously incease the modulation depth
i1     55    4    10000  440    100      10
i1     60    4    10000  440    100      50
i1     65    4    10000  440    100      100
i1     70    4    10000  440    100      500
i1     75    4    10000  440    100      1000
i1     80    4    10000  440    100      5000
;finally, we'll change the modulation frequency slightly
i1     85    4    10000  440    100      500
i1     90    4    10000  440    105      500
i1     95    4    10000  440    110      500
i1    100    4    10000  440    120      500
e

You must listen to this score – and think about the parameters – while you listen to the sound output.

It is clear, then, that we have with Csound complete and precise software control over the making of frequency modulation effects.

D – Ring Modulation

Yet another method by which we can enrich the sound is ring modulation. This was a familiar feature of many of the early analog synthesizers. It is achieved by a very simple process of multiplying together the output of two different oscillators; this distorts the harmonic ratios by creating sum & difference tones. (As waves can be expressed as sine functions, multiplying two waves means multiplying two sine functions. By the laws of trigonometry, this will involve the sum and difference of the two.)

This is expressed in a schematic way in the following flow diagram:

We can think about what happens by considering the graphs. When the two waves are multiplied together, a more complex pattern of partials emerges. The following orchestra and score illustrates ring modulation:


;rm1.orc - simple ring modulation instrument
sr  =    22050
kr  =     1470
ksmps =     15
nchnls =     1

;multiplication instrument

instr 1
a1  oscil  p6, p7, 1
a2  oscil  p4, p5, 1
      out    a1 * a2	;NB  * not +
endin

;simple oscillator for comparison
instr 2
a3  oscil  p4, p5, 1
      out    a3
endin

In the score below, note that the duration of the first event is 6 seconds; the second event comes in after three seconds, so they overlap, thus combining the sound of the two events; both are produced with the simple oscillator defined as instr 2. This is not ring modulation, but is here so that we can compare the two tones sounding together, i.e., added, and two tones multiplied together. After the initial 6 seconds, and we then hear the ring modulation effect for four seconds.

The s in the score is a section divider, used so that we can start each section at time 0.

The value given for amplitude2 in p6 is very low. The reason for this is that when a1 is multiplied by a2, the amplitudes are also multiplied (p6 * p4) resulting in the more normal value of 20000. We could have used equal amplitudes and then scaled the output as illustrated in the section on Chorusing.


;rm1.sc

f1 0 4096 10 1  ;sine wave

;p1    p2    p3   p4    p5    p6    p7
;instr start dur  amp   freq  amp2  freq2   ;comments
i2     0     6    2000  440                 ;tone 1
i2     3     3    2000  163                 ;tone 1+tone2
i1     6     4    2000  440   10    163     ;tone 1*tone2
s
i2     0     6    2000  440                 ;tone 1
i2     3     3    2000  420                 ;tone 1+tone2
i1     6     4    2000  440   10    420     ;tone 1*tone2
s
i2     0     6    2000  440                 ;tone 1
i2     3     3    2000  20                  ;tone 1+tone2
i1     6     4    2000  440   10    20      ;tone 1*tone2
s
i2     0     6    2000  440                 ;tone 1
i2     3     3    2000  881                 ;tone 1+tone2
i1     6     4    2000  440   10    881     ;tone 1*tone2
s
i2     0     6    2000  440                 ;tone 1
i2     3     3    2000  1000                ;tone 1+tone2
i1     6     4    2000  440   10    1000    ;tone 1*tone2
s
i2     0     6    2000  440                 ;tone 1
i2     3     3    2000  3864                ;tone 1+tone2
i1     6     4    2000  440   10    3864    ;tone 1*tone2
e


E – Buzz

The Buzz unit generator automatically produces N partials – i.e., as many as you want: whatever value you enter for N. Thus you can produce quite a complex sound with one line of code. The example given here illustrates what happens as the number of partials is increased. The buzz orchestra is so amazingly simple that it's a very useful unit generator to explore, especially as the results are often rich enough to provide some good material.


;buzz1.orc - buzz orchestra

sr =   22050
kr =    1470
ksmps =   15
nchnls =   1

instr 1
k1  linen  p4, p6, p3, p7	;envelope
a1  buzz   k1, p5, p8, 1	;oscillator – p8 is N partials
      out    a1
endin

Buzz is therefore using a constant amplitude shape k1 as defined by linen (ampl-p4, attack-p6, duration-p3, decay-p7). The next parameter is pitch (p5) which in our score remains constant, then the number of partials (p8), which steadily increases in the score, and finally wavetable 1, again using only a simple sine wave.

In the score, note the use of dots as a way of repeating the parameter data. Also note that the frequency selected is very low. This brings more of the higher partials into a readily audible range, thus making the buzz effect more noticeable.


;buzz1.sc - buzz score

f1  0  8192  10  1	;note the larger table

;p1    p2    p3   p4    p5    p6    p7     p8
;instr start dur  ampl  freq  rise  decay  partials
i1     0     2    30000 40    .1    .1     5
i1     3     .    .     .      .     .     6
i1     6     .    .     .      .     .     7
i1     9     .    .     .      .     .     8
i1     12    .    .     .      .     .     10
i1     15    .    .     .      .     .     15
i1     18    .    .     .      .     .     20
i1     21    .    .     .      .     .     40
i1     24    .    .     .      .     .     80
e


Summary

It would be wonderful to go through all the unit generators of Csound in this way, but hopefully this will be sufficient to provide a good start on using this powerful tool. The next step could be to select another unit generator and explore it in a similar way. After that you could work through the Csound Tutorial by Richard Boulanger in the new Csound Reference Manual (now located here [R.F.]).

The Csound Book and The Csound Catalogue (ed. R. Boulanger) are also now available. These are absolute goldmines of information about all aspects of Csound.

© 1993 Andy Hunt, York, N. Yorks., England

Last Updated Jan. 2016 -- HTML5 version
Revisions: Robert Fraser