Eastman Csound Tutorial
END of this chapter -- NEXT CHAPTER (Chapter 5) -- Table of Contents CHAPTER 1 -- CHAPTER 2 -- CHAPTER 3 -- CHAPTER 4 -- CHAPTER 5 -- CHAPTER 6 APPENDIX 1 -- APPENDIX 2

Chapter 4

PULSE TRAIN GENERATORS ; RANDOM NUMBER GENERATORS

4.1. Buzz and Gbuzz

[ See the discussion of buzz and gbuzz in the Csound reference manual ]

buzz and gbuzz can be used in place of oscillators in situations where we wish to create audio signal waveforms with exactly harmonic partials.[1] In the case of buzz, these harmonics will be equal in amplitude, and the lowest frequency will be the fundamental. (Advanced users also may wish to investigate GEN11. Functions created with gen11 produce similar waveforms, and can be read by standard oscillators.)

The arguments to buzz are :

(1) xamp : amplitude
(2) xcps : frequency of the fundamental
(3) knh : number of harmonics present in the waveform
(4) ifn : function number (must point to a sine wave in the score)
(5) [iphs] :(optional starting phase value, as with "oscil" and "oscili")

Like oscillators, buzz requires an audio function table in the score. This function must be a sine wave, and a large (accurate) table size is recommended. The Csound manual suggests a table size of 8192 points. Below is a sample orchestra and score, in which the number of harmonics increases from 3 to 50 (p5). If you look at the waveform display while playing soundfile /sflib/x/ex4-1.wav in a soundfile soundfile editor such as rezound, audacity or sweep, you will see the regular sharp pulses in the waveform. Also note that the brighter the timbre (the more harmonics that are present), the narrower the pulses.

;  ########################################################
;  soundfile ex4-1   :  buzz                Csound Tutorial
;  #######################################################
; Orchestra file used to create this soundfile example:
-----------------------------------------------------------
nchnls = 1

instr 1
kamp expseg 1, .2, 8000, p3-.4, 5000, .2, 1
ipitch = cpspch(p4)
a1 buzz kamp, ipitch , p5, 1
out a1
endin
-----------------------------------------------------------


< score11 file used to create soundfile example  "ex4-1" :
*f1 0 8192 10 1.;   < large sine wave table for buzz

i1 0 0 5;
p3 rh 4;
p4 no a3;
p5 nu 3/  10/  20/  35/  50;            < number of harmonics
end;
-----------------------------------------------------------

Appendix Csound score file examples : Chapter 4

When you hear the result, you will know why the unit generator is called "buzz." You may also wonder, "Why bother with this thing?". In fact, the output of buzz is usually filtered, or otherwise post-processed, to produce a timbre with greater musical interest than we hear in this didactic example.

Because this is a simple test orc/sco pair we have employed constants for peak (8000) and steady-state (5000) amplitude values within our expseg amplitude envelope generator. If we actually wanted to use this instrument to create something resembling music, we would want to change these constants to score p-field variables.

Like buzz, gbuzz produces an audio waveform consisting of (exactly) harmonic partials. However, gbuzz provides us with greater control over this set of harmonics, and therefore is musically more powerful and useful. Whereas buzz will always produce harmonics of equal strength, beginning with the fundamental, gbuzz enables us to specify both the lowest harmonic number (which need not be the fundamental), and a "brightness factor" (kr). The arguments to gbuzz are :

1) xamp : total amplitude amplitude (as with buzz)
2) xcps : frequency of the fundamental (as with buzz)
3) knh : the number of harmonics present in the waveform (as with buzz)
4) klh : the lowest harmonic present (usually a positive integer) If this value is "1," the lowest harmonic will be the fundamental. However, higher values (such as 2,3...10,11, etc.) are also possible, so that the fundamental and lower harmonics may be "missing" from the waveform. Generally, the perceived pitch will still be the fundamental "xcps," (since this frequency is still the period of the waveform), but the timbre will change.
5) kmul : "brightness factor," a scalar for the relative strength of the harmonics:
If kmul is set to "1", the harmonics will be of equal strength, as in buzz;
If kmul is less than 1, the higher harmonics are progressively attenuated, as though the signal had been sent through a low-pass filter. The lower the kmul value, between "1" and "0," the "mellower" the resulting timbre.
If kmul is greater than 1, the highest harmonic will have the greatest amplitude (as though the signal had been sent through a high-pass filter), while each lower harmonic will have a progressively lower amplitude. The higher the kmul value, the brighter and more nasal the resulting timbre.
6) ifn : function number (must point to a cosine wave function in the score). A cosine wave is a sine wave with a 90 degree phase shift The function must be created with gen9, and should look like this :
* f1 0 8192 9 1. 1. 90;
7) [iphs] :(optional starting phase value -- almost never used)

Here's a simple orchestra and score, once again with an identical amplitude envelope for every note, in which all of the input arguments to gbuzz remain fixed throughout each tone:

;  #############################################################
;  soundfile ex4-2    :  gbuzz                  Csound Tutorial
;  #############################################################
nchnls = 1

instr 1
kamp expseg 1, .2, 8000, p3-.4, 5000, .2, 1
ipitch = cpspch(p4)
a1 gbuzz kamp,  ipitch, p5, p6, p7, 1
out a1
endin
---------------------------------------------------------


< score11 file used to create soundfile "ex4-2" :
* f1 0 8192 9 1 1 90;          < gbuzz audio function

i1 0 0 5;
p3 rh 4;
p4 no a3;
p5 16;                         < knh ( # of harmonics)
p6 1;                          < klh lowest harmonic # (1 = fundamental)
p7 nu 1./ 2./ .5/ 5./ .2;      < kmul (brightness)
end;
-----------------------------------------------------------

In determining the number of harmonics to use with gbuzz, one must consider not only the desired timbral brightness, but also the pitches (fundamental frequencies) of the notes. The spectra of the lower tones of most orchestra instruments includes many more partial frequencies than the spectra of higher pitched tones. In other words, we often will want to scale the number of harmonics in a tone produced by gbuzz depending upon the pitch of the note. (The lower pitched the note, the more harmonics.) To do this ourselves, note by note in a score file, would be wearisome. So in the following example we let the instrument handle this unappealing chore, by including a little subroutine that provides the maximum number of harmonics up to 12000 hertz for each note.

Additionally, the louder that a tone is played, the greater the amplitude of the higher harmonics (which translates into higher kmul values when working with gbuzz). This example also includes a simple envelope to vary the kmul argument to gbuzz (and thus the timbral brightness and the perceived loudness) within each note:

;  #############################################################
;  soundfile ex4-3   :  gbuzz : variable kmul  Csound Tutorial
;  #############################################################
Orchestra file used to create this soundfile:
-----------------------------------------------------------
  nchnls = 1

1   instr 1
2   kamp expseg  1, .2, 8000, p3-.4, 5000, .2, 1    ; amplitude envelope
3   ipitch = cpspch(p4)
4   kbright  line  p6, p3, p7     ; envelope of gbuzz timbral brightness
5   iharmonics = int((12000)/(ipitch*p5)) 
6   ; "iharmonics" returns the maximum number of harmonics below 12000 hz
7     print  ipitch, iharmonics    ; print these values in the sterr output
8   asound gbuzz kamp,  ipitch,  iharmonics,  p5,  kbright,  1
9  out asound
10  endin
-----------------------------------------------------------

< score11 file for ex4-3
* f1 0 8192 9 1 1 90;          < gbuzz audio function

i1 0 0 8;
p3 rh 2;
p4 no a1*2/c3*2/bf4*2/d6*2;            <   < pitch 
p5 nu 1/3;                    < lowest harmonic (1=fundamental)
p6 nu .1/1.1;         <  < kmul value 1: start of note
p7 nu 1.1/.1;         <   < kmul value 2: end of note
end;
-----------------------------------------------------------

Notice in our score file that 8 output notes are created, but p-fields 5, 6 and 7 include only two values, so that these two values will loop, so that our p5 values will be 1/3/1/3/1/3/1/3. This p-field specifies the lowest harmonic to be created by gbuzz, so for the 2nd, 4th, 6th and 8th notes, the harmonic series will begin with the third harmonic, an octave and a perfect fifth above the fundamental. The fundamental and second harmonic will be missing.

Within our instrument, the variable ipitch on line 3 specifies the fundamental frequency (pitch) for each note. On line 4 we create a simple linear envelope to vary the kmul "brightness" value (the relative amplitudes of the lower and the higher harmonics) from the value given in p6 (at the very beginning of the note) to the value given in p7 (at the very end of the note). Odd numbered notes move from a dull timbre of mostly fundamental (p6 = .1) to a bright timbre (p7 = 1.1) in which the highest harmonic has the highest amplitude. Even numbered notes reverse this envelope, changing from bright to mellow.

The variable iharmonics on line 5 specifies the number of harmonics to be created. 12000 is divided by the product of the fundamental frequency (ipitch times the lowest harmonic number (p5). The value converter int returns only the integer portion of the (12000)/(ipitch*p5) expression, throwing away the fractional remainder. Since we may be curious as to how many harmonics will result for different notes, we include a call to unit generator print on line 7, to print out (within Csound's sterr output display) the values ipitch and iharmonics for each note.

Notice in the chart of resulting values below that, given a cutoff frequency for gbuzz of 12 kHz, low notes can produce a very large number of harmonics, and as a result considerable difference in timbre between low and high kmul values for gbuzz; high notes, by contrast, produce far fewer harmonics (especially when the lowest harmonic is not the fundamental), and variations in kmul have much less effect.

note  pitch  fund. freq.  lowest harmonic   number of harmonics
 1      a1      55.000         1                218
 2      a1      55.000         3                 72
 3      c3     130.813         1                 91
 4      c3     130.813         3                 30
 5      bf4    466.137         1                 25
 6      bf4    466.137         3                  8
 7      d6    1174.626         1                 10
 8      d6    1174.626         3                  3

kmul values greater than "1.0" generally will produce buzzy, "steely-edged" or "brittle-sounding" timbres, because such timbres belie the acoustical tendency of partial frequencies to decrease in amplitude as they increase in frequency.

Perhaps you remain unimpressed with the timbral possibilities of gbuzz. Our final gbuzz example, ex4-4, is more fun. The fundamental frequency is very low. In fact, it is below the audible range for the first two notes. The lowest harmonic is not the fundamental, and glissandos have been included.

;  #############################################################
;  soundfile ex4-4 : gbuzz : sub-audio fundamental & glissando
;  #############################################################
Orchestra file used to create this soundfile :
sr = 44100
kr = 4410
nchnls = 1

instr 1
amp expseg 1,.2*p3,8000,.7*p3,3000,.3*p3,1    ; amplitude envelope

; glissando :
   ipitch1 = (p4 > 0 ? cpspch(p4) : abs(p4)) ; negative values = cps
   ipitch2 = (p5 > 0 ? cpspch(p5) : abs(p5)) ; negative values = cps
kgliss expseg ipitch1 ,.2*p3, ipitch1, .6*p3, ipitch2, .2*p3, ipitch2

kmulenv expseg p8, .5*p3, p9, .5*p3,  p8 ; gbuzz kmul brightness envelope

a1 gbuzz amp,  kgliss,  p7,  p6,  kmulenv,  1
a1 tone   a1,  1500            ; filter out spurious high frequncies
out a1
endin
-----------------------------------------------------------


<score11 file used to create soundfile  "ex4-4" :
* f1 0 8192 9 1 1 90;      < gbuzz audio function

i1 0 0 3;
p3 5.;
du 304.5;
p4 nu  -16/ -8.5/ -53;     < 1st fundmental {neg. = cps}
p5 nu  -14.5/ -9/ -49;     < 2nd fundmental {neg. = cps}

p6 nu  3/ 42/ 13;          < lowest harmonic (1=fundamental)
p7 nu  50/ 10/ 40;         < number of harmonics

p8 nu  .5/ .8/ .3;         < kmul1 (brightness multiplier) 1 (start & end)
p9 nu  .9/ 1.4/ .9;        < kmul2 (brightness multiplier) 1 (middle)
end;
-----------------------------------------------------------

Comments on ex4-41 : The init variables ipitch1 and ipitch2 allow us to use "notes" for our score11 pitch input, but also, if p4 and/or p5 are negative, to use cps values. In this score, we are using cps values for both pitch levels of the glissando (negative p4 and p5 values, which are converted to positive by the value converter abs). By using subaudio or very low fundamental frequencies, here with the lower harmonics missing from the waveform, and by changing amplitude ratios for the harmonics (the kmulenv envelope), we can create various kinds of birdcall, motor-like, and other "humming" and "throbbing" types of timbres.

The signals produced in this example are acoustically complex. To assure maximum signal resolution, we have run the amplitude envelope generator at the audio rate and have used a high control rate (4410). Still, a trace of unwanted high frequency noise artifacts result. We have included a low-pass filter (tone, covered in Chapter 5), to reduce this unwanted debris.

4.2. Pseudo-random Number Generators

As noted earlier in this tutorial, natural sounds change in three ways :

1) gradual increases or decreases between different levels (envelopes)
2) periodic (regularly recurring) changes (modulation)
3) "random" (erratic, irregular or complex) variations

We have introduced gradual, non-repeating changes in sound parameters by means of envelope generators, or by oscillators that read a function once per note. Periodic changes in a parameter are produced by oscillators that cycle through a function repeatedly. Pseudo-random number generators enable us to create aperiodic (or stochastic) variations in amplitude, pitch, timbre, and other parameters. Pseudo-random number generators actually create exactly the same series of numbers every time a job is run, but these numbers to not follow a perceptible pattern The sequence of numbers usually can be changed by reseeding the random number generator, changing the default seed (starting value) to another number.

It should be noted that envelopes and periodic variations themselves generally include a "random" component (e.g. slight but noticeable, unpredictable variations in both the rate and depth of a vibrato, which "animate" the vibrato, give it particular expressive qualities and make it sound less mechanical). By introducing random deviations to envelopes and to periodic variations we often can increase the expressivity or "realism" of these control signals. (Necessarily this will make our instruments look more complicated.) In fact, when creating almost any type of control signal, one of these questions we often need to ask is how much randomness to incorporate into the signal.

[ See the discussions of rand, randi and randh, in the Csound reference manual ]

The most basic pseudo-random number generators provided by Csound are the rand family. rand is simply a white-noise generator. Its only argument is amplitude, which can vary at any rate. An optional reseed argument is provided so that one could replace the default seed, or starting, value of .5 with any other between 0 and 1., but this would make no audible difference. The output of rand, then, is a stream of aperiodic numbers lying somewhere between +/- its current amplitude input value.

;  #############################################################
;  soundfile ex4-5    :  White noise        Csound Tutorial
;  #############################################################
Orchetsra file used to create this soundfile :
-----------------------------------------------------------
sr = 22050
kr = 2205
ksmps = 10
nchnls = 1

instr 1
kenv  envlpx  p5, p6, p3, p7, 60, p8, .01 , p9  ; amplitude envelope
; amplitude tremolo :
  ktremrate  line  p10, p3 , p11   ; tremolo rate envelope
  ktremolo  oscil  p12 , ktremrate, 1  ; amplitude modulation signal
    ; add non-modulated & modulated amplitude signals
kamp = ( (1. - p12) * kenv)  +  (ktremolo  * kenv)
anoise  rand  kamp
out anoise
endin
-----------------------------------------------------------


< Score11 file used to create  soundfile "ex4-5" :
* f1  0 1024 10 1.;       < sine wave, used for amplitude tremolo
* f60 0 65 5 .01 64 1.;   < exponential rise

i1 0 0 2;
p3 4;
du .95;
p4 0;        < dummy p-field, (not used )
< amplitude envelope :
p5 15000;
p6 nu 1.5 / .05; < attack time
p7 nu .5 / 1.5;  < decay time
p8 nu .3 / .05;  < atss
p9  nu 0 / .9;   < xmod
< tremolo :
p10  nu 1. / 11. ;  < beginning tremolo rate
p11  nu 6. / 4.;    < end tremolo rate
p12  nu .2 / .5 ;  < tremolo %
end;
-----------------------------------------------------------

4.2.1. randh and randi

randh and randi are similar in basic operation to rand, but with the following differences :

1) whereas rand produces a new number at the k-rate or a-rate, randh and randi allow (and require) us to specify a particular rate, in herz, at which new numbers will be generated. This rate can vary during a tone from near 0 to any value up to kr-1. (If randh or randi are running at the control rate, and the k-rate has been set to 2205, any value up to 2204 is legal.)
2) randh ("rand hold") will hold each value until the next number is generated
3) randi ("rand interpolate") will interpolate, along a linear curve, between each successive pairs of values generated.

Examples:
     k1 randh 5, 10 
Result: A new integer value lying between +5 and -5 will be created 10 times per second. Each value will be "held" (repeated at the k-rate) for 1/10 second
     a1 randi .2, .25  
Result: A breakpoint value between +.2 and -.2 will be generated once every 4 seconds (.25 herz). On every sample pass, a new number will be output which lies along a line connecting successive breakpoint values.

randi is particularly useful in the creation of band-limited noise, illustrated in ex4-6:

;  #############################################################
;  soundfile ex4-6 : band-limited noise or frequency flutter
;  #############################################################
nchnls = 1

instr 2
ipitch = ( p4 < 15 ? cpspch(p4) : p4)   ; p4 can be in cps or pch
inoisewidth = (p9 < 15  ?  p9 * ipitch : p9)
inoiserate = (p10 = 0  ?  kr-1 : p10)     ; for maximum rate, use 0 in p10

kenv  envlpx p5, p6, p3, p7, 60, p8,.01  ; amplitude envelope
knoise randi  inoisewidth, inoiserate    ; for p10 any value up to kr-1 is OK
audio  oscili  kenv , ipitch + knoise, 100
out audio
endin
-----------------------------------------------------------


< Score11 file for "ex4-6" : Band limited noise
< Score for ex4-6 : Band limited noise
* f60 0 65 5 .01 64 1.;                < exponential rise. up
* f100 0 256 10 1.;                     < SINE WAVE
< 1st note : 1.5 octave noise;   2nd note : 80 hz. noise
< 3rd note : 4 % frequency "jitter"
i2 0 0 3;
p3 2;
du .99;
p4 no a4;    < no pitch
p5 15000;
p6 .2;        < attack time
p7 .3;        < decay time
p8 .5;        < atss
p9  nu 1.2 /  80/  .04;  < noise bandwidth ; if < 15,then = multiplier * p4
p10 nu 0/  800/  13;    < rate of random frequency change
end;
-----------------------------------------------------------

Here, knoise is a band-limited stream of numbers between +/- the value the variable we have named inoisewidth. For the three notes in the score, the inoisewidth values are 660, 80 and 17.6 herz. Within the audio oscillator, this control signal is added to a base frequency of 440, herz. The resulting noise bands for the three "notes" have the following properties :

              Center    Highest    Lowest    Noise     Noise
              Frequency Frequency  Frequency Bandwidth Rate
   1st note:   440       1100       -200      1100      2204
   2nd note:   440        520        360       160       800
   3rd note:   440        457.6      423.4      34.2      13

Note that because the random number generator are bi-polar, outputing both positive and negative numbers within the range of its amplitude argument, we actually are specifying half-bandwidth, rather than the full noise bandwidth, in p9. If this innacuracy bothers you, the amplitude argument to randi could easily be changed to

knoise randi .5 * inoisewidth, inoiserate

so that p9 in our score will indicate the full noise bandwidth.

  ########################
  soundfile ex4-7 : randh
  #######################

Soundfile example ex4-7 is identical to ex4-6 in all respects, except that in the orchestra file, randi has been replaced by randh. The audible difference is most apparent on the third note, where we now hear stepped pitch deviations.

randi is frequently used to add small random deviations to various control signals, as in the following skeletal orchestra file:

    1  (orchestra header values)
    2  instr 1 
     ;AMPLITUDE :
    3  kenv  envlpx --,--,--,--,--,--,-- ; amplitude envelope
    4  krandamp randi  .1*kenv, 9          ; +/-10 % random amp. deviation
    5  kamp =  kenv + krandamp           ; final amplitude control signal
    ; PITCH :
    6  ipitch = cpspch(p4)               ; center pitch
    7  krandpitch randi .01*ipitch, 7.       ; +/-1 % random pitch deviation
    8  kpitch = ipitch + krandpitch      ; final pitch control signal
    ; F M INDEX :
    9  kindex  expseg  --,--,--,--,--,   ; fm index envelope
   10  krandindex  randi .2*kindex,5.5       ; +/-20 % random deviation
   11  kindex =  kindex + krandindex     ; final index control signal
   12  a1 foscili kamp, kpitch, 1, 2.005, kindex, 100 ;audio signal
    ; SPATIAL PLACEMENT :
   13  krandspace randi  .24,  4.        ; random spatial movement
   14  kspace = krandspace + .25
   15  outs1 sqrt(kspace) * a1         ; left channel
   16  outs2 sqrt(1-kspace) * a1     ; right channel
   17  endin

In this example, randi control signals are created to introduce irregularities in amplitude, pitch, F.M. index, and spatial placement :

Amplitude : The envelope created by envlpx (line 3) will be varied randomly by +/- 10 %, 9 times per second (lines 4,5)
Pitch : The base pitch (line 6) will deviate by +/- one percent, 7 times per second (lines 7,8). If the center pitch is 200 herz it will waver randomly between 202 and 198 herz.
FM index : The FM index envelope (line 9) will include irregular ripples of +/- 20 % occurring at a rate of 5.5 herz.
Spatial placement : The signal will move erratically, 4 times per second, between the left speaker and "center" placement. Values for the control signal kspace will vary between .01 and .49.

Were we to substitute randh for randi anywhere in the preceding example, the resulting stepped (rather than gradual) changes in level would be audibly more obvious. In natural sounds, random fluctuations are usually gradual rather than abrupt, but there are some musical gestures or sounds in which discontinuities can be used to good effect.

4.2.2. Introducing Attack Chiffs

In all of the examples so far the arguments to the random number generators have been constants. It is often useful, however, to vary the amplitude and/or rate argument values by means of envelope, oscillator, or even other random signals.

The pitch of many acoustic sounds varies widely, and aperiodically, at the very onset of a tone, before gradually settling in to a quasi-periodic pattern. Many additional noise-like frequencies (associated with the scrape of the bow, the slap of the tongue against a reed, and so on) also are present during the prefix (attack) of the tone, but die away quickly. During the "steady-state" and decay, the frequency often includes much smaller random fluctuations.

To simulate the attack noise of acoustic sounds, we can create a randi control signal that begins with high input values for both amplitude (range) and rate, then reduce these values so that they level off at a much lower plateau by the end of the attack. A beginning frequency deviation of 100 % (+/- 50 %) is not uncommon for pitches around middle C or above. To produce a similar result for lower frequencies, even greater initial random deviation is necessary. (A 50 herz tone, varied randomly by +/- 50 %, will produce only a 50 herz band of noise, whereas a 440 herz tone will produce a 440 herz band of noise.)

;  #############################################################
;  soundfile ex4-8  : Frequency Modulation instrument with attack noise
;  #############################################################
;Orchestra file used to create this soundfile:
-----------------------------------------------------------

nchnls = 1

 ; p9 = attack hardness; p10 = fm c:m ratio ; p11 = fm index

 instr 3
 ipitch = (p4<15? cpspch(p4) : p4)   ; p4 can be in cps or pch
 p9 = (p9 = 0 ? 1. : p9) ; allows for p9 to be left blank in score
 iscale = octcps(ipitch)
 iscale = (18-iscale)*.1      ; scalar : c4 = 1., c5 = .9, c3 = 1.1, etc.
 iscale = .5*iscale*p9
 kamp envlpx p5, p6, p3, p7, 60, p8, .01

 ; Pitch skew
 k1 expseg iscale, p9*p6, .005,p3-p6, .005  ; envelope for % pitch skew
 k2 expseg kr - 1, p9*p6, p9*30, p3-p6, 20 ; envelope for pitch skew rate
 knoise  randi k1*ipitch, k2              ; pitch skew

 ; f.m. index envelope
 kindex  expseg p9*p11, p9*p6, p11, p3-(p9*p6),.6*p11
 asound foscili kamp, knoise + ipitch, 1, p10, kindex, 100
 out asound
 endin
-----------------------------------------------------------


< Score for ex4-8 : FM instrument with attack noise
* f60 0 65 5 .01 64 1.;     <expo. up
* f100 0 256 10 1.;         < SINE WAVE

i3 0 0 3;
p3 2;
du .99;
p4 no a4;
 < amplitude envelope :
p5 15000;
p6 nu .07/ .25/ .06;       < attack time
p7 .3;                     < decay time
p8 nu .65/ .85/ .25;       < atss
 < attack hardness & f.m. values :
p9 nu 1./.6/1.7;           < attack hardness, 1. = ord., > 1 = harder
p10 1.006;                 < c:m ratio
p11 nu 1.9/ 1./ 2.6;       < f.m.  index
end;
-----------------------------------------------------------
Here p9 enables us to apply accents, "soft' attacks and other types of phrasing articulations to a series of melodic notes or chords. In this manner, a single score p-field can modify the amplitude, pitch and timbral arguments passed to audio signal generators.

4.2.3. Combining Periodic and Aperiodic Control Signals

Combining oscillator and randi or randh signals within a single subroutine can provide us with the means to create a control signal that lies anywhere along a continuum from total periodicity to total randomness. The cost is about six p-fields. The example below is one possible realization of such an all-purpose periodic/random control signal generator. This module could be used for the generation of tremolo, vibrato, filter bandwidth or panning signals, or for many other types of signal processing operations that might occur to you :

ALL-PURPOSE PERIODIC/RANDOM CONTROL SIGNAL GENERATOR :

; p fields : (beginning arbitrarily with p6)
; p6 = 1st value         p7 = 2nd value
; p8 = rate of change between p6 & p7
; p9 = function table number for change between p6 & p7 values
; p10 =  random deviation  %     p11 = random deviation  rate

(optional p8 flags might be inserted here -- see see discussion below)
kperiodic oscil p7-p6,  p8,  p9     ; this output is the DIFFERENCE between p6 & p7
kperiodic  = kperiodic  + p6        ; add this DIFFERENCE to p6
krandom  randi p10 * kperiodic, p11 ; random deviation ( +/-  % variance in k1)
ksignal  = kperiodic  + krandom     ; add random deviation to periodic variation

-----------------------------------------------------------
Score p-fields for this module :

p6                      < value 1
p7                      < value 2
p8                      < rate of change between p1 & p2 (with optional flags)
p9                      < function for change between p6 & p7
p10                     < random deviation %
p11                     < random deviation  rate

With low values for p10, the resulting control signal will be mostly periodic, with small deviations. With high values for p10, the signal will be mostly random, with a smaller periodic component. When using high p10 values, however, we would frequently need to choose our p6 and p7 values carefully, so that the total signal level produced by adding the periodic and random components would not exceed "1." or "0" at any point. This would be necessary, for example, if the signal were controlling spatial placement.

Additional flag values for p8 could be included within the module above to enable us to specify rates at which is the oscillator function is read in alternative formats to herz. The sub-routine below, for example, includes :

1) a "0" flag, in which the function is read once per note
2) a ">100" flag, enabling us to specify the NUMBER of times the function will be read per note
3) a negative-number flag, enabling us to specify the PERIOD (duration) during which the function is read. The value converter "abs" returns the "absolute" (positive) value of any positive or negative number.
; --  optional flags for p8 rate of change --
p8 = (p8 = 0 ? 1/p3 : p8)       ; if p8 is 0, the function is read once
                                ; per note
p8 = (p8>100 ? (p8-100)/p3: p8) ; if p8 is > 100, the function will be
                                ; read p8-100 times per note ( if p8 is
                                ; is 102.5, the function will be read 2.5
                                ; times per note)
p8 = (p8 < 0? 1/abs(p8) : p8 )  ; if p8 is negative, it will indicate
                                ; the PERIOD of oscillation ( if p8 = -2.5,
                                ; the function will be read once every
                                ; 2.5 seconds

4.2.4. Additional pseudo-random number generators

In addition to the basic rand, randh and randi opcodes Csound also provides many other pseudo-random number generators. Several of these opcodes produce particular weighted (or probability) distributions of pseudo-random number streams, so that values will occur within certain ranges more frequently than within other ranges. In an output stream produced by opcode gauss, for example, the values will tend to cluster in the middle, like a bell-shaped curve, while the values produced by betarand will cluster around two poles.

Two additional "global" pseudo-random number opcodes, rnd (unipolar) and birnd (bi-polar), can be useful in introducing random components within init and control signals. In the following example, rnd is used

  1. to vary the output amplitude of a series of monophonic input soundfiles, multiplying the samples by a value somewhere between .99 and .5 (the variable iamp
  2. to introduce random fade-in times (somewhere between 5 % and 25 % of the total duration of the note -- the variable ifadein
  3. to introduce random fade-out times (somewhere between 10 % and 40 % of the total duration of the note -- the variable ifadeout
  4. to vary the stereo output location (the variable ispace)

   instr 1
   iamp = rnd(.49) + .5 ; vary output amplitude multiplier between .5 and .99
   ifadein = (rnd(.2) +.05) * p3
   ifadeout = (rnd(.3) +  .1) * p3
   kfades  expseg  .005, ifadein , iamp., p3 - (ifadein + ifadeout), iamp ifadeout, .005
   asample  diskin2  kfades, p5, p6

   ispace = rnd (1.)  ; create random left-right stereo locations between 0 and 1.
   outs  sqrt(ispace) * asample, sqrt(1. - ispace) * asample
   endin

jitter 2

In some cases, particularly when random deviation is applied to a parameter such as pitch,to which we are acutely sensitive even to very slight changes, randi may not be adequate for our needs, producing random fluctuations that sound somewhat coarse. In such cases we can employ unit generator jitter2 in place of randi. Whereas randi introduces a random "rippling" into some parameter of a sound, jitter2 provides three simultaneous "rippling" waves. Each of these three random components can have a different rate and depth -- the equivalent of combining three randi signals in parallel to vary the parameter at three different rates and depths. Let us compare the arguments to randi and jitter2:
        kout  randi    kamp,          kcps
        kout jitter2 ktotamp, kamp1, kcps1, kamp2, kcps2, kamp3, kcps3
The two required arguments for randi are depth (kamp and rate (kcps). jitter2 has seven required arguments: a total depth (ktotamp), a depth for each of the three random components (kamp1, kamp2 and kamp3), and a rate for each of the random components (kcps1, kcps2 and kcps3).

Orchestra file ex4-9 below is used with 3 companion score files: ex4-9-1, which adds amplitude jitter to a soundfile, ex4-9-2 which adds pitch jitter to a soundfile, and ex4-9-3 which adds both amplitude and pitch jitter to a soundfile.

;  #############################################################
;  orchestra file ex4-9, used to create soundfiles ex4-9-1, 4-9-2 and 4-9-3
;  #############################################################

nchnls=1
1 instr 3 
2 isound = p4 
3 ; (1) pitch transposition ----------------------------- 
4 ; p6 specifies pitch transposition in semitones; convert here to ratio
5 imult = abs(p6) 
6 if (p6 >= 0) then 
7    itransp = 1*(2^(imult/12)) 
8 elseif (p6 < 0) then 
9    itransp = 1 / (2^(imult/12)) 
10 endif 
11   ; print p6,itransp  ; uncomment for debugging if transposition not working 
12 ; --- (2) optional pitch jitter  ---------------------------------- 
13 if (p9 > 0 ) && (p10 > 0) then 
14  kpitchjit jitter2 p9, .4*p9,p10,  .35*p9,.75*p10,   .25*p9, 1.25*p10 
15  kpitchjit = kpitchjit * .059 
16  asound  diskin2 p4, itransp + kpitchjit  , 1 
17 else 
18    asound  diskin2 p4, itransp, 1 
19 endif 
20 ; ---- (3) amplitude envelope ---------------------------------- 
21 kamp expseg .005,.1,p5, p3-.2,p5,.2,.005 
22 ; --- (4) optional amplitude jitter ------------------------- 
23 if (p7 > 0 ) && (p8 > 0) then 
24   kampjit jitter2 p7, .4*p7,p8,  .35*p7,.75*p8,   .25*p7, 1.25*p8 
25   knoampjit = 1. - p7 
26   asound = (knoampjit * asound) + (kampjit * asound) 
27   out  kamp * kampjit * asound 
28 endif  ; ---------------------------------------------------- 
29     out kamp * asound 
30 endin 
----------------------------------------------------------------------
Here is the first our our three score files for this instrument, ex4-9-1:
 < ECMC Csound Library Tutorial score11 input file >>  ex4-9-1 << :
< illustrates use of jitter2 to add random amplitude variations to a soundfile
< NOTE: before running this example you must create a link to /sflib/voice/bass2.d3.wav
< In a shell window type: sflinksfl  bass2.d3.wav 4
i3 0 0  6;
p3 nu 2/4*5;
am .95;
p4 4;<  1;  < soundin.# number for input soundfile
            < soundin.4 points to /sflib/voice/bass2.d3.wav
p5 .5 ;  < amplitude multiplier
< p6 = transposition up (pos.) or down (neg.) in semitones
p6 nu 0/2./-3./5/ 5.5/-2;  
< p7 & p8 : amplitude jitter: -------------------------------
p7 nu 0/ .5/ .6/  .7/ .8/1.;       < total depth for amplitude jitter (0 - 1.)
p8 nu 0/ 10/  12/  25./70/200;      < basic rate for amplitude jitter
< p9 & 10 : pitch jitter -------------------------------
p9                           < depth  for pitch jitter (1. = semitone)
p10                          < basic rate for pitch jitter
end;
-----------------------------------------------------------------------

This instrument employs our old friend diskin2 to stream the samples from hard disk soundfiles into RAM for processing. So, once again, before we can create a usable score for this instrument we first must create soundin.# link files for all soundfiles to be used. This is most easily accomplished by using the sflink command (for our own soundfiles) or the sflinksfl utility (for sflib soundfiles). Example scores ex4-9-1 and ex4-9-2 use sflib soundfile /sflib/voice/bass2.d3.wav for all notes, denoted by the link file soundin.4 in these scores, while ex4-9-2 employs the sflib soundfile /sflib/env/brook.wav , which we will assign to link file soundin.20. We can make these links with the command

sflinksfl  voice.d3  4     brook  20
Remember than input soundfiles do not need to have the same sampling rate as our output soundfile. If diskin2 detects that the input and output sampling rates d not match, it automatically will employ high quality sample rate conversion on the input soundfile.

I will want to transpose the pitch of these input soundfiles. diskin2 requires that transpositions be specified as resampling ratios, but I would prefer to specify transpositions in my score in terms of the number of semitones that the input soundfile should be transposed up or down. p6 in score file ex4-9-1 above

p6 nu 0/2./-3./5/ 5.5/-2;
specifies no transposition for the first note; up a major second (2 semitones) for the second note; down a minor third (-3 semitones) for the third note; up a perfect fourth (5 semitones) for the fourth note; up a perfect fourth plus a quarter tone (5.5) for the fifth note; and down a major second for the final note.

In the instrument, lines 5 through 10 take care of the conversion from "number of semitones, up or down" to the resampling ratios that diskin2 requires, multiplying (for upward transpositions) or dividing (for downward transpositions) the value in p6 bu the twelfth root of two. You don't need to understand the workings of this code fully; it works, and you can copy and paste it into your own instruments if you wish.

The option to add pitch jitter is performed on lines 13 or 16 of the instrument. Two score p-fields, p9> and , control the pitch jitter, specifying a maximum depth for the pitch warble in semitones (p9) and a basic rate for this jitter in p10. An if...else construction on lines 13 through 19 of the instrument enable us either to implement or bypass the pitch jitter code. If p9 and p10 both are set to zero


if (p9 > 0 ) && (p10 > 0) then
then lines 14 through 16 are skipped, and no pitch jitter is added when diskin2 processes the input soundfile on line 18.

While control signals that affect pitch, such as the jitter2 subroutine on line 14, must be created before we call upon diskin2 (because these signals are needed by diskin2 to alter the input pitch), amplitude adjustments must be made to the audio signal after it has been read in and processed by diskin2. On line 20 we create a simple fade-in/fade-out amplitude envelope, and then, on lines 23 through 28, an option to add amplitude jitter.

The code here is similar to the earlier code on lines 13 through 19 that was used to add (or bypass) pitch jitter. Two score p-fields are used to control amplitude jitter: p7, which specifies the depth on the jitter on decimal a scale of 0 to 1.0 (0 % to 100 %), and p8, which determines a basic rate for the amplitude jitter. If p7 and p8 both are set to zero (or left blank in the score file), this will set the "if..." conditional on line 23 to "false," and the amplitude jitter subroutine on lines 24 through 27 will be bypassed.

Let's take a closer look at the arguments to the two jitter2 unit generators (lines 14 and 24) used to create pitch and amplitude jitter.

                                                        ktotamp   kamp1   kcps1    kamp2   kcps2        kamp3      kcps3
14  kpitchjit jitter2 p9, .4*p9,p10,  .35*p9,.75*p10,   .25*p9, 1.25*p10 ;  (pitch jitter)
24    kampjit jitter2  p7, .4*p7,  p8,  .35*p7,.75*p8,   .25*p7, 1.25*p8 ; (amplitude jitter)

On line 14 p9 specifies the total maximum pitch deviation in semitones, while on line 24 p7 specifies the maximum depth of amplitude jitter. The amplitude arguments to the three random number generators within jitter2 divide up the "peak" value of p9 or p7 into 40 % of this maximum (kamp1), 35 % ((kamp2) and 25 % (kamp3). If all three random number generators are at their peak positive or negative value simultaneously (something that quite likely will never happen), the full value of p9 or p7 will be attained. By the law of averages, however, most of the time when we add the random values being produced by the three random number generators their sum will cluster somewhere around 50 % of p9 or p7.

p10 provides a "basic" rate at which the numbers for the pitch jitter are being created, while p8 provides a similar "basic rate" for the amplitude jitter. The first of the three random number generators within both of our jitter2 opcodes is set to this "basic" value (kcps1). The second random number generator produces numbers at only 3/4 (.75) of this rate (kcps2), while the third random number generator creates breakpoint values at a rate 25 % faster than the "basic" rate (kcps3).

There is nothing magical about the particular percentages I have employed here. However, if you want the jitter to be relatively smooth rather than erratic it is typical to have the three random number generators within jitter2 running at speeds that differ significantly but not by a spread that is too extreme.

It now is time for you to take a look at example score ex4-9-1 in more detail, and to listen to the resulting soundfile (/sflib/x/ex4-9-1.wav), in which amplitude jitter increases both in rate and depth from the first note (no jitter) to the final sixth note, in which the bass singer is reduced to an unceremonious gargling (or, perhaps, gurgling).

Our second score for this instrument, ex4-9-2, is very similar to the preceding score, but employs pitch jitter in place of amplitude jitter. When the bass singer showed up to record vocal tones for our sflib collection many years ago, it is doubtful that this poor soul had any clue that his voice would be subject to such debasement.

  < ECMC Csound Library Tutorial score11 input file >>  ex4-9-2 << :
< illustrates use of jitter2 to add random pitch variations to a soundfile
< NOTE: before running this example you must create a link to /sflib/voice/bass2.d3.wav
< In a shell window type: sflinksfl  bass2.d3.wav 4

i3 0 0  5;
p3 nu 2/4*4;
du .95;
p4 4;  < soundin.# number for input soundfile
       < soundin.4 points to /sflib/voice/bass2.d3.wav
p5 .5 ;  < amplitude multiplier
< p6 = transposition up (pos.) or down (neg.) in semitones
p6 nu 0/2./-3./5/ 5.5;  
< p7 & p8 : amplitude jitter: -------------------------------
p7  < (no amplitude jitter)     < total depth for amplitude jitter (0 - 1.)
p8                               < basic rate for jitter
< p9 & p10 : pitch jitter:
p9 nu 0/ .5/   1./ 2.5/4.; < total pitch  depth  for jitter (1. = semitone)
p10 nu 0/ 12/   7./50/900;       < basic rate for vibrato
end;
-------------------------------------------------------------

Our third and final score for this instrument, ex9-4-3 adds both amplitude and pitch jitter to a babbling brook:

  < ECMC Csound Library Tutorial score11 input file >>  ex4-9-3 << :
< illustrates use of jitter2 to add random amplitude and pitch variations
< to a soundfile
< Before running this score file type:
< sflinksfl  brook.wav   20
< in a shell window to create the link (20) specified in p4

i3 0 0  3;
p3 2;
du 306;
p4 20;  < soundin.# number for input soundfile
p5 .8 ;  < amplitude multiplier
< p6 = transposition up (pos.) or down (neg.) in semitones
p6 nu  -5/-3/-8;
< p7 & p8 : amplitude jitter: -------------------------------
p7  .9;                           < total depth for amplitude jitter (0 - 1.)
p8  33;                          < basic rate for jitter
< p9 & p10 : pitch jitter:
p9 nu 4./3/6;       < total pitch  depth  for jitter (1. = semitone)
p10 nu 25/33/18;     < basic rate for vibrato
end;

Assignment

Try out gbuzz the random number generator randi and perhaps also randh and jitter2. Try adding random deviation in amplitude, pitch, panning, tremolo and vibrato rates and depths and other parameters within one or more of your existing algorithms.

Random number generators provide an extremely useful means of animating sounds. The pitch, amplitude and timbre of most acoustic sounds include significant random components, often quite large during attacks, generally much smaller during the "steady state" and decay of tones. Vibrato (especially) and tremolo tend to be much more "interesting" and "life-like" if both the modulation rate and depth include a small random component.


Eastman Csound Tutorial: End of Chapter 4

TOP of this chapter -- NEXT CHAPTER (Chapter 5) -- Table of Contents CHAPTER 1 -- CHAPTER 2 -- CHAPTER 3 -- CHAPTER 4 -- CHAPTER 5 -- CHAPTER 6 APPENDIX 1 -- APPENDIX 2