Keith Hamel's Csound Course

Week 10

In this tutorial:


Index Next Week Previous Week


GEN-01

Gen routine 1 allows data to be transfered from a sound file into a function table, where it can be read and accessed by table, oscili, or even oscil and foscil. The sound file can be processed and transformed more easily than with soundin.

In order to read a soundfile with GEN-01 you should follow the following steps:

  1. The soundfile can be created by SoundEdit16 or by Csound.
  2. Modify the soundfile (with SoundEdit16) so that it is in MONO and at the same sampling rate you are using in Csound ( 22050). To modify the soundfile, click on the Format button in the main panel of SoundEdit16.
  3. Save the sound file (with Command-S) and place it in your Samples folder (in your Csound directory).
  4. Create a GEN-01 function in the score (Discussed below) Design your instrument in the orchestra (to read the Gen function you have created in the score).

goto top Index


Creating a GEN-01 function table

A Gen-01 function statement has the following format:

f#     start-time     table-size     1     file-# skiptime     format     0
The start-time will be 0, the file number will be the number of the soundfile you wish to read, the skip-time will normally be 0 (provided you want to start reading at the beginning of the file) and the format will be 4 (16-bit short integers). The 0 listed as parameter 8 is needed by this implementation of Csound even though it is not documented anywhere. The table size is the tricky bit. It must be a power of two, and must be large enough to store the sound, but not so large that the soundfile exists only at the beginning portion of the file. Some experimentation may be necessary. The following tables sizes and approximate durations will give you a rough idea.

Durations     Table Size
 0.75 sec     16384
 1.5  sec     32768
 3.0  sec     65536
 6.0  sec     131072
12.0  sec     262144
24.0  sec     524288
48.0  sec     1048576
The table must be large enough to hold the soundfile or the last portion of the sound will be omitted.

A typical Gen-01 statement (accessing a .894 second soundfile stored as "tse-u") is:

f1  0  32768  -1  "tse-u" 0 4 0
In this case a negative 1 is used rather than a 1 because the raw values from the table will be used, not the values scaled to one.

goto top Index


Designing an Instrument to Read Gen-01

Since Gen-01 produces a function table, it can be accessed by any generator that reads tables at an audio rate. The most useful of these is the table generator. In conjuction with a phasor, you can proceed through the table at any speed you want. As you read through the table faster, the pitch will be transposed up. In the example below, a phasor proceeds through the table once in the duration passed from the score. The longer the note, the lower the pitch.

aindex  phasor  (.894/1.5)/p3       ; read through once in the total duration
asig    table   aindex*32768, 1     ; read table 1 (with raw values)
outs    asig, asig                  ; output to stereo

The ratio (.894/1.5) is necessary to ensure the sample is read in its entirety and not stretched (transposed down) or squashed (transposed up). The ratio results from dividing the length of the sample (you can determine this in Soundedit16) to the length of the table (see the durations/table size chart above).


Alternatively, a line could be used (from 0 to 1) as the index into the table.

aindex  line    0, p3, 1            ; rises from 0 to 1 in the total duration
asig    table   aindex*32768, 1     ; read table 1 (with raw values)
outs    asig, asig                  ; output to stereo

To start reading the table in a different location, a phase offset value can be added to phasor, or line could begin reading above 0.

aindex  phasor  (.894/1.5)/p3, p6   ; offset passed in p6 (between 0 and 1)

OR

aindex  line    p6, p3, p7          ; read from p6 to p7 (between 0 and 1)
; assumes a sound file of duration p3

In order to calculate exact transpositions of the sound, you must know the duration of the soundfile in the table. It will be:

Table Size   Exact Duration
  16384      0.7447272 sec.
  32768      1.4860771 sec.
  65536      2.9722154 sec.
 131072      5.9443084 sec.
 262144      11.888617 sec.
 524288      23.777234 sec.
1048576      47.554467 sec.
In order to read through the table at the correct original speed use the duration value appropriate for your table size:

aindex  phasor  1/1.4860771         ; read once in table duration
In order to transpose the sound, calculate the ratio between the original pitch and the new pitch. Assuming an original pitch of 8.00 we would have:

itrans  =   cpspch(8.00)/cpspch(p5)                 ; ratio of orig to new pitch
aindex  phasor   (.894/1.5)/(1.4860771 * itrans)    ; read once in table duration
asig    table    aindex*32768, 1                    ; read table 1
outs    asig, asig                                  ; output to stereo

Since the actual durations of the notes are different depending on how quickly we run through the table, the actual duration of the transposed sound can also be set in the instrument.

itrans  =   cpspch(8.00) / cpspch(p5)     ; ratio of orig to new pitch
p3      =   (1.4860771 * itrans)          ; calculate real duration
aindex  phasor  (.894/1.5) / p3           ; read once in new duration
asig    table   aindex*32768, 1           ; read table 1
outs    asig, asig                        ; output to stereo

goto top Index


Delay

Delay is a useful generator for creating echo and reverberation effects on an audio signal. It takes an audio signal and delay time (in seconds) as arguments. (The longer the delay time, the more memory consummed by the instrument).

kenv  expon   1, p3, .0001                             ; expon envelope
asig  foscil  p4 * kenv, cpspch(p5), 1, 1.414, 2, 1    ; an fm bell
adel  delay   asig, .5                                 ; delay .5 seconds
outs  asig + adel, asig + adel

The following uses a series of delays all with diminishing ampltudes

kenv   expon  1, p3, .0001     ; expon envelope
asig   foscil p4 * kenv, cpspch(p5), 1, 1.414, 2, 1   ; an fm bell
adel1  delay  asig, .2         ; delay .2 seconds
adel2  delay  asig, .4         ; delay .4 seconds
adel3  delay  asig, .6         ; delay .6 seconds
adel4  delay  asig, .8         ; delay .8 seconds
adel5  delay  asig, 1.0        ; delay 1 seconds
asig   =   asig + adel1*.9 + adel2*.7 + adel3*.5 + adel4*.3 + adel5*.1
outs   asig,asig

It is also possible to read and write directly to a delay line (with delayw and delayr) and to create a one sample delay (with delay1).

goto top Index


upsamp, downsamp and interp

At times it is useful to convert between directly between control (k-) and audio (a-) variables. This is done with the upsamp (k to a) and downsamp (a to k) routines. For instance is an audio source is needed as a control, you can down-sample the a- variable to a k- variable and use it as a control.

asig1,asig2   soundin 1
ksig  downsamp  asig1
Conversely, a control may be up-sampled to a-rate with upsamp or (for interpolated results) with interp.

ksig  oscil1  p6, 1, p3, 1          ; read table 1 with oscil1
asig  upsamp  ksig                  ; up sample to audio rate 
OR

ksig  oscil1  p6, 1, p3, 1          ; read table 1 with oscil1
asig  interp  ksig                  ; up sample to audio rate 
In the example above, a GEN-01 table is read by oscil1 with the start time specified in p6, and the duration in p3. Upsampling or interpolating between k- values will still result in some distortion of the original audio signal.


goto top Index Next Week Previous Week