Keith Hamel's Csound Course

Week 12

In this tutorial:


goto top Index Next Week Previous Week

Granular Synthesis

Granular Synthesis uses a large volume of small units of sound to create rich acoustic timbres. Although Csound does not have a granular synthesis generator, it is possible to implement a version of Granular Synthesis within the Csound environment. In most Granular Synthesis systems, a synthesizer generates the maximum grains possible and distributes them within a specified frequency field. The grains can be any small audio signal (sampled or otherwise) and the the resultant frequencies are created by the rate of repetition of the grains, not by the frequency of the sound within the grain. To produce granular synthesis correctly, we would need a simple instrument which generates a pulse of sound and a massively large score (controlling the proximity of grains). This is not practical within Csound, so we simulate the granular effect by designing an instrument which generates multiple grains at a fixed (or variable) frequency. To begin with, we need a small grain of sound (sound followed by silence) which can be read by the instrument. The easiest way to create a grain in Csound is with a function table. A simple grain could be created with a GEN-7 function table such as:

f1  0  1024  7  0 16 1 224 1 16 0 16 -1 224 -1 16 0 512 0
This is almost a square wave for half the table length, the second half remains at 0. We can use this table simply as an oscillating pulse, and read through the table at a specified rate.

instr 1
kenv    linseg  0, p3/2, p4, p3/2, 0     ; up-down envelope 
aindex  phasor  cpspch(p5)               ; read table at pitch rate
asig    table   aindex*1024, 1           ; index table
outs    asig*kenv, asig*kenv             ; output signal
endin

If a wider band of grains is desired, a random function can be used to vary the rate at which the table will be read:

instr 1
kenv    linseg  0, p3/2, p4, p3/2, 0     ; up-down envelope 
krand   randi   cpspch(p5)*.03, kr       ; a band of frequencies
aindex  phasor  cpspch(p5) + krand       ; read table at pitch rate
asig    table   aindex*1024, 1;          ; index table
outs    asig*kenv, asig*kenv             ; output signal
endin

Glissing and other effects can be added:

instr 1
ist    =   cpspch(p5)                    ; start pitch
iend   =   cpspch(p5+1.00)               ; end pitch
kpitch line   ist, p3, iend              ; gliss from start to end
kenv   linseg 0, p3/2, p4, p3/2, 0       ; up-down envelope 
krand  randi  kpitch*.03, kr             ; a band of frequencies
aindex phasor kpitch+krand               ; read table at pitch rate
asig   table  aindex*1024, 1             ; index table
outs   asig*kenv, asig*kenv              ; output signal
endin

In order to create a better granular effect, we may want to call several (or many) copies of the instrument from the score with slightly different starting times and slightly different frequencies. Likewise, we could simulate a band of sound within the instrument, by having it read the table many times at slightly different rates:

aindex1   phasor  kpitch
aindex2   phasor  kpitch+2
aindex3   phasor  kpitch-2
aindex4   phasor  kpitch+5
aindex5   phasor  kpitch-5
asig1     table   aindex1*1024, 1;
asig2     table   aindex2*1024, 1;
asig3     table   aindex3*1024, 1;
asig4     table   aindex4*1024, 1;
asig5     table   aindex5*1024, 1;
asig   =   (asig1+asig2+asig3+asig4+asig5)*.2

goto top Index


Creating grains with sampled sounds

Rich and wonderful timbres can result if you use samples as the audio source for your grains. The easiest way to do this is to bring a sample into Csound via GEN-1. In order for this to work correctly, you must have a sample that will fit into about half your table - (the remainder will be filled with zeros.) Try using a table of 1024 - this will give you several cycles of a normal pitched acoustic sound. (as before, the sample should be carefully edited with SoundEdit16 and saved as a 16-bit mono file at sampling rate: 22050). It is important that there be some blank space in your table (i.e. zeros) otherwise some of the granular quality will be lost.

An instrument reading GEN-1 for granular syntheis will look something like:

f2   0   1024   -1  1  0  4             ; reads soundin.1
; N.B. kenv is scaled to 1 since samples are read with raw data instr 2
kenv   line   0, p3/2, 1, p3/2, 0       ; up-down envelope
aindex phasor cpspch(p5)                ; read table at pitch rate
asig   table  aindex*1024, 2            ; index table f2
outs   asig*kenv, asig*kenv             ; output signal
endin
The sound works best in lower frequencies - as frequencies get higher, the output will become increasingly noisy. For high sounds, it is better to use a simple waveform rather than a sampled source.

Feel free to experiment with different sources. You can either create function tables directly, record sounds with SoundEdit16, or create audio with CSound and then edit the sounds with SoundEdit18 to create the GEN-1 tables.


goto top Index Next Week Previous Week