Create a CSound opcode compatible with Sympheo.

This tutorial will learn you to create or to adapt cSound instruments for Sympheo. It's absolutely essential to be familiarized to the CSound programming language. If it isn’t the case, numerous tutorials exist in the www.csounds.com site.


Here is an example of file .orc compatible with Sympheo:

--------------------------------------------------------------------------------
;1st section : specific datas to Sympheo

;< info


;<     "tutorial FM" 6

;<     1:a  = id9     "amplitude"       a
;<     2:k  = id2     "frequence"       f
;<     3:t  = id3     "carrierfact"     u     def "1.0"
;<     4:k  = id7     "modfact"         u     def 0.0     min 0.0     max 2.0
;<     5:k  = id5     "indexmod"        u     def 0.0     min 0.0     max 20.0
;<     6:t  = id1     "table"           u     def "$TABLE_SINUS"


;< endinfo

; 2nd section: Csound opcode.

opcode     tutorialFM, a, akpkkp

      aamp, kfreq, icar, kmod, kndxmod, itable xin

      a1 foscili aamp, kfreq, icar, kmod, kndxmod, itable

      xout a1

endop
--------------------------------------------------------------------------------

First of all you'll notice that the usual csound header is absent. Orc files will be automatically included in a unique csd file with a header created automatically by Sympheo at sound rendering. Every .orc must contain only a single opcode.

Then the instructions instr and endin are replaced by opcode and endop, these allow to use instruments exactly as internal opcodes in cSound, they facilitate largely the interfacing with Sympheo.

            [opcode name]       [outtypes declaration],       [intypes declaration]
opcode      tutorialFM,         a,                            akpkkp

intypes: akpkkp = 1 a-rate, 3 k-rates, 2 constants
outtypes: a = 1 a-rate channel

Parameter input and output are respectively managed by xin and xout.
In our example xin put 6 parameters of type: a,k,p,k,k et p respectively in aamp, kfreq, icar, kmod, kndxmod, itable. Types must correspond between declarations and variables.

xout sends a1 to the unique output channel.
A complete description of these instructions is present in cSound manual


Let's now study the specific section to Sympheo:

;< info


;<     "tutorial FM" 6

;<     1:a  = id9     "amplitude"       a
;<     2:k  = id2     "frequence"       f
;<     3:t  = id3     "carrierfact"     u     def "1.0"
;<     4:k  = id7     "modfact"         u     def 0.0     min 0.0     max 2.0
;<     5:k  = id5     "indexmod"        u     def 0.0     min 0.0     max 20.0
;<     6:t  = id1     "table"           u     def "$TABLE_SINUS"


;< endinfo

 

The character ' ;< ' mark beginning of any text lines used by Sympheo, this allows the cohabition of specific instructions to cSound and Sympheo, the character ' ; ' neutralizes in comment what is peculiar to Sympheo.

;< info and ;< endinfo are start and end mark to opcode parameters description block.

Comes then :


Les caractères ‘ ;< ‘ marque le début des lignes de texte utilisées par SonicDraw, ceci permet la cohabition d’instructions spécifiques à cSound et SonicDraw, le caractère ‘ ;’ neutralisant en commentaire tout ce qui est propre à SonicDraw.

;<info et ;<endinfo marque le début et la fin du bloc descriptifs des paramètres de l’opcode

vient ensuite :

;<     "tutorial FM"     6
       [module name]     [ nb param]     audioin: [nbin]     audioout:[nbout]

audioin:[nbin]: nb of audio input channel. If this parameter is omitted then nbin equal 0 by default (it is the case here)
A value > 0 implies that the opcode will be used as a sound effect. It also implies addition of [nbin] a-rates parameters in the [intype] filed of the opcode instruction.

Audioout:[nbout]: nb of audio output channel, it must be equal to the number of parameters present in the [outtypes] field of the opcode instruction. If this parameter is omitted, nbout is worth 1 by default.

IMPORTANT: (version 0.804)
[module name]: this field must still be present but is now used. Since 0.804 version Sympheo show filename instead.



then the 6 parameters description comes:

;<     1:a  = id9     "amplitude"       a
;<     2:k  = id2     "frequence"       f
;<     3:t  = id3     "carrierfact"     u     def "1.0"
;<     4:k  = id7     "modfact"         u     def 0.0     min 0.0     max 2.0
;<     5:k  = id5     "indexmod"        u     def 0.0     min 0.0     max 20.0
;<     6:t  = id1     "table"           u     def "$TABLE_SINUS"

;<    [oppar]:[opdat] = id[sppar] [name] [unit]   def [defval]   min [minval]   max [maxval]

oppar : parameter number(rank) in the opcode, from 1 to nb param. (Maximum 24)

opdat : data format send to the opcode
a = a-rate
k = k-rate
ak = a-rate & k-rate

t = constante alphanumerical constant send use as is for the opcode. A default value in quotation mark must be define absolutely, ex : def "mytext"


Sppar : ID number of the parameter in Sympheo. Place what you want from 1 to 128.

Name : the name of the parameter, to write it between quotation mark.


Unit : defines the specific type unit for Sympheo.
a = amplitude
f = frequency
u = user, in that case the values def, min, max must be defined.

Remark: for the amplitude and the frequence it's possible to specify the partial number in the following way: a1, a2, f4...


Defval : the default initialization value, must be in a range between minval and maxval

Minval and maxval : define the extreme values of the scale for the "the graphic editor" specific to this parameter.

Defval, minval and maxval are only used by the user parameter (u)



Here is an opcode example managing several input output.
Please, notice that the number of channel defined by audioin and audioout echoes directly on the opcode instruction fields [outtype] and [intypes]. This is underlined by the colour.


---------------------------------------------------------
;1st section : specific datas to Sympheo

;< info

;<     "stereo pan1" 1         audioin: 2     audioout:2

;<     1:a = id2     "pan"     u     def 0.5     min 0.0     max 1.0

;< endinfo

; 2nd section: Csound opcode.
opcode stereopan1, aa,aaa

    apan, aleft, aright  xin

    a1 = aleft*apan
    a2 = aright*(1.0-apan)

xout a1,a2

; WARNING bug si on utilise directement les params de xin en sortie.
;xout aleft*kpan, aright*(1.0-kpan)

endop
-------------------------------------------------------

CSound Tables management:

Tables hold an important role in the cSound architecture, here is how they're managed by Sympheo:

Tables serve to communicate curves data to opcodes, consequently a rigorous management of the table numbers is indispensable. To avoid any conflict with these Sympheo internal tables, user tables name can’t be a number but only an alphanumeric label.

They're declared in the following way:

;< table

;<     f $TABLE_SINUS      0 16384 10 1
;<     f $TABLE_SAWTOOTH   0 16384 7  1 16384 -1
;<     f $TABLE_SQUARE     0 512   7  1 256 1 0 -1 256 -1

;< endtable

Between the keywords ;< table and ;< endtable is the tables description according to cSound model.

Every table must be write on a single line(no return) and must begin by ;<

Replacing the table number there's a name preceded necessarily by $. This is a define for csound. Anyway there is no need to use the instruction #define since Sympheo takes care to create it automatically in .csd file after text analysis.
Other parameters are in accordance with cSound.

Where to write these tables ?

- In the common.tbl file:
Place there the global and standard tables common to several opcodes.


- In .orc files:
To create tables specific to an opcode. However they'll be finally managed globally in the same way as those from common.tbl. Thus be careful on the possible tables conflicts between opcodes and common.tbl...

Example of use:

---------------------------------------------------------
;1st section : specific datas to Sympheo

;< info

;<     "granular" 4

;<     1:a = id1     "amplitude"       a
;<     2:k = id2     "frequence"       f
;<     3:k = id3     "density"         u     def 100   min .01   max 2000
;<     4:k = id4     "freq offset"     u     def .5    min 0     max 1


;< endinfo


; specific tables to this opcode.
;< table

;<     f $TABLE_WFRM         0 1024 10 1 0 .2 .2 .03 .12 .22 .11 .022 .0101 .0167
;<     f $TABLE_GRAIN_ENVEL1 0 1024 8 0 512 1 512 0

;< endtable


; 2nd
section: Csound opcode.
opcode grain, a, akkk

    aampl, kfrq, kdens, kfoff xin

    a1 grain aampl,kfrq, kdens, 10000, kfrq* kfoff, .2, $TABLE_WFRM, $TABLE_GRAIN_ENVEL1, 5

    xout a1

endop
---------------------------------------------------------



Cet autre exemple met en évidence l’utilisation du numéro de partielle (optionel). Il permet, lors de l’édition graphique de ce paramètre, de dessiner directement des courbes proportionnellement à la fondamentale suivant son rang harmonique. Par défaut le numéro de partielle = 1 soit la fondamentale.
Ici nous avons 8 ondes sinusoidales correspondant à la fondamentale plus 7 partielles, elles sont paramètrées chacune par 2 courbes (amplitude et fréquence).
---------------------------------------------------------
;1st section : specific datas to Sympheo

;<info

;< "additive synth8" 16
;<       1:a = id1       "amplitude1"       a1       ;amplitude fondamentale
;<       2:a = id2       "amplitude2"       a2       ; partielle de rang 2
;<       3:a = id3       "amplitude3"       a3       ; partielle de rang 3
;<       4:a = id4       "amplitude4"       a4       ; etc...
;<       5:a = id5       "amplitude5"       a5
;<       6:a = id6       "amplitude6"       a6
;<       7:a = id7       "amplitude7"       a7
;<       8:a = id8       "amplitude8"       a8

;<       9:a = id21        "frequence1"     f1 ;frequence fondamentale
;<       10:a = id22       "frequence2"     f2 ; partielle de rang 2
;<       11:a = id23       "frequence3"     f3 ; partielle de rang 3
;<       12:a = id24       "frequence4"     f4 ; etc...
;<       13:a = id25       "frequence5"     f5
;<       14:a = id26       "frequence6"     f6
;<       15:a = id27       "frequence7"     f7
;<       16:a = id28       "frequence8"     f8

;<endinfo

; 2nd section: Csound opcode.
opcode addsynth8, a,aaaaaaaaaaaaaaaa

      aampl1, aampl2, aampl3, aampl4, aampl5, aampl6, aampl7, aampl8, afreq1, afreq2, afreq3, afreq4, afreq5, afreq6, afreq7, afreq8 xin

      a2 = 0

      a1 oscil aampl1, afreq1, $TABLE_SINUS ; fondamentale
      a2 = a2 + a1

      a1 oscil aampl2, afreq2, $TABLE_SINUS ; partielle de rang 2
      a2 = a2 + a1

      a1 oscil aampl3, afreq3, $TABLE_SINUS ; partielle de rang 3
      a2 = a2 + a1

      a1 oscil aampl4, afreq4, $TABLE_SINUS ; etc...
      a2 = a2 + a1

      a1 oscil aampl5, afreq5, $TABLE_SINUS
      a2 = a2 + a1

      a1 oscil aampl6, afreq6, $TABLE_SINUS
      a2 = a2 + a1

      a1 oscil aampl7, afreq7, $TABLE_SINUS
      a2 = a2 + a1

      a1 oscil aampl8, afreq8, $TABLE_SINUS
      a2 = a2 + a1

      xout a2

endop
-------------------------------------------------------