zakinit isizea, isizek
ir zir indx kr zkr kndx ziw isig, indx zkw ksig, kndx ziwm isig, indx, imix zkwm ksig, kndx, kmix kr zkmod ksig, kzkmod ar zamod asig, kzamod zkcl kfirst, klas zacl kfirst, klast ar zar kndx ar zarg kndx, kgain zaw asig, kndx zawm asig, kndx, kmix
zakinit isizea, isizek
"zak" means a or k rate patching, (i rate too), with a z at the start of the names of the ugens.
This is a fudge to do the work until arrays are implemented. I want to use such facilities and will use zak for the time being.
The zak system uses one area of memory as a global i or k rate patching area, and another for audio rate patching.
isizea - The number of audio rate "locations" for a rate patching. Each "location" is actually an array which is ksmps long.
isizek - The number of locations we want to reserve for floats in the zk space. These can be written and read at i and k rates.
These are establised by a ugen which must be called once only:
zakinit 10 30
reserves memory for locations 0 to 30 of zk space and for locations 0 to 10 of a rate za space. With ksmps = 8, this would take 31 floats for zk and 80 floats for za space. At least one location is always allocated for both za and zk spaces. There is nothing wrong with having za and zk ranges thousands or tens of thousands, but most pieces probably only need a few dozen to patch their signals around. These patching locations can be referred to by number with the following ugens.
The easiest way to run zakinit just once is to put it outside any instrument definition. Typically this would be at the start of the orchestra file, with the sr etc. definitions. All code outside the instrument definitions is treated as instrument one and is given an init run at time = 0.
Known bugs in zak system
When using the mix function of zkwm or zawm, care must be taken that the variables mixed to are zeroed at the end (or start) of each k cycle. The same applies to any variables to which signals are mixed. If you keep adding signals to them, their values can drift to astronomical figures - which is probably not what you want.
My intention is to have certain ranges of za and zk variables used for mixing - I use zkcl and zacl in the last instrument to clear those ranges.
Why arrays or "zak" are important for some applications
A major theme of my approach to making music is to set up processes and let them interact and be affected by random occurrences. This can be expensive in analog hardware - but a load of fun too.
Setting up a garden of interacting processes and then tweaking them to whatever state of control or chaos I like is my idea of fun! Lets say I want to set up a musical cellular automata - with 100 similar cells.
Each one produces sound and has various internal states stored as i, k or a rate variables. The behaviour of each cell is at least partially dependant on that of its neighbours. Typically, each cell would make some of its own internal state - including sound output - readable by its neigbours or other things.
There could be a global matron function who tries to control the cells' level of friskiness if they individually or collectively incur her wrath by becoming too obstreperous.
So I have a 10 x 10 array of cells, and their internal state is made available as global variables - with different names for the same variable in different cells. This could be done with 100 carefully written instruments, but life is too short.
The only alternative is to use one instrument and have each instance
decide where its interal states are written to for others to read. It should
decide which of the 99 other instances it will read the states of. The
ideal way is if we could write global variables as:
gahuey[p7] = afoo * abar or gahuey[kdest] = afoo * abar
In either case, one element of an array huey[] of a rate variables is
written. (Actually each variable is an array of ksmps floats.) Likewise
we want to be able to write these array specifications in the right hand
of equations.
gaduey[kdest] = huey[ksource] * (ablah + p4)
So that is the first thing about arrays - make them easy and direct
to use with i or k rate indexing. Secondly, make them multidimensional:
galouey[4, 10] Is a 2D array of global audio rate variables.
gkblah[2, 4, 10] Is a 3D array of global k rate variables.
Thirdly, we want them to be either global or local to the instance of the instrument. This is quite a tall order, since the core of Csound is not perfect and is largely devoid of comments. Such facilities are obviously beyond what Csound was originally conceived to do, but now that CPUs are so much faster, many people will be writing more sophisticated programs.
In principle, the global aspect of arrays can be acheived with the zak system, but it is trickier. zak ugens do not go on the left or right of equations, they have their own line. They must write to normal variables and be fed by normal variables. Arrays, and multi dimensional arrays can all be done with offsets and multiplications to arrive at the final number of the location in za or zk space - but it this involves bulky, hard do debug and understand .orc code, and there is no prospect for building mnemonic names into the way these variables are accessed.
I intend to do some cellular automatata or use multiple reverb and sound source instruments with varying delay times between them, all mixed with my binaural model - with the instruments, reverb points (and hence their connecting time delays) potentially moving around.
Robin Whittle
Australia
May 1997
ar zar kndx ar zarg kndx, kgain zaw asig, kndx zawm asig, kndx [, imix]
For a rate reading and writing, in the za space.
kndx - Points to which za variable to read.
kgain - multiplies the a rate signal by a k rate value kgain.
zar reads the number kndx array of floats in za space which are the ksmps number of audio rate floats to be processed in a k cycle.
zarg is imilar to zar, but multiplies the a rate signal by a k rate value kgain.
zaw rites asig into the za variable specified by kndx.
zawm is similar to zaw above, except that it can mix - add the asig to the current value of the destination za variable. If no imix is specified, it mixes, but if imix is used, then 0 will cause a simple write (like zaw) and any other value will cause mixing.
Robin Whittle
Australia
May 1997
kr zkmod ksig, kzkmod ar zamod asig, kzamod zacl kfirst, klast zkcl kfirst, klast
Opcodes to clear and modulate the za and zk spaces.
zkmod is a unit generator intended to facilitate the modulation of one signal by another, where the modulating signal comes from a zk variable. Either additive or mulitiplicative modulation is provided.
ksig - is the input signal, to be modulated and sent to the output of the zkmod unit generator.
kzkmod - controls which zk variable is used for modulation. A positive value means additive modulation, a negative value means multiplicative modulation. A value of 0 means no change to ksig - it is transferred directly to the output.
For instance kzkmod = 23 will read from zk variable 23, and add the value it finds there to ksig. If kzkmod = -402, then ksig is multiplied by the value read from zk location 402.
kzkmod - can be an i or a k rate value.
zamod - Modulation of one audio rate signal by a second one - which comes from a za variable. The location of the modulating variable is controlled by the i or k rate variable kzamod. This is the audio rate version of zkmod described above.
zacl - This will clear to zero one or more variables in the za space. Useful for those variables which are accumulators for mixing things during the processing for each cycle, but which must be cleared to zero before the next set of calculations.
zkcl - This will clear to zero one or more variables in the zk space. Useful for those variables which are accumulators for mixing things during the processing for each cycle, but which must be cleared to zero before the next set of calculations.
Robin Whittle
Australia
May 1997
ir zir indx kr zkr kndx ziw isig, indx zkw ksig, kndx ziwm isig, indx [,imix] zkwm ksig, kndx [,imix]
There are two short, simple, fast opcodes which read a location in zk space, at either i time or at the k rate. Likewise, two write to a location in zk space at i time or at the k rate.
isig, ksig - i or k rate. Value to write to the zk location. indx,kndx - i or k rate. Which zk location to write it to.
These are fast and always check that the index is within the range of zk space. If it is out of range, an error is reported and 0 is returned, or no writing takes place.
For instance,:
zkw kzoom, p8
can be used so that parameter 8 of the instrument's command line could control where in zk space the output is written.
zkw kzoom, 7
This will always write it to zk location 7.
ziwm and zkwm are like ziw and zkw above, except that
they can mix - add the sig to the current value of the variable. If no
imix is specified, they mix, but if imix is used, then 0 will cause writing
(like ziw and zkw) any other value will cause mixing.
kxxx phasor 1 kdest = 40 + kxxx * 16 zkw kzoom, kdest ;This will write kzoom to locations 40 to 55 on a one second scan ;cycle.
Robin Whittle
Australia
May 1997