opcode
Prev | Orchestra Opcodes and Operators | Next

## opcode

opcode — Defines the start of user-defined opcode block.

## Defining opcodes

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 statements.

A user-defined opcode block must precede the instrument (or other opcode) from which it is used. But it is possible to call the opcode from itself. This allows recursion of any depth that is limited only by available memory.

Similarly to instruments, the variables and labels of a user-defined 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 up to and including the highest-numbered one referenced in the calling instrument

- extra time (see also xtratim, linsegr, and related opcodes). This may affect the operation of linsegr/expsegr/linenr/envlpxr in the user-defined opcode block.

- MIDI parameters, if there are any.

Also, the release flag (see the 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.

Use the setksmps opcode to set the local ksmps value.

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 the parameters intypes and outtypes.

| Tip
You can create UDOs which take no inputs or outputs by using 0 instead of a string.

| 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. 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.

## Syntax

    opcode name, outtypes, intypes

## 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.

intypes -- list of input types, any combination of the characters: a, f, k, O, P, V, 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 intypes is shown in the following table:

Type | Description | Variable Types Allowed | Updated At
--- | --- | --- | ---
a | a-rate variable | a-rate | a-rate
f | f-sig variable | f-sig | k-rate
i | i-rate variable | i-rate | i-time
j | optional i-time, defaults to -1 | i-rate, constant | i-time
k | k-rate variable | k- and i-rate, constant | k-rate
O | optional k-rate variable, defaults to 0 | k- and i-rate, constant | k-rate
P | optional k-rate variable, defaults to 1 | k- and i-rate, constant | k-rate
V | optional k-rate variable, defaults to 0.5 | k- and i-rate, constant | k-rate
J | optional k-rate variable, defaults to -1 | k- and i-rate, constant | k-rate
K | k-rate with initialization | k- and i-rate, constant | i-time and k-rate
o | optional i-time, defaults to 0 | i-rate, constant | i-time
p | optional i-time, defaults to 1 | i-rate, constant | i-time
S | string variable | k- and i-rate string, constant | i-time and k-rate

outtypes -- list of output types. The format is the same as in the case of intypes.

Here are the available outtypes:

Type | Description | Variable Types Allowed | Updated At
--- | --- | --- | ---
a | a-rate variable | a-rate | a-rate
f | f-sig variable | f-sig | k-rate
i | i-rate variable | i-rate | i-time
k | k-rate variable | k-rate | k-rate
K | k-rate with initialization | k-rate | i-time and k-rate
S | string variable | k- and i-rate string | i-time and k-rate

The maximum allowed number of output arguments is 256.

The input parameters can be read with xin, and the output is written by xout opcode. Only one instance of these units should be used, as xout overwrites and does not accumulate the output. The number and type of arguments for xin and xout must be the same as in the declaration of the user-defined opcode block (see tables above).

## Performance

The syntax of a user-defined opcode block is as follows:

    opcode  name, outtypes, intypes
    xinarg1 [, xinarg2] [, xinarg3] ... [xinargN]  xin
    [setksmps  iksmps]
    ... the rest of the instrument's code.
    xout  xoutarg1 [, xoutarg2] [, xoutarg3] ... [xoutargN]
    endop

The new opcode can then be used with the usual syntax:

    [xoutarg1] [, xoutarg2] ... [xoutargN] name  [xinarg1] [, xinarg2] ... [xinargN]

| 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

Here is an example of a user-defined opcode. It uses the file opcode.csd.

Example 682. Example of a user-defined opcode.

See the sections Real-time Audio and Command Line Flags for more information on using command line flags.

    <CsoundSynthesizer>
    <CsOptions>
    ; Select audio/midi flags here according to platform
    -odac    ;;;realtime audio out
    ;-iadc    ;;;uncomment -iadc if realtime audio input is needed too
    ; For Non-realtime ouput leave only the line below:
    ; -o opcode_example.wav -W ;;; for file output any platform
    </CsOptions>
    <CsInstruments>

    sr = 44100
    ksmps = 32
    nchnls = 2
    0dbfs  = 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    =  .7                ; 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
            outs a1, a1

            endin

    </CsInstruments>
    <CsScore>

    i 1 0 4
    e5		;extra second before quitting

    </CsScore>
    </CsoundSynthesizer>

Here is another example of a user-defined opcode. It uses the file opcode_f.csd.

Example 683. Second example of a user-defined opcode.

    <CsoundSynthesizer>
    <CsOptions>
    ; Select audio/midi flags here according to platform
    -odac    ;;;realtime audio out
    ;-iadc    ;;;uncomment -iadc if realtime audio input is needed too
    ; For Non-realtime ouput leave only the line below:
    ; -o opcode_f.wav -W ;;; for file output any platform
    </CsOptions>
    <CsInstruments>

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

    ; example by Luis Salgueiro and joachim heintz

    opcode Transpose, a, fk    ; transpose a monophonic input signal through FFT.
      fsig, kInterval xin
      fScaled pvscale fsig, semitone(kInterval)
      aTransposed pvsynth fScaled
      xout aTransposed
    endop

    opcode Stretch,f,ik
      iTab, kSpeed xin
      fStretch pvstanal kSpeed, 1, 1, iTab
      xout fStretch
    endop

    giFox ftgen 0, 0, 0, 1, "fox.wav", 0, 0, 0

    instr 1
      aSnd diskin2 "fox.wav"
      fSnd pvsanal aSnd, 1024, 256, 1024, 1
      aTransposed Transpose fSnd, p4   ; p4 = transposition in semitones
      outall aTransposed/2
    endin

    instr 2
      fStretch Stretch giFox, transeg:k(1,p3,-3,0)
      aStretch pvsynth fStretch
      outall aStretch
    endin

    </CsInstruments>
    <CsScore>
    i1 0 3 0
    i1 . . 7
    i1 . . 12
    i2 4 8
    e
    </CsScore>
    </CsoundSynthesizer>

## See Also

User Defined Opcodes (UDO)

## Credits

Author: Istvan Varga, 2002; based on code by Matt J. Ingalls

New in version 4.22

Prev | Up | Next
olabuffer | Home | oscbnk