| luis jure wrote:
> BTW, perhaps the manual page could be more explicit about this. it's true
> that you can infer this by reading carefully the note:
The updated (Oct 2002) manual does mention this (and has many other
corrections as well, and is generally more usable than the original
"draft" version that is unfortunately in all manual distributions).
I kept posting the new manual several times since then, but it was
always ignored; probably I will replace the manual myself eventually.
Anyway, it is included below:
USER DEFINED OPCODES
--------------------
opcode Name, outtypes, intypes
[xinarg1[, xinarg2[, xinarg3[, ... ]]] xin]
[setksmps iksmps]
[...]
[ xout xoutarg1[, xoutarg2[, xoutarg3[, ... ]]]]
endop
[xoutarg1[, ... ]] Name [xinarg1[, ... ]][, iksmps]
DESCRIPTION
-----------
The opcode and endop statements allow defining a new opcode that can
be used the same way as any of the built-in Csound opcodes. These
opcode blocks are very similar to instruments (and are, in fact,
implemented as special instruments), but cannot be called as a normal
instrument e.g. with the "i" score event. An opcode definition must
precede the instrument (or other opcode) from which it is used, but
it is possible to call the opcode from itself, allowing recursion of
any depth that is limited only by available memory. Additionally,
there is an experimental feature that allows running the opcode
definition at a higher control rate than the kr value specified in
the orchestra header.
Similarly to instruments, the variables and labels of an opcode block
are local, and cannot be accessed from the caller instrument (and the
opcode cannot access variables of the caller, either).
Some parameters are automatically copied at initialization, however:
- all p-fields (including p1)
- extra time (see also xtratim, linsegr, and related opcodes). This
may affect the operation of linsegr/expsegr/linenr/envlpxr in the
opcode definition.
- MIDI parameters, if there are any
Also, the release flag (see release opcode) is copied at performance
time.
Modifying the note duration in the opcode definition by assigning to
p3, or using ihold, turnoff, xtratim, linsegr, or similar opcodes
will also affect the caller instrument. Changes to MIDI controllers
(for example with ctrlinit) will also apply to the instrument from
which the opcode was called.
setksmps sets the local ksmps value (see "iksmps" below).
The xin and xout opcodes copy variables to and from the opcode
definition, allowing communication with the calling instrument.
The types of input and output variables are defined by "intypes" and
"outtypes".
NOTES:
- xin and xout should be called only once, and xin should precede
xout, otherwise an init error, and deactivation of the current
instrument may occur.
- these opcodes actually run only at i-time, and performance time
copying is done by the user opcode call. This means that skipping
xin or xout with kgoto has no effect, while skipping with igoto
affects both init and performance time operation.
INITIALIZATION
--------------
Name - name of the opcode. It may consist of any combination of
letters, digits, and underscore (_), but should not begin with a
digit. If an opcode with the specified name already exists, it is
redefined (a warning is printed in such cases). Some reserved words
(like instr and endin) cannot be redefined.
NOTE: redefinitions do not affect instruments that are defined
before the new opcode.
intypes - list of input types, any combination of the characters a, k,
K, i, o, p, and j. A single 0 character can be used if there are no
input arguments. Double quotes and delimiter characters (e.g. comma)
are *not* needed. The meaning of the various types is shown in the
following table:
+------+-------------------+-------------------------+------------+
| Type | Description | Variable types allowed | Updated at |
+------+-------------------+-------------------------+------------+
| a | a-rate variable | a-rate | a-rate |
+------+-------------------+-------------------------+------------+
| k | k-rate variable | k- and i-rate, constant | k-rate |
+------+-------------------+-------------------------+------------+
| K | k-rate with | k- and i-rate, constant | i- and |
| | initialization | | k-rate |
+------+-------------------+-------------------------+------------+
| i | i-rate variable | i-rate, constant | i-rate |
+------+-------------------+-------------------------+------------+
| o | optional i-rate, | i-rate, constant | i-rate |
| | defaults to zero | | |
+------+-------------------+-------------------------+------------+
| p | optional i-rate, | i-rate, constant | i-rate |
| | defaults to 1 | | |
+------+-------------------+-------------------------+------------+
| j | optional i-rate, | i-rate, constant | i-rate |
| | defaults to -1 | | |
+------+-------------------+-------------------------+------------+
The maximum allowed number of input arguments is 24.
Additionally to the user specified argument list, one optional
i-rate input parameter is always added. This defaults to zero, and
sets the local ksmps value of the opcode call (see "iksmps" below).
outtypes - list of output types. The format is the same as in the case
of intypes, however, the available types are slightly different:
+------+-------------------+-------------------------+------------+
| Type | Description | Variable types allowed | Updated at |
+------+-------------------+-------------------------+------------+
| a | a-rate variable | a-rate | a-rate |
+------+-------------------+-------------------------+------------+
| k | k-rate variable | k-rate | k-rate |
+------+-------------------+-------------------------+------------+
| K | k-rate with | k-rate | i- and |
| | initialization | | k-rate |
+------+-------------------+-------------------------+------------+
| i | i-rate variable | i-rate | i-rate |
+------+-------------------+-------------------------+------------+
The maximum allowed number of output arguments is 24.
iksmps - local ksmps value. Must be a positive integer, and also the
ksmps of the calling instrument or opcode must be an integer
multiple of this value. For example, if ksmps is 10 in the
instrument from which the opcode was called, the allowed values for
iksmps are 1, 2, 5, and 10.
If iksmps is set to zero, the ksmps of the caller instrument or
opcode is used (this is the default behavior).
NOTE: local ksmps is implmented by splitting up a control period
into smaller sub-kperiods, and temporarily modifying internal
Csound global variables. This also requires converting the rate of
k-rate input and output arguments (input variables receive the
same value in all sub-kperiods, while outputs are written only in
the last one).
WARNING: when the local ksmps is not the same as the orchestra level
ksmps value (as specified in the orchestra header), global a-rate
operations must not be used in the opcode definition.
These include:
- any access to "ga" variables
- a-rate zak opcodes (zar, zaw, etc.)
- tablera and tablewa (these two opcodes may in fact work, but
caution is needed)
- in and out opcode family (these read from, and write to global
a-rate buffers)
In general, the local ksmps should be used with care, as it is an
experimental feature, though it works correctly in most cases.
PERFORMANCE
-----------
xinarg1, xinarg2, ... - input arguments. The number and type of
variables must agree with the declaration (see also the table at
"intypes").
xoutarg1, xoutarg2, ... - output arguments. The number and type of
variables must agree with the declaration (see also the table at
"outtypes").
NOTE: the opcode call is always executed both at initialization and
performance time, even if there are no a- or k-rate arguments.
If there are many user opcode calls that are known to have no
effect at performance time in an instrument, then it may save some
CPU time to jump over groups of such opcodes with kgoto.
EXAMPLES
--------
/* ---- opcode_example.orc ---- */
sr = 44100
ksmps = 50
nchnls = 1
/* example opcode 1: simple oscillator */
opcode Oscillator, a, kk
kamp, kcps xin ; read input parameters
a1 vco2 kamp, kcps ; sawtooth oscillator
xout a1 ; write output
endop
/* example opcode 2: lowpass filter with local ksmps */
opcode Lowpass, a, akk
setksmps 1 ; need sr=kr
ain, ka1, ka2 xin ; read input parameters
aout init 0 ; initialize output
aout = ain*ka1 + aout*ka2 ; simple tone-like filter
xout aout ; write output
endop
/* example opcode 3: recursive call */
opcode RecursiveLowpass, a, akkpp
ain, ka1, ka2, idep, icnt xin ; read input parameters
if (icnt >= idep) goto skip1 ; check if max depth reached
ain RecursiveLowpass ain, ka1, ka2, idep, icnt + 1
skip1:
aout Lowpass ain, ka1, ka2 ; call filter
xout aout ; write output
endop
/* example opcode 4: de-click envelope */
opcode DeClick, a, a
ain xin
aenv linseg 0, 0.02, 1, p3 - 0.05, 1, 0.02, 0, 0.01, 0
xout ain * aenv ; apply envelope and write output
endop
/* instr 1 uses the example opcodes */
instr 1
kamp = 20000 ; amplitude
kcps expon 50, p3, 500 ; pitch
a1 Oscillator kamp, kcps ; call oscillator
kflt linseg 0.4, 1.5, 0.4, 1, 0.8, 1.5, 0.8 ; filter envelope
a1 RecursiveLowpass a1, kflt, 1 - kflt, 10 ; 10th order lowpass
a1 DeClick a1
out a1
endin
/* ---- opcode_example.sco ---- */
i 1 0 4
e
AUTHOR
------
Istvan Varga, 2002; based on code by Matt J. Ingalls |