Granular synthesis is a technique in which a source sound or waveform is broken into many fragments, often of very short duration, which are then restructured and rearranged according to various patterning and indeterminacy functions.
If we imagine the simplest possible granular synthesis algorithm in which a precise fragment of sound is repeated with regularity, there are two principle attributes of this process that we are most concerned with. Firstly the duration of each sound grain is significant: if the grain duration if very small, typically less than 0.02 seconds, then less of the characteristics of the source sound will be evident. If the grain duration is greater than 0.02 then more of the character of the source sound or waveform will be evident. Secondly the rate at which grains are generated will be significant: if grain generation is below 20 hertz, i.e. less than 20 grains per second, then the stream of grains will be perceived as a rhythmic pulsation; if rate of grain generation increases beyond 20 Hz then individual grains will be harder to distinguish and instead we will begin to perceive a buzzing tone, the fundamental of which will correspond to the frequency of grain generation. Any pitch contained within the source material is not normally perceived as the fundamental of the tone whenever grain generation is periodic, instead the pitch of the source material or waveform will be perceived as a resonance peak (sometimes referred to as a formant); therefore transposition of the source material will result in the shifting of this resonance peak.
The following example exemplifies the concepts discussed above. None of Csound's built-in granular synthesis opcodes are used, instead schedkwhen in instrument 1 is used to precisely control the triggering of grains in instrument 2. Three notes in instrument 1 are called from the score one after the other which in turn generate three streams of grains in instrument 2. The first note demonstrates the transition from pulsation to the perception of a tone as the rate of grain generation extends beyond 20 Hz. The second note demonstrates the loss of influence of the source material as the grain duration is reduced below 0.02 seconds. The third note demonstrates how shifting the pitch of the source material for the grains results in the shifting of a resonance peak in the output tone. In each case information regarding rate of grain generation, duration and fundamental (source material pitch) is output to the terminal every 1/2 second so that the user can observe the changing parameters.
It should also be noted how the amplitude of each grain is enveloped in instrument 2. If grains were left unenveloped they would likely produce clicks on account of discontinuities in the waveform produced at the beginning and ending of each grain.
Granular synthesis in which grain generation occurs with perceivable periodicity is referred to as synchronous granular synthesis. granular synthesis in which this periodicity is not evident is referred to as asynchronous granular synthesis.
<CsoundSynthesizer>
<CsOptions>
-odac -m0
</CsOptions>
<CsInstruments>
;Example by Iain McCurdy
sr = 44100
ksmps = 1
nchnls = 1
0dbfs = 1
giSine ftgen 0,0,4096,10,1
instr 1
kRate expon p4,p3,p5 ; rate of grain generation
kTrig metro kRate ; a trigger to generate grains
kDur expon p6,p3,p7 ; grain duration
kForm expon p8,p3,p9 ; formant (spectral centroid)
; p1 p2 p3 p4
schedkwhen kTrig,0,0,2, 0, kDur,kForm ;trigger a note(grain) in instr 2
;print data to terminal every 1/2 second
printks "Rate:%5.2F Dur:%5.2F Formant:%5.2F%n", 0.5, kRate , kDur, kForm
endin
instr 2
iForm = p4
aEnv linseg 0,0.005,0.2,p3-0.01,0.2,0.005,0
aSig poscil aEnv, iForm, giSine
out aSig
endin
</CsInstruments>
<CsScore>
;p4 = rate begin
;p5 = rate end
;p6 = duration begin
;p7 = duration end
;p8 = formant begin
;p9 = formant end
; p1 p2 p3 p4 p5 p6 p7 p8 p9
i 1 0 30 1 100 0.02 0.02 400 400 ;demo of grain generation rate
i 1 31 10 10 10 0.4 0.01 400 400 ;demo of grain size
i 1 42 20 50 50 0.02 0.02 100 5000 ;demo of changing formant
e
</CsScore>
</CsoundSynthesizer>
The principles outlined in the previous example can be extended to imitate vowel sounds produced by the human voice. This type of granular synthesis is referred to as FOF (fonction d'onde formatique) synthesis and is based on work by Xavier Rodet on his CHANT program at IRCAM. Typically five synchronous granular synthesis streams will be used to create five different resonant peaks in a fundamental tone in order to imitate different vowel sounds expressible by the human voice. The most crucial element in defining a vowel imitation is the degree to which the source material within each of the five grain streams is transposed. Bandwidth (essentially grain duration) and intensity (loudness) of each grain stream are also important indicators in defining the resultant sound.
Csound has a number of opcodes that make working with FOF synthesis easier. We will be using fof.
Information regarding frequency, bandwidth and intensity values that will produce various vowel sounds for different voice types can be found in the appendix of the Csound manual here. These values are stored in function tables in the FOF synthesis example. GEN07, which produces linear break point envelopes, is chosen as we will then be able to morph continuously between vowels.
<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;example by Iain McCurdy
sr = 44100
ksmps = 16
nchnls = 2
0dbfs = 1
;FUNCTION TABLES STORING DATA FOR VARIOUS VOICE FORMANTS
;BASS
giBF1 ftgen 0, 0, -5, -2, 600, 400, 250, 400, 350
giBF2 ftgen 0, 0, -5, -2, 1040, 1620, 1750, 750, 600
giBF3 ftgen 0, 0, -5, -2, 2250, 2400, 2600, 2400, 2400
giBF4 ftgen 0, 0, -5, -2, 2450, 2800, 3050, 2600, 2675
giBF5 ftgen 0, 0, -5, -2, 2750, 3100, 3340, 2900, 2950
giBDb1 ftgen 0, 0, -5, -2, 0, 0, 0, 0, 0
giBDb2 ftgen 0, 0, -5, -2, -7, -12, -30, -11, -20
giBDb3 ftgen 0, 0, -5, -2, -9, -9, -16, -21, -32
giBDb4 ftgen 0, 0, -5, -2, -9, -12, -22, -20, -28
giBDb5 ftgen 0, 0, -5, -2, -20, -18, -28, -40, -36
giBBW1 ftgen 0, 0, -5, -2, 60, 40, 60, 40, 40
giBBW2 ftgen 0, 0, -5, -2, 70, 80, 90, 80, 80
giBBW3 ftgen 0, 0, -5, -2, 110, 100, 100, 100, 100
giBBW4 ftgen 0, 0, -5, -2, 120, 120, 120, 120, 120
giBBW5 ftgen 0, 0, -5, -2, 130, 120, 120, 120, 120
;TENOR
giTF1 ftgen 0, 0, -5, -2, 650, 400, 290, 400, 350
giTF2 ftgen 0, 0, -5, -2, 1080, 1700, 1870, 800, 600
giTF3 ftgen 0, 0, -5, -2, 2650, 2600, 2800, 2600, 2700
giTF4 ftgen 0, 0, -5, -2, 2900, 3200, 3250, 2800, 2900
giTF5 ftgen 0, 0, -5, -2, 3250, 3580, 3540, 3000, 3300
giTDb1 ftgen 0, 0, -5, -2, 0, 0, 0, 0, 0
giTDb2 ftgen 0, 0, -5, -2, -6, -14, -15, -10, -20
giTDb3 ftgen 0, 0, -5, -2, -7, -12, -18, -12, -17
giTDb4 ftgen 0, 0, -5, -2, -8, -14, -20, -12, -14
giTDb5 ftgen 0, 0, -5, -2, -22, -20, -30, -26, -26
giTBW1 ftgen 0, 0, -5, -2, 80, 70, 40, 40, 40
giTBW2 ftgen 0, 0, -5, -2, 90, 80, 90, 80, 60
giTBW3 ftgen 0, 0, -5, -2, 120, 100, 100, 100, 100
giTBW4 ftgen 0, 0, -5, -2, 130, 120, 120, 120, 120
giTBW5 ftgen 0, 0, -5, -2, 140, 120, 120, 120, 120
;COUNTER TENOR
giCTF1 ftgen 0, 0, -5, -2, 660, 440, 270, 430, 370
giCTF2 ftgen 0, 0, -5, -2, 1120, 1800, 1850, 820, 630
giCTF3 ftgen 0, 0, -5, -2, 2750, 2700, 2900, 2700, 2750
giCTF4 ftgen 0, 0, -5, -2, 3000, 3000, 3350, 3000, 3000
giCTF5 ftgen 0, 0, -5, -2, 3350, 3300, 3590, 3300, 3400
giTBDb1 ftgen 0, 0, -5, -2, 0, 0, 0, 0, 0
giTBDb2 ftgen 0, 0, -5, -2, -6, -14, -24, -10, -20
giTBDb3 ftgen 0, 0, -5, -2, -23, -18, -24, -26, -23
giTBDb4 ftgen 0, 0, -5, -2, -24, -20, -36, -22, -30
giTBDb5 ftgen 0, 0, -5, -2, -38, -20, -36, -34, -30
giTBW1 ftgen 0, 0, -5, -2, 80, 70, 40, 40, 40
giTBW2 ftgen 0, 0, -5, -2, 90, 80, 90, 80, 60
giTBW3 ftgen 0, 0, -5, -2, 120, 100, 100, 100, 100
giTBW4 ftgen 0, 0, -5, -2, 130, 120, 120, 120, 120
giTBW5 ftgen 0, 0, -5, -2, 140, 120, 120, 120, 120
;ALTO
giAF1 ftgen 0, 0, -5, -2, 800, 400, 350, 450, 325
giAF2 ftgen 0, 0, -5, -2, 1150, 1600, 1700, 800, 700
giAF3 ftgen 0, 0, -5, -2, 2800, 2700, 2700, 2830, 2530
giAF4 ftgen 0, 0, -5, -2, 3500, 3300, 3700, 3500, 2500
giAF5 ftgen 0, 0, -5, -2, 4950, 4950, 4950, 4950, 4950
giADb1 ftgen 0, 0, -5, -2, 0, 0, 0, 0, 0
giADb2 ftgen 0, 0, -5, -2, -4, -24, -20, -9, -12
giADb3 ftgen 0, 0, -5, -2, -20, -30, -30, -16, -30
giADb4 ftgen 0, 0, -5, -2, -36, -35, -36, -28, -40
giADb5 ftgen 0, 0, -5, -2, -60, -60, -60, -55, -64
giABW1 ftgen 0, 0, -5, -2, 50, 60, 50, 70, 50
giABW2 ftgen 0, 0, -5, -2, 60, 80, 100, 80, 60
giABW3 ftgen 0, 0, -5, -2, 170, 120, 120, 100, 170
giABW4 ftgen 0, 0, -5, -2, 180, 150, 150, 130, 180
giABW5 ftgen 0, 0, -5, -2, 200, 200, 200, 135, 200
;SOPRANO
giSF1 ftgen 0, 0, -5, -2, 800, 350, 270, 450, 325
giSF2 ftgen 0, 0, -5, -2, 1150, 2000, 2140, 800, 700
giSF3 ftgen 0, 0, -5, -2, 2900, 2800, 2950, 2830, 2700
giSF4 ftgen 0, 0, -5, -2, 3900, 3600, 3900, 3800, 3800
giSF5 ftgen 0, 0, -5, -2, 4950, 4950, 4950, 4950, 4950
giSDb1 ftgen 0, 0, -5, -2, 0, 0, 0, 0, 0
giSDb2 ftgen 0, 0, -5, -2, -6, -20, -12, -11, -16
giSDb3 ftgen 0, 0, -5, -2, -32, -15, -26, -22, -35
giSDb4 ftgen 0, 0, -5, -2, -20, -40, -26, -22, -40
giSDb5 ftgen 0, 0, -5, -2, -50, -56, -44, -50, -60
giSBW1 ftgen 0, 0, -5, -2, 80, 60, 60, 70, 50
giSBW2 ftgen 0, 0, -5, -2, 90, 90, 90, 80, 60
giSBW3 ftgen 0, 0, -5, -2, 120, 100, 100, 100, 170
giSBW4 ftgen 0, 0, -5, -2, 130, 150, 120, 130, 180
giSBW5 ftgen 0, 0, -5, -2, 140, 200, 120, 135, 200
gisine ftgen 0, 0, 4096, 10, 1
giexp ftgen 0, 0, 1024, 19, 0.5, 0.5, 270, 0.5
instr 1
kFund expon p4,p3,p5 ; fundemental
kVow line p6,p3,p7 ; vowel select
kBW line p8,p3,p9 ; bandwidth factor
iVoice = p10 ; voice select
; read formant cutoff frequenies from tables
kForm1 tablei kVow*5,giBF1+(iVoice*15)
kForm2 tablei kVow*5,giBF1+(iVoice*15)+1
kForm3 tablei kVow*5,giBF1+(iVoice*15)+2
kForm4 tablei kVow*5,giBF1+(iVoice*15)+3
kForm5 tablei kVow*5,giBF1+(iVoice*15)+4
; read formant intensity values from tables
kDB1 tablei kVow*5,giBF1+(iVoice*15)+5
kDB2 tablei kVow*5,giBF1+(iVoice*15)+6
kDB3 tablei kVow*5,giBF1+(iVoice*15)+7
kDB4 tablei kVow*5,giBF1+(iVoice*15)+8
kDB5 tablei kVow*5,giBF1+(iVoice*15)+9
; read formant bandwidths from tables
kBW1 tablei kVow*5,giBF1+(iVoice*15)+10
kBW2 tablei kVow*5,giBF1+(iVoice*15)+11
kBW3 tablei kVow*5,giBF1+(iVoice*15)+12
kBW4 tablei kVow*5,giBF1+(iVoice*15)+13
kBW5 tablei kVow*5,giBF1+(iVoice*15)+14
; create resonant formants using fof opcode
koct = 1
aForm1 fof ampdb(kDB1),kFund,kForm1,0,kBW1,0.003,0.02,0.007,\
1000,gisine,giexp,3600
aForm2 fof ampdb(kDB2),kFund,kForm2,0,kBW2,0.003,0.02,0.007,\
1000,gisine,giexp,3600
aForm3 fof ampdb(kDB3),kFund,kForm3,0,kBW3,0.003,0.02,0.007,\
1000,gisine,giexp,3600
aForm4 fof ampdb(kDB4),kFund,kForm4,0,kBW4,0.003,0.02,0.007,\
1000,gisine,giexp,3600
aForm5 fof ampdb(kDB5),kFund,kForm5,0,kBW5,0.003,0.02,0.007,\
1000,gisine,giexp,3600
; formants are mixed
aMix sum aForm1,aForm2,aForm3,aForm4,aForm5
kEnv linseg 0,3,1,p3-6,1,3,0 ; an amplitude envelope
outs aMix*kEnv*0.3, aMix*kEnv*0.3 ; send audio to outputs
endin
</CsInstruments>
<CsScore>
; p4 = fundamental begin value (c.p.s.)
; p5 = fundamental end value
; p6 = vowel begin value (0 - 1 : a e i o u)
; p7 = vowel end value
; p8 = bandwidth factor begin (suggested range 0 - 2)
; p9 = bandwidth factor end
; p10 = voice (0=bass; 1=tenor; 2=counter_tenor; 3=alto; 4=soprano)
; p1 p2 p3 p4 p5 p6 p7 p8 p9 p10
i 1 0 10 50 100 0 1 2 0 0
i 1 8 . 78 77 1 0 1 0 1
i 1 16 . 150 118 0 1 1 0 2
i 1 24 . 200 220 1 0 0.2 0 3
i 1 32 . 400 800 0 1 0.2 0 4
e
</CsScore>
</CsoundSynthesizer>
The previous two examples have played psychoacoustic phenomena associated with the perception of granular textures that exhibit periodicity and patterns. If we introduce indeterminacy into some of the parameters of granular synthesis we begin to lose the coherence of some of these harmonic structures.
The next example is based on the design of example 04F01.csd. Two streams of grains are generated. The first stream begins as a synchronous stream but as the note progresses the periodicity of grain generation is eroded through the addition of an increasing degree of gaussian noise. It will be heard how the tone metamorphosizes from one characterized by steady purity to one of fuzzy airiness. The second the applies a similar process of increasing indeterminacy to the formant parameter (frequency of material within each grain).
Other parameters of granular synthesis such as the amplitude of each grain, grain duration, spatial location etc. can be similarly modulated with random functions to offset the psychoacoustic effects of synchronicity when using constant values.
<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Iain McCurdy
sr = 44100
ksmps = 1
nchnls = 1
0dbfs = 1
giWave ftgen 0,0,2^10,10,1,1/2,1/4,1/8,1/16,1/32,1/64
instr 1 ;grain generating instrument 1
kRate = p4
kTrig metro kRate ; a trigger to generate grains
kDur = p5
kForm = p6
;note delay time (p2) is defined using a random function -
;- beginning with no randomization but then gradually increasing
kDelayRange transeg 0,1,0,0, p3-1,4,0.03
kDelay gauss kDelayRange
; p1 p2 p3 p4
schedkwhen kTrig,0,0,3, abs(kDelay), kDur,kForm ;trigger a note (grain) in instr 3
endin
instr 2 ;grain generating instrument 2
kRate = p4
kTrig metro kRate ; a trigger to generate grains
kDur = p5
;formant frequency (p4) is multiplied by a random function -
;- beginning with no randomization but then gradually increasing
kForm = p6
kFormOSRange transeg 0,1,0,0, p3-1,2,12 ;range defined in semitones
kFormOS gauss kFormOSRange
; p1 p2 p3 p4
schedkwhen kTrig,0,0,3, 0, kDur,kForm*semitone(kFormOS)
endin
instr 3 ;grain sounding instrument
iForm = p4
aEnv linseg 0,0.005,0.2,p3-0.01,0.2,0.005,0
aSig poscil aEnv, iForm, giWave
out aSig
endin
</CsInstruments>
<CsScore>
;p4 = rate
;p5 = duration
;p6 = formant
; p1 p2 p3 p4 p5 p6
i 1 0 12 200 0.02 400
i 2 12.5 12 200 0.02 400
e
</CsScore>
</CsoundSynthesizer>
The next example introduces another of Csound's built-in granular synthesis opcodes to demonstrate the range of dynamic sound spectra that are possible with granular synthesis.
Several parameters are modulated slowly using Csound's random spline generator rspline. These parameters are formant frequency, grain duration and grain density (rate of grain generation). The waveform used in generating the content for each grain is randomly chosen using a slow sample and hold random function - a new waveform will be selected every 10 seconds. Five waveforms are provided: a sawtooth, a square wave, a triangle wave, a pulse wave and a band limited buzz-like waveform. Some of these waveforms, particularly the sawtooth, square and pulse waveforms, can generate very high overtones, for this reason a high sample rate is recommended to reduce the risk of aliasing (see chapter 01A).
Current values for formant (cps), grain duration, density and waveform are printed to the terminal every second. The key for waveforms is: 1:sawtooth; 2:square; 3:triangle; 4:pulse; 5:buzz.
<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;example by Iain McCurdy
sr = 96000
ksmps = 16
nchnls = 1
0dbfs = 1
;waveforms used for granulation
giSaw ftgen 1,0,4096,7,0,4096,1
giSq ftgen 2,0,4096,7,0,2046,0,0,1,2046,1
giTri ftgen 3,0,4096,7,0,2046,1,2046,0
giPls ftgen 4,0,4096,7,1,200,1,0,0,4096-200,0
giBuzz ftgen 5,0,4096,11,20,1,1
;window function - used as an amplitude envelope for each grain
;(hanning window)
giWFn ftgen 7,0,16384,20,2,1
instr 1
;random spline generates formant values in oct format
kOct rspline 4,8,0.1,0.5
;oct format values converted to cps format
kCPS = cpsoct(kOct)
;phase location is left at 0 (the beginning of the waveform)
kPhs = 0
;frequency (formant) randomization and phase randomization are not used
kFmd = 0
kPmd = 0
;grain duration and density (rate of grain generation)
kGDur rspline 0.01,0.2,0.05,0.2
kDens rspline 10,200,0.05,0.5
;maximum number of grain overlaps allowed. This is used as a CPU brake
iMaxOvr = 1000
;function table for source waveform for content of the grain
;a different waveform chosen once every 10 seconds
kFn randomh 1,5.99,0.1
;print info. to the terminal
printks "CPS:%5.2F%TDur:%5.2F%TDensity:%5.2F%TWaveform:%1.0F%n",1,\
kCPS,kGDur,kDens,kFn
aSig grain3 kCPS, kPhs, kFmd, kPmd, kGDur, kDens, iMaxOvr, kFn, giWFn, \
0, 0
out aSig*0.06
endin
</CsInstruments>
<CsScore>
i 1 0 300
e
</CsScore>
</CsoundSynthesizer>
The final example introduces grain3's two built-in randomizing functions for phase and pitch. Phase refers to the location in the source waveform from which a grain will be read, pitch refers to the pitch of the material within grains. In this example a long note is played, initially no randomization is employed but gradually phase randomization is increased and then reduced back to zero. The same process is applied to the pitch randomization amount parameter. This time grain size is relatively large:0.8 seconds and density correspondingly low: 20 Hz.
<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;example by Iain McCurdy
sr = 44100
ksmps = 16
nchnls = 1
0dbfs = 1
;waveforms used for granulation
giBuzz ftgen 1,0,4096,11,40,1,0.9
;window function - used as an amplitude envelope for each grain
;(bartlett window)
giWFn ftgen 2,0,16384,20,3,1
instr 1
kCPS = 100
kPhs = 0
kFmd transeg 0,21,0,0, 10,4,15, 10,-4,0
kPmd transeg 0,1,0,0, 10,4,1, 10,-4,0
kGDur = 0.8
kDens = 20
iMaxOvr = 1000
kFn = 1
;print info. to the terminal
printks "Random Phase:%5.2F%TPitch Random:%5.2F%n",1,kPmd,kFmd
aSig grain3 kCPS, kPhs, kFmd, kPmd, kGDur, kDens, iMaxOvr, kFn, giWFn, 0, 0
out aSig*0.06
endin
</CsInstruments>
<CsScore>
i 1 0 51
e
</CsScore>
</CsoundSynthesizer>
This chapter has introduced some of the concepts behind the synthesis of new sounds based on simple waveforms by using granular synthesis techniques. Only two of Csound's built-in opcodes for granular synthesis, fof and grain3, have been used; it is beyond the scope of this work to cover all of the many opcodes for granulation that Csound provides. This chapter has focused mainly on synchronous granular synthesis; chapter 05G, which introduces granulation of recorded sound files, makes greater use of asynchronous granular synthesis for time-stretching and pitch shifting. This chapter will also introduce some of Csound's other opcodes for granular synthesis.
There has been error in communication with Booktype server. Not sure right now where is the problem.
You should refresh this page.