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

