opcode
Prev | Opcodes et opérateurs de l'orchestre | Next

## opcode

opcode — Commence un bloc d'opcode défini par l'utilisateur.

## Définir des opcodes

Les instructions opcode et endop permettent de définir un nouvel opcode qui peut être utilisé de la même façon qu'un opcode original de Csound. Ces blocs d'opcode ressemblent beaucoup aux instruments (et sont, en fait, implémentés comme des instruments spéciaux), mais on ne peut pas les appeler comme des intruments normaux, par exemple avec des instructions i.

Un bloc d'opcode défini par l'utilisateur doit précéder l'instrument (ou l'opcode) depuis lequel on l'utilise. Mais un opcode peut aussi s'appeler lui-même. Cela permet une récursivité dont la profondeur n'est limitée que par la mémoire disponible. De plus, on peut, à titre expérimental, exécuter l'opcode défini à un taux de contrôle plus élevé que la valeur de kr spécifiée dans l'en-tête de l'orchestre.

Comme pour les intruments, les variables et les étiquettes d'un bloc d'opcode défini par l'utilisateur sont locales et ne sont pas visible depuis l'instrument appelant (de même que l'opcode n'a pas accès aux variables de l'instrument qui l'a appelé).

Cependant, certains paramètres sont copiés automatiquement à l'initialisation :

- tous les p-champs (p1 inclus)

- le temps supplémentaire (voir aussi xtratim, linsegr, et les opcodes correspondants). Ceci peut affecter le fonctionnement de linsegr/expsegr/linenr/envlpxr dans le bloc d'opcode défini par l'utilisateur.

- les paramètres MIDI, s'il y en a.

Le drapeau de release (voir l'opcode release) est également copié durant l'exécution.

La modification de la durée de la note dans la définition de l'opcode en assignant une valeur à p3, ou l'utilisation de ihold, turnoff, xtratim, linsegr, ou d'autres opcodes similaires affecteront aussi l'instrument appelant. Les changements sur des contrôleurs MIDI (par exemple avec ctrlinit) s'appliqueront aussi à l'instrument qui a appelé l'opcode.

Utilisez l'opcode setksmps pour fixer la valeur locale de ksmps.

Les opcodes xin et xout copient des variables vers et depuis la définition de l'opcode, permettant la communication avec l'instrument appelant.

Les types des variables d'entrée et de sortie sont définis par les paramètres intypes et outtypes.

| Tip
On peut créer des UDOs sans entrée ou sans sortie en remplaçant la chaîne caractères correspondante par 0.

| Notes
xin et xout ne doivent être appelés qu'une seule fois, et xin doit précéder xout, sinon une erreur d'initialisation et une désactivation de l'instrument courant peuvent se produire. Ces deux opcodes n'agissent qu'à l'initialisation. La copie durant l'exécution est réalisée par l'appel de l'opcode de l'utilisateur. Cela signifie que sauter xin ou xout avec kgoto n'a aucun effet, alors que les sauter avec igoto affecte à la fois les opérations de l'initialisation et de l'exécution.

## Syntaxe

    opcode nom, outtypes, intypes

## Initialisation

nom -- nom de l'opcode. Il est constitué de n'importe quelle combinaison de lettres, chiffres et traits de soulignement mais il ne doit pas commencer par un chiffre. Si un opcode du même nom existe déjà, il est redéfini (un avertissement est imprimé dans ce cas). Certains mots réservés (comme instr et endin) ne peuvent pas être redéfinis.

intypes -- liste des types en entrée, toute combinaison des caractères a, k, O, P, V, K, i, o, p et j. Un caractère 0 unique peut être utilisé s'il n'y a pas d'argument en entrée. Il n'y a pas besoin d'apostrophes doubles et de délimiteurs (comme la virgule).

La signification des différent intypes est montrée dans le tableau suivant :

Type | Description | Types de Variable Autorisés | Mise à jour
--- | --- | --- | ---
a | variable de taux-a | taux-a | taux-a
i | variable de taux-i | taux-i | initialisation
j | facultatif de taux-i, -1 par défaut | taux-i, constante | initialisation
k | variable de taux-k | taux-k et -i, constante | taux-k
O | variable facultative de taux-k, valant 0 par défaut | taux-k et -i, constante | taux-k
P | variable facultative de taux-k, valant 1 par défaut | taux-k et -i, constante | taux-k
V | variable facultative de taux-k, valant 0.5 par défaut | taux-k et -i, constante | taux-k
K | taux-k avec initialisation | taux-k et -i, constante | taux-i et taux-k
o | facultatif à l'initialisation, 0 par défaut | taux-i, constante | initialisation
p | facultatif à l'initialisation, 1 par défaut | taux-i, constante | initialisation
S | variable chaîne de caractères | chaîne de caractères de taux-i | initialisation

Le nombre maximum d'arguments en entrée autorisé est 256.

outtypes -- liste des types en sortie. Le format est le même que celui utilisé pour intypes.

Voici les outtypes disponibles :

Type | Description | Types de Variable Autorisés | Mise à jour
--- | --- | --- | ---
a | variable de taux-a | taux-a | taux-a
i | variable de taux-i | taux-i | initialisation
k | variable de taux-k | taux-k | taux-k
K | taux-k avec initialisation | taux-k | taux-i et taux-k

Le nombre maximum d'arguments en sortie autorisé est 256.

iksmps (facultatif, 0 par défaut) -- fixe la valeur locale de ksmps. Doit être un nombre entier positif, et le ksmps de l'instrument appelant doit être un multiple entier de cette valeur. Par exemple, si ksmps vaut 10 dans l'instrument depuis lequel l'opcode a été appelé, les valeurs permises pour iksmps sont 1, 2, 5, et 10.

Si iksmps vaut zéro, le ksmps de l'instrument ou de l'opcode appelant est utilisé (c'est le comportement par défaut).

| Note
Le ksmps local est implémenté en divisant une période de contrôle en sous-périodes-k plus petites et en modifiant temporairement les variables globales internes de Csound. Ceci nécessite aussi la conversion du taux des arguments d'entrée et de sortie de taux-k (les variables d'entrée reçoivent la même valeur dans tous les sous-périodes-k, tandis que les valeurs de sortie ne sont écrites que pendant la dernière).

| Avertissement au sujet du ksmps local
Lorsque le ksmps local est différent du ksmps de l'orchestre (celui spécifié dans l'en-tête de l'orchestre), il ne faut pas utiliser d'opération globale de taux-a dans le bloc d'opcode défini par l'utilisateur. Ceci comprend : tous les accès aux variables “ga” les opcodes zak de taux-a (zar, zaw, etc.) tablera et tablewa (ces deux opcodes peuvent fonctionner en fait, mais il faut prendre des précautions) La famille d'ocpode in et out (ils lisent depuis et écrivent dans des tampons globaux de taux-a) En général, il faut utiliser le ksmps local avec précaution car c'est une fonctionnalité expérimentale, bien qu'elle fonctionne correctement dans la plupart des cas.

L'instruction setksmps peut être utilisée pour fixer la valeur du ksmps local du bloc d'opcode défini par l'utilisateur. Elle a un paramètre de taux-i spécifiant la nouvelle valeur de ksmps (qui reste inchangée si l'on utilise zéro, voir aussi les notes au sujet de iksmps ci-dessus). setksmps doit être utilisé avant tout autre opcode (mais il est autorisé après xin), autrement des résultats imprévisibles peuvent se produire.

On peut lire les paramètres d'entrée avec l'opcode xin, et la sortie est écrite par l'opcode xout. On ne doit utiliser qu'une seule instance de ces unités, car xout écrase la sortie sans accumuler les valeurs. Le nombre et le type des arguments pour xin et xout doit être le même que dans la déclaration du bloc d'opcode défini par l'utilisateur (voir les tableaux ci-dessus).

Les arguments d'entrée et de sortie doivent se conformer à la définition à la fois en nombre (sauf si des entrées de taux-i facultatives sont utilisées) et en genre. Un paramètre d'entrée facultatif de taux-i (iksmps) est automatiquement ajouté à la liste des intypes et (comme pour setksmps) fixe la valeur du ksmps local.

## Exécution

La syntaxe d'un bloc d'opcode défini par l'utilisateur est la suivante :

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

Le nouvel opcode peut ensuite être utilisé avec la syntaxe usuelle :

    [xoutarg1] [, xoutarg2] ... [xoutargN] nom  [xinarg1] [, xinarg2] ... [xinargN] [, iksmps]

| Note
L'opcode est toujours appelé à la fois durant l'initialisation et durant l'exécution, même s'il n'y a pas d'arguments de taux-k ou -a. Si l'on sait que plusieurs opcodes définis par l'utilisateur n'ont pas d'effet durant l'exécution (taux-k) dans un instrument, on peut épargner du temps CPU en sautant ces groupes d'opcodes avec kgoto.

## Exemples

Voici un exemple d'opcode défini par l'utilisateur. Il utilise le fichier opcode.csd.

Example 559. Exemple d'opcode défini par l'utilisateur.

Voir les sections Audio en Temps Réel et Options de la Ligne de Commande pour plus d'information sur l'utilisation des options de la ligne de commande.

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

## Voir aussi

endop, setksmps, xin, xout

## Crédits

Auteur : Istvan Varga, 2002 ; basé sur du code de Matt J. Ingalls

Nouveau dans la version 4.22

Prev | Up | Next
olabuffer | Home | oscbnk