Csound

ARRAYS

Since Csound 5.14  (see the release note) there is a possibility to use an experimental way of handling arrays, called t-variables (t as table) which are basically vectors of k-variables. In Csound6, the implementation of arrays has been extended considerably and is continuously developing. Please keep an eye on the changes and documentation.

As for now, we will give some examples for t-variables in Csound 5, and sort of preview on arrays in Csound 6.

Csound 5

Initialisation and allocation:

t1 init 10

allocates t1[0] through t1[9], initialised to zero.

t2 init 20, 1

allocates t2[0] through t2[19], initialised to 1

Individual elements can be assigned via

t1[kvar] = ...expression...

and all expressions can contain t1[kexpr]

It is possible to copy a table with 
t1 = t2

At present there are no global t variables (use ftables). 

Interaction with tables

tans copy2ftab tab, kftbl

The copy2ftab opcode takes a t-var and copies the contents to an f-table.

tans copy2ttab tab, kftbl

The copy2ttab opcode takes an f-table and copies the contents to a t-var.

For example if you want to transfer data from one instrument to another, you need to use global f-tables (and there is plenty of other cases where it is necessary to write data from f-table to t-array or vice versa).

   EXAMPLE 03E01_Array_to_table.csd 

<CsoundSynthesizer>
<CsOptions>
-odac -d
;Example by Tarmo Johannes
</CsOptions>
<CsInstruments>

sr = 44100
ksmps = 32
nchnls = 1
0dbfs = 1

giTab1 ftgen 0, 0, -6, -2, 10,11,12,13,14,15
giTab2 ftgen 0, 0, -6, -2, 0

instr 1
        tvar init ftlen(giTab1) ; declare and initialize array tvar
        copy2ttab tvar,giTab1 ; copy giTab1 to tvar
        printk2 tvar[4]
        tvar[4]=tvar[4]+tvar[3] ;    change a value
        copy2ftab tvar, giTab2 ; write the whole array to the other table
        turnoff ; stop after 1st k-cycle        
endin

instr 2
        index = 0
loophere:
    ival tab_i index,giTab2
    print index,ival
    loop_lt index, 1, ftlen(giTab2), loophere   
endin

</CsInstruments>
<CsScore>
i 1 0 0.1 ; must have some duration, since tvar is handled in k-time (percormance pass)
i 2 0.2 0  ; here only i-values, no duration needed
</CsScore>
</CsoundSynthesizer>

Other opcodes with t-variables

plustab     -  Performs an element by element addition of two vectors.

tans plustab tleft, tright

multtab     - Performs an element by element multiplication of two vectors.

tans multtab tleft, tright

maxtab     - returns the maximum value in a vector.

kmax maxtab tab

mintab     -    returns the minimum value in a vector.

kmin mintab tab

sumtab    - returns the sum of the elements in a vector.

ksum sumtab tab

scalet      -  scales the values in a range of a vector.

scalet tab, kmin, kmax[, kleft, kright]

(tab -- table for operation, kmin, kmax -- target minimum and maximum values, kleft, kright -- range of table to use, defaulting to 0 and size of the vector)

pvs2tab  -  copies spectral data to t-variables.

kframe pvs2tab tvar, fsig

tab2pvs  - copies spectral data from t-variables

fsig tab2pvs tvar[,ihopsize, iwinsize, iwintype]

Examples

Example 1: normalize two tables tables to the maximum value of the tables (using maxtab and scalet  ) - can be useful for leveling also tables with audio data.

   EXAMPLE 03E02_norm_to_max.csd 

<CsoundSynthesizer>
<CsOptions>
-odac ; no -d -allow displays
;Example by Tarmo Johannes
</CsOptions>
<CsInstruments>

sr = 44100
ksmps = 32
nchnls = 1
0dbfs = 1

#define ELEMENTS #5#
seed 0

giTab1 ftgen 0,0,-$ELEMENTS,-21,1,100 ; table of random numbers, 5 elements, maximum 100
giTab2 ftgen 0,0,-$ELEMENTS,-21,1,100


instr 1
        
        t1 init $ELEMENTS
        t2 init $ELEMENTS
        
        copy2ttab t1, giTab1 ; f-tables to vectors
        copy2ttab t2, giTab2
        
        ; find out maxima
        kmax1 maxtab t1
        kmax2 maxtab t2
        
        if (kmax1>kmax2) then
                scalet t2, 0,kmax1 ; scale to the maximum of the higer table
                printks "Vector 1 has higer maximum: %f\n",0, kmax1
                copy2ftab t2, giTab2 ; and write it back to f-table
        else
                scalet t1, 0,kmax2 ; scale to the maximum of the higer table
                printks "Vector 2 has higer maximum %f\n",0, kmax2
                copy2ftab t1, giTab1
        endif

        ; output the new values of the vectors
        kindex=0
loop2:
        event "i", 2, 0, 0, 1,kindex,t1[kindex]
        event "i", 2, 0, 0, 2,kindex,t2[kindex]
        loop_lt kindex,1,$ELEMENTS, loop2
        
        turnoff ; finish after 1 performance pass       
endin

instr 2 ; output values
        prints "Vector: %d index: %d value: %f\n", p4,p5,p6
endin

</CsInstruments>
<CsScore>
i 1 0 0.1
</CsScore>
</CsoundSynthesizer> 

  Example 2: detect peaks in the signal - save data from FFT analyze to array (pvs2tab), scan the array for peaks and play back sound on the frequencies and amplitudes of the peaks as arpeggio.

   EXAMPLE 03E03_FFT_peaks_arpegg.csd   

<CsoundSynthesizer>
<CsOptions>
-odac -d -m128
; Example by Tarmo Johannes
</CsOptions>
<CsInstruments>

sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

giSine ftgen 0, 0, 4096, 10, 1

instr getPeaks
        
        ; generate signal to analyze
        kfrcoef jspline 60,0.1,1 ; change the signal in time a bit for better testing
        kharmcoef jspline 4,0.1,1
        kmodcoef jspline 1,0.1,1
        kenv linen 0.5,0.05,p3,0.05
        asig foscil kenv, 300+kfrcoef,1,1+kmodcoef, 10,giSine
        outs asig*0.05,asig*0.05 ; original sound in backround
        
        ; FFT analyze
        ifftsize  = 1024
        ioverlap  = ifftsize / 4
        iwinsize  = ifftsize
        iwinshape = 1
        fsig pvsanal asig, ifftsize, ioverlap, iwinsize, iwinshape
        ithresh= 0.001 ; detect only peaks over this value      
        tFrames init iwinsize+2 ; declare array
        kframe pvs2tab tFrames, fsig ; FFT values to array - every even member - amp of one bin, odd - frequency

        ; detect peaks
        kindex = 2 ; start checking from second bin, to be able to compare it to previous one
        kcounter = 0
        iMaxPeaks = 13 ; track up to iMaxPeaks peaks
        ktrigger metro 1/2 ; check after every 2 seconds
        if (kframe>0 && ktrigger==1 ) then
                label1:
                        if (tFrames[kindex-2]<=tFrames[kindex] && tFrames[kindex]>tFrames[kindex+2] && tFrames[kindex]>ithresh && kcounter<iMaxPeaks) then  ; check with neigbouring amps - if higher or equal than previous amp and more than the coming one, must be peak.
                                kamp = tFrames[kindex]
                                kfreq = tFrames[kindex+1]                       
                                event "i", "sound", kcounter*0.1, 1, kamp, kfreq ; play sounds with the amplitude and frequency of the peak as in arpeggio
                                kcounter=kcounter+1
                        endif           
                loop_lt kindex,2,ifftsize,label1;
        endif   
endin

instr sound
        iamp= p4
        ifreq=p5
        kenv adsr 0.1,0.1,0.5,p3/2
        kndx line 5,p3,1
        asig foscil iamp*kenv, ifreq,1,0.75,kndx,giSine
        outs asig, asig
endin


</CsInstruments>
<CsScore>
i "getPeaks" 0 60
</CsScore>
</CsoundSynthesizer>

Arrays in Csound 6

During the time of writing on this release, Csound 6 is still in alpha development. But it may nevertheless be useful to put some examples for arrays in Csound 6 here which are working already now in march 2013.

i-Arrays Local

<CsoundSynthesizer>
<CsOptions>
-dnm0
</CsOptions>
<CsInstruments>

;test local iArrays
;jh march 2013

instr 1
          prints    "iArr in instr %d:\n", p1
iArr[]    init     4
icounter  =        0
  until (icounter >= 4) do
iArr[icounter] =   icounter ^ 2
          prints   " iArr[%d] = %f\n", icounter, iArr[icounter]
icounter  +=       1
  od
endin

instr 2
          prints    "iArr in instr %d:\n", p1
iArr[]    init     4
icounter  =        0
  until (icounter >= 4) do
iArr[icounter] =   icounter ^ 2 + 1
          prints   " iArr[%d] = %f\n", icounter, iArr[icounter]
icounter  +=       1
  od
endin

</CsInstruments>
<CsScore>
i 1 0 0
i 2 0 0
</CsScore>
</CsoundSynthesizer>

Prints:
iArr in instr 1:
iArr[0] = 0.000000
iArr[1] = 1.000000
iArr[2] = 4.000000
iArr[3] = 9.000000
iArr in instr 2:
iArr[0] = 1.000000
iArr[1] = 2.000000
iArr[2] = 5.000000
iArr[3] = 10.000000

i-Arrays Global

<CsoundSynthesizer>
<CsOptions>
-dnm0
</CsOptions>
<CsInstruments>

;test global iArrays
;jh march 2013

giArr[]    init       4

instr 1
           prints     "Printing giArr[] in instr %d:\n [", p1
icounter   =          0
           until      (icounter == 3) do
           prints     "%f ", giArr[icounter]
icounter += 1
od
           prints     "%f]\n", giArr[3]
endin

instr 2
           prints     "Changing giArr[] in instr %d.\n", p1
icounter   =          0
           until      (icounter == 4) do
giArr[icounter] =     rnd(10)
           printf_i   " giArr[%d] = %f\n", icounter+1, icounter, giArr[icounter]
icounter   +=         1
od
endin

instr 3
           prints     "Printing giArr[] in instr %d:\n [", p1
icounter   =          0
           until      (icounter == 3) do
           prints     "%f ", giArr[icounter]
icounter   +=         1
od
           prints     "%f]\n", giArr[3]
endin
</CsInstruments>
<CsScore>
i 1 0 0
i 2 0 0
i 3 0 0
</CsScore>
</CsoundSynthesizer>

Prints:
Printing giArr[] in instr 1:
[0.000000 0.000000 0.000000 0.000000]
Changing giArr[] in instr 2.
giArr[0] = 9.735000
giArr[1] = 1.394045
giArr[2] = 7.694886
giArr[3] = 5.250046
Printing giArr[] in instr 3:
[9.735000 1.394045 7.694886 5.250046]

k-Arrays Local

<CsoundSynthesizer>
<CsOptions>
-dnm0
</CsOptions>
<CsInstruments>

;test local kArrays
;jh march 2013

instr 1
          printks   "kArr in instr %d:\n", 0, p1
kArr[]    init     4
kcounter  =        0
  until (kcounter == 4) do
kArr[kcounter] =   kcounter ^ 2
          printf   " kArr[%d] = %f\n", kcounter+1, kcounter, kArr[kcounter]
kcounter  +=       1
  od
          turnoff
endin

instr 2
          printks   "kArr in instr %d:\n", 0, p1
kArr[]    init     4
kcounter  =        0
  until (kcounter == 4) do
kArr[kcounter] =   kcounter ^ 2 + 1
          printf   " kArr[%d] = %f\n", kcounter+1, kcounter, kArr[kcounter]
kcounter  +=       1
  od
          turnoff
endin

</CsInstruments>
<CsScore>
i 1 0 1
i 2 0 1
</CsScore>
</CsoundSynthesizer>
Prints:
kArr in instr 1:
 kArr[0] = 0.000000
 kArr[1] = 1.000000
 kArr[2] = 4.000000
 kArr[3] = 9.000000
kArr in instr 2:
 kArr[0] = 1.000000
 kArr[1] = 2.000000
 kArr[2] = 5.000000
 kArr[3] = 10.000000

k-Arrays Global

<CsoundSynthesizer>
<CsOptions>
-dnm0
</CsOptions>
<CsInstruments>

;test global iArrays
;jh march 2013

giArrLen  =        5
gkArr[]   init     giArrLen

instr 1
          printks   "Printing gkArr[] in instr %d:\n [", 0, p1
kcounter  =        0
  until (kcounter == giArrLen-1) do
          printf   "%f ", kcounter+1, gkArr[kcounter]
kcounter  +=       1
  od
          printf    "%f]\n", kcounter+1, gkArr[kcounter]
          turnoff
endin

instr 2
          printks   "Changing gkArr[] in instr %d.\n", 0, p1
kcounter  =        0
kLim      init     10
  until kcounter == giArrLen do
gkArr[kcounter] =  rnd(kLim)
          printf " gkArr[%d] = %f\n", kcounter+1, kcounter, gkArr[kcounter]
kcounter  +=       1
  od
          turnoff
endin

instr 3
          printks   "Printing gkArr[] in instr %d:\n [", 0, p1
kcounter  =        0
  until (kcounter == giArrLen-1) do
          printf   "%f ", kcounter+1, gkArr[kcounter]
kcounter  +=       1
  od
          printf    "%f]\n", kcounter+1, gkArr[kcounter]
          turnoff
endin
</CsInstruments>
<CsScore>
i 1 0 1
i 2 0 1
i 3 0 1
</CsScore>
</CsoundSynthesizer>
Prints:
Printing gkArr[] in instr 1:
 [0.000000 0.000000 0.000000 0.000000 0.000000]

Changing gkArr[] in instr 2.
 gkArr[0] = 9.735000
 gkArr[1] = 1.394045
 gkArr[2] = 7.694886
 gkArr[3] = 5.250046
 gkArr[4] = 6.226652
Printing gkArr[] in instr 3:
 [9.735000 1.394045 7.694886 5.250046 6.226652]

a-Arrays Local

<CsoundSynthesizer>
<CsOptions>
-odac -d
</CsOptions>
<CsInstruments>

;test local aArrays
;jh march 2013

sr = 44100
ksmps = 32
nchnls = 2

instr 1
aArr[]     init       2
a1         oscils     .2, 400, 0
a2         oscils     .2, 500, 0
kEnv       transeg    1, p3, -3, 0
aArr[0]    =          a1 * kEnv * 20000
aArr[1]    =          a2 * kEnv * 20000
           outch      1, aArr[0], 2, aArr[1]
endin

instr 2 ;to test identical names
aArr[]     init       2
a1         oscils     .2, 600, 0
a2         oscils     .2, 700, 0
kEnv       transeg    0, p3-p3/10, 3, 1, p3/10, -6, 0
aArr[0]    =          a1 * kEnv * 20000
aArr[1]    =          a2 * kEnv * 20000
           outch      1, aArr[0], 2, aArr[1]
endin
</CsInstruments>
<CsScore>
i 1 0 3
i 2 0 3
</CsScore>
</CsoundSynthesizer>

a-Arrays Global

<CsoundSynthesizer>
<CsOptions>
-odac -d
</CsOptions>
<CsInstruments>

;test global aArrays
;jh march 2013 (using code from iain mccurdy)

sr = 44100
ksmps = 32
nchnls = 2

gaArr[]    init       2

  instr 1 ; left channel
kEnv       loopseg    0.5, 0, 0, 1,0.003, 1,0.0001, 0,0.9969
aSig       pinkish    kEnv
gaArr[0]   =          aSig * 20000
  endin

  instr 2 ; right channel
kEnv       loopseg    0.5, 0, 0.5, 1,0.003, 1,0.0001, 0,0.9969
aSig       pinkish    kEnv
gaArr[1]   =          aSig * 20000
  endin

  instr 3 ; reverb
aInSigL    =          gaArr[0] / 3
aInSigR    =          gaArr[1] / 2
aRvbL,aRvbR reverbsc  aInSigL, aInSigR, 0.88, 8000
gaArr[0]   =          gaArr[0] + aRvbL
gaArr[1]   =          gaArr[1] + aRvbR
           outs       gaArr[0], gaArr[1]
gaArr[0]   =          0
gaArr[1]   =          0
  endin
</CsInstruments>
<CsScore>
i 1 0 10
i 2 0 10
i 3 0 12
</CsScore>
</CsoundSynthesizer>

S-Arrays Local 

<CsoundSynthesizer>
<CsOptions>
-dnm0
</CsOptions>
<CsInstruments>

;test local SArrays
;(same code in instr 1 and 2, different values)
;create and fill string array at i-time, modify at k-time
;jh march 2013

  opcode StrAgrm, S, Sj
  ;changes the elements in Sin randomly, like in an anagram
Sin, iLen  xin
 if iLen == -1 then
iLen       strlen     Sin
 endif
Sout       =          ""
;for all elements in Sin
iCnt       =          0
iRange     =          iLen
loop:
;get one randomly
iRnd       rnd31      iRange-.0001, 0
iRnd       =          int(abs(iRnd))
Sel        strsub     Sin, iRnd, iRnd+1
Sout       strcat     Sout, Sel
;take it out from Sin
Ssub1      strsub     Sin, 0, iRnd
Ssub2      strsub     Sin, iRnd+1
Sin        strcat     Ssub1, Ssub2
;adapt range (new length)
iRange     =          iRange-1
           loop_lt    iCnt, 1, iLen, loop
           xout       Sout
  endop


  instr 1
           prints     "SArr[] in instr %d at init-time:\n  [", p1
;create
S_Arr[]    init       4
;fill
iCounter   =          0
           until      (iCounter == 4) do
S_new      StrAgrm    "csound"
S_Arr[iCounter] =     S_new
iCounter += 1
od
;print
iCounter   =          0
           until      (iCounter == 4) do
           printf_i   "%s ", iCounter+1, S_Arr[iCounter]
iCounter += 1
od
           prints     "]\n"

kCycle     timeinstk
           printks    "SArr[] in instr %d at k-cycle %d:\n  [", 0, p1, kCycle
;fill
kCounter   =          0
           until      (kCounter == 4) do
kChar      random     33, 127
S_new      sprintfk   "%c ", int(kChar)
S_Arr[kCounter] strcpyk S_new ;'=' should work but does not
kCounter += 1
od
;print
kCounter   =          0
           until      (kCounter == 4) do
           printf     "%s ", kCounter+1, S_Arr[kCounter]
kCounter += 1
od
           printks    "]\n", 0
if kCycle == 3 then
           turnoff
endif
  endin

  instr 2
           prints     "SArr[] in instr %d at init-time:\n  [", p1
;create
S_Arr[]    init       4
;fill
iCounter   =          0
           until      (iCounter == 4) do
S_new      StrAgrm    "csound"
S_Arr[iCounter] =     S_new
iCounter += 1
od
;print
iCounter   =          0
           until      (iCounter == 4) do
           printf_i   "%s ", iCounter+1, S_Arr[iCounter]
iCounter += 1
od
           prints     "]\n"

kCycle     timeinstk
           printks    "SArr[] in instr %d at k-cycle %d:\n  [", 0, p1, kCycle
;fill
kCounter   =          0
           until      (kCounter == 4) do
kChar      random     33, 127
S_new      sprintfk   "%c ", int(kChar)
S_Arr[kCounter] strcpyk S_new ;'=' should work but does not
kCounter += 1
od
;print
kCounter   =          0
           until      (kCounter == 4) do
           printf     "%s ", kCounter+1, S_Arr[kCounter]
kCounter += 1
od
           printks    "]\n", 0
if kCycle == 3 then
           turnoff
endif
  endin

</CsInstruments>
<CsScore>
i 1 0 1
i 2 1 1
</CsScore>
</CsoundSynthesizer> 

Prints:
SArr[] in instr 1 at init-time:
[consdu uncdos oduscn scodun ]
SArr[] in instr 1 at k-cycle 1:
[s < x + ]
SArr[] in instr 1 at k-cycle 2:
[! P Z r ]
SArr[] in instr 1 at k-cycle 3:
[u U b K ]
SArr[] in instr 2 at init-time:
[uocdsn odscnu uscdon sncduo ]
SArr[] in instr 2 at k-cycle 1:
[c " h h ]
SArr[] in instr 2 at k-cycle 2:
[9 = # U ]
SArr[] in instr 2 at k-cycle 3:
[x F Z l ]

S-Arrays Global

<CsoundSynthesizer>
<CsOptions>
-dnm0
</CsOptions>
<CsInstruments>

;test global SArrays
;jh march 2013

giArrLen  =        5
gSArr[]   init     giArrLen

  opcode StrAgrm, S, Sj
  ;changes the elements in Sin randomly, like in an anagram
Sin, iLen  xin
 if iLen == -1 then
iLen       strlen     Sin
 endif
Sout       =          ""
;for all elements in Sin
iCnt       =          0
iRange     =          iLen
loop:
;get one randomly
iRnd       rnd31      iRange-.0001, 0
iRnd       =          int(abs(iRnd))
Sel        strsub     Sin, iRnd, iRnd+1
Sout       strcat     Sout, Sel
;take it out from Sin
Ssub1      strsub     Sin, 0, iRnd
Ssub2      strsub     Sin, iRnd+1
Sin        strcat     Ssub1, Ssub2
;adapt range (new length)
iRange     =          iRange-1
           loop_lt    iCnt, 1, iLen, loop
           xout       Sout
  endop


  instr 1
           prints     "Filling gSArr[] in instr %d at init-time!\n", p1
iCounter   =          0
           until      (iCounter == giArrLen) do
S_new      StrAgrm    "csound"
gSArr[iCounter] =     S_new
iCounter += 1
od
endin

instr 2
           prints     "Printing gSArr[] in instr %d at init-time:\n  [", p1
iCounter   =          0
           until      (iCounter == giArrLen) do
           printf_i   "%s ", iCounter+1, gSArr[iCounter]
iCounter += 1
od
           prints     "]\n"
endin

instr 3
          printks   "Printing gSArr[] in instr %d at perf-time:\n  [", 0, p1
kcounter  =        0
  until (kcounter == giArrLen) do
          printf   "%s ", kcounter+1, gSArr[kcounter]
kcounter  +=       1
  od
          printks  "]\n", 0
          turnoff
endin

instr 4
           prints     "Modifying gSArr[] in instr %d at init-time!\n", p1
iCounter   =          0
           until      (iCounter == giArrLen) do
S_new      StrAgrm    "csound"
gSArr[iCounter] =     S_new
iCounter += 1
od
endin

instr 5
           prints     "Printing gSArr[] in instr %d at init-time:\n  [", p1
iCounter   =          0
           until      (iCounter == giArrLen) do
           printf_i   "%s ", iCounter+1, gSArr[iCounter]
iCounter += 1
od
           prints     "]\n"
endin

instr 6
kCycle     timeinstk
           printks    "Modifying gSArr[] in instr %d at k-cycle %d!\n", 0, p1, kCycle
kCounter   =          0
           until      (kCounter == giArrLen) do
kChar      random     33, 127
S_new      sprintfk   "%c ", int(kChar)
gSArr[kCounter] strcpyk S_new ;'=' should work but does not
kCounter += 1
od
if kCycle == 3 then
           turnoff
endif
endin

instr 7
kCycle     timeinstk
           printks    "Printing gSArr[] in instr %d at k-cycle %d:\n  [", 0, p1, kCycle
kCounter   =          0
           until      (kCounter == giArrLen) do
           printf     "%s ", kCounter+1, gSArr[kCounter]
kCounter += 1
od
           printks    "]\n", 0
if kCycle == 3 then
           turnoff
endif
endin
</CsInstruments>
<CsScore>
i 1 0 1
i 2 0 1
i 3 0 1
i 4 1 1
i 5 1 1
i 6 1 1
i 7 1 1
</CsScore>
</CsoundSynthesizer>

Prints:
Filling gSArr[] in instr 1 at init-time!
Printing gSArr[] in instr 2 at init-time:
[nudosc coudns dsocun ocsund osncdu ]
Printing gSArr[] in instr 3 at perf-time:
[nudosc coudns dsocun ocsund osncdu ]
Modifying gSArr[] in instr 4 at init-time!
Printing gSArr[] in instr 5 at init-time:
[ousndc uocdns sudocn usnocd ouncds ]
Modifying gSArr[] in instr 6 at k-cycle 1!
Printing gSArr[] in instr 7 at k-cycle 1:
[s < x + ! ]
Modifying gSArr[] in instr 6 at k-cycle 2!
Printing gSArr[] in instr 7 at k-cycle 2:
[P Z r u U ]
Modifying gSArr[] in instr 6 at k-cycle 3!
Printing gSArr[] in instr 7 at k-cycle 3:
[b K c " h ] 



your comment:
name :
comment :

If you can't read the word, click here
word :