FLOSS Manuals

 English |  Español |  Français |  Italiano |  Português |  Русский |  Shqip

CSOUND Español

Csound: CONTROLSTRUCTURES

CONTROL STRUCTURES

In a way, control structures are the core of a programming language. The fundamental element in each language is the conditional if branch. Actually all other control structures like for-, until- or while-loops can be traced back to if-statements.

En cierto modo, las estructuras de control son el núcleo de un lenguaje de programación. El elemento fundamental en cada lengua es el condicional si rama. En realidad, todas las demás estructuras de control como for-, until o while-loops pueden rastrearse hasta if-statements.

 

So, Csound provides mainly the if-statement; either in the usual if-then-else form, or in the older way of an if-goto statement. These will be covered first. Though all necessary loops can be built just by if-statements, Csound's while, until and loop facility offer a more comfortable way of performing loops. They will be introduced later, in the Loop and the While / Until section of this chapter. Finally, time loops are shown, which are particulary important in audio programming languages.

Por lo tanto, Csound proporciona principalmente la instrucción if; Ya sea en la forma usual if-then-else, o en la forma más antigua de una sentencia if-goto. Estos serán cubiertos en primer lugar. Aunque todos los bucles necesarios pueden ser construidos por if-statements, Csounds while, hasta y loop facility ofrecen una forma más cómoda de realizar bucles. Se presentarán más adelante, en la sección Loop y en la sección While / Until de este capítulo. Finalmente, se muestran los bucles de tiempo, que son particularmente importantes en los lenguajes de programación de audio.

If i-Time Then Not k-Time!

The fundamental difference in Csound between i-time and k-time which has been explained in chapter 03A, must be regarded very carefully when you work with control structures. If you make a conditional branch at i-time, the condition will be tested just once for each note, at the initialization pass. If you make a conditional branch at k-time, the condition will be tested again and again in each control-cycle.

La diferencia fundamental en Csound entre i-time y k-time que se ha explicado en el capítulo 03A, debe considerarse con mucho cuidado cuando se trabaja con estructuras de control. Si realiza una rama condicional en i-time, la condición se probará una vez para cada nota, en el paso de inicialización. Si usted hace una rama condicional en k-tiempo, la condición será probada una y otra vez en cada ciclo de control.

For instance, if you test a soundfile whether it is mono or stereo, this is done at init-time. If you test an amplitude value to be below a certain threshold, it is done at performance time (k-time). If you get user-input by a scroll number, this is also a k-value, so you need a k-condition.

Por ejemplo, si prueba un archivo de sonido si es mono o estéreo, esto se hace a init-time. Si se prueba un valor de amplitud por debajo de cierto umbral, se realiza en el tiempo de ejecución (k-time). Si obtiene la entrada de usuario por un número de desplazamiento, esto también es un valor k, por lo que necesita una condición k.

Thus, all if and loop opcodes have an "i" and a "k" descendant. In the next few sections, a general introduction into the different control tools is given, followed by examples both at i-time and at k-time for each tool.

Por lo tanto, todos los opcodes if y loop poseen un i y un descendiente k. En las siguientes secciones, se proporciona una introducción general a las diferentes herramientas de control, seguida de ejemplos tanto en i-tiempo como en k-time para cada herramienta.

If - then - [elseif - then -] else

The use of the if-then-else statement is very similar to other programming languages. Note that in Csound, "then" must be written in the same line as "if" and the expression to be tested, and that you must close the if-block with an "endif" statement on a new line:

El uso de la instrucción if-then-else es muy similar a otros lenguajes de programación. Tenga en cuenta que en Csound, entonces debe escribirse en la misma línea que if y la expresión a probar, y que debe cerrar el if-block con una instrucción endif en una nueva línea:

if <condition> then
...
else
...
endif

It is also possible to have no "else" statement:

También es posible no tener otra declaración:

if <condition> then
...
endif

Or you can have one or more "elseif-then" statements in between:

O puede tener una o más declaraciones elseif-then entre ellas:

if <condition1> then

...
elseif <condition2> then
...
else
...
endif

If statements can also be nested. Each level must be closed with an "endif". This is an example with three levels:

Si las sentencias también pueden anidarse. Cada nivel debe estar cerrado con un endif. Este es un ejemplo con tres niveles:

if <condition1> then; first condition opened
 if <condition2> then; second condition openend
  if <condition3> then; third condition openend
  ...
  else
  ...
  endif; third condition closed
 elseif <condition2a> then
 ...
 endif; second condition closed
else
...
endif; first condition closed

i-Rate Examples

A typical problem in Csound: You have either mono or stereo files, and want to read both with a stereo output. For the real stereo ones that means: use soundin (diskin / diskin2) with two output arguments. For the mono ones it means: use soundin / diskin / diskin2 with one output argument, and throw it to both output channels:

Un problema típico en Csound: Usted tiene archivos mono o estéreo, y quiere leer ambos con una salida estéreo. Para los estereofónicos reales que significa: use soundin (diskin / diskin2) con dos argumentos de salida. Para los mono esto significa: use soundin / diskin / diskin2 con un argumento de salida, y lánzalo a ambos canales de salida:

   EXAMPLE 03C01_IfThen_i.csd 

<CsoundSynthesizer>
<CsOptions>
-o dac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

  instr 1
Sfile     =          "/my/file.wav" ;your soundfile path here
ifilchnls filenchnls Sfile
 if ifilchnls == 1 then ;mono
aL        soundin    Sfile
aR        =          aL
 else	;stereo
aL, aR    soundin    Sfile
 endif
          outs       aL, aR
  endin

</CsInstruments>
<CsScore>
i 1 0 5
</CsScore>
</CsoundSynthesizer>

If you use CsoundQt, you can browse in the widget panel for the soundfile. See the corresponding example in the CsoundQt Example menu.

Si utiliza CsoundQt, puede explorar el panel de widgets para el archivo de sonido. Consulte el ejemplo correspondiente en el menú de ejemplo CsoundQt.

k-Rate Examples

The following example establishes a moving gate between 0 and 1. If the gate is above 0.5, the gate opens and you hear a tone. If the gate is equal or below 0.5, the gate closes, and you hear nothing.

El siguiente ejemplo establece una puerta móvil entre 0 y 1. Si la compuerta está por encima de 0,5, la compuerta se abre y se oye un tono. Si la compuerta es igual o inferior a 0,5, la compuerta se cierra y no se oye nada.

   EXAMPLE 03C02_IfThen_k.csd 

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

          seed      0; random values each time different
giTone    ftgen     0, 0, 2^10, 10, 1, .5, .3, .1

  instr 1

; move between 0 and 1 (3 new values per second)
kGate     randomi   0, 1, 3
; move between 300 and 800 hz (1 new value per sec)
kFreq     randomi   300, 800, 1
; move between -12 and 0 dB (5 new values per sec)
kdB       randomi   -12, 0, 5
aSig      oscil3    1, kFreq, giTone
kVol      init      0
 if kGate > 0.5 then; if kGate is larger than 0.5
kVol      =         ampdb(kdB); open gate
 else
kVol      =         0; otherwise close gate
 endif
kVol      port      kVol, .02; smooth volume curve to avoid clicks
aOut      =         aSig * kVol
          outs      aOut, aOut
  endin

</CsInstruments>
<CsScore>
i 1 0 30
</CsScore>
</CsoundSynthesizer>

Short Form: (a v b ? x : y)

If you need an if-statement to give a value to an (i- or k-) variable, you can also use a traditional short form in parentheses: (a v b ? x : y).1 It asks whether the condition a or b is true. If a, the value is set to x; if b, to y. For instance, the last example could be written in this way:

Si necesita una instrucción if para dar un valor a una variable (i- o k-), también puede usar un formulario corto tradicional entre paréntesis: (avb? X: y) .1 Pregunta si la condición a o b es verdad. Si a, el valor se establece en x; Si b, a y. Por ejemplo, el último ejemplo podría escribirse de esta manera:

   EXAMPLE 03C03_IfThen_short_form.csd 

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

          seed      0
giTone    ftgen     0, 0, 2^10, 10, 1, .5, .3, .1

  instr 1
kGate     randomi   0, 1, 3; moves between 0 and 1 (3 new values per second)
kFreq     randomi   300, 800, 1; moves between 300 and 800 hz
                               ;(1 new value per sec)
kdB       randomi   -12, 0, 5; moves between -12 and 0 dB
                             ;(5 new values per sec)
aSig      oscil3    1, kFreq, giTone
kVol      init      0
kVol      =         (kGate > 0.5 ? ampdb(kdB) : 0); short form of condition
kVol      port      kVol, .02; smooth volume curve to avoid clicks
aOut      =         aSig * kVol
          outs      aOut, aOut
  endin

</CsInstruments>
<CsScore>
i 1 0 20
</CsScore>
</CsoundSynthesizer>

If - goto

An older way of performing a conditional branch - but still useful in certain cases - is an "if" statement which is not followed by a "then", but by a label name. The "else" construction follows (or doesn't follow) in the next line. Like the if-then-else statement, the if-goto works either at i-time or at k-time. You should declare the type by either using igoto or kgoto. Usually you need an additional igoto/kgoto statement for omitting the "else" block if the first condition is true. This is the general syntax:

Una forma más antigua de realizar una rama condicional, pero aún útil en ciertos casos, es una instrucción if que no es seguida por un then, sino por un nombre de etiqueta. La otra construcción sigue (o no sigue) en la línea siguiente. Al igual que la instrucción if-then-else, el if-goto funciona en i-time o en k-time. Debe declarar el tipo utilizando igoto o kgoto. Por lo general, necesita una instrucción igoto / kgoto adicional para omitir el bloque else si la primera condición es verdadera. Esta es la sintaxis general:

i-time

if <condition> igoto this; same as if-then
 igoto that; same as else
this: ;the label "this" ...
...
igoto continue ;skip the "that" block
that: ; ... and the label "that" must be found
...
continue: ;go on after the conditional branch
...

k-time

if <condition> kgoto this; same as if-then
 kgoto that; same as else
this: ;the label "this" ...
...
kgoto continue ;skip the "that" block
that: ; ... and the label "that" must be found
...
continue: ;go on after the conditional branch
...

i-Rate Examples

This is the same example as above in the if-then-else syntax for a branch depending on a mono or stereo file. If you just want to know whether a file is mono or stereo, you can use the "pure" if-igoto statement:

Este es el mismo ejemplo que el anterior en la sintaxis if-then-else para una rama dependiendo de un archivo mono o estéreo. Si sólo desea saber si un archivo es mono o estéreo, puede utilizar la instrucción if-igoto pura:

   EXAMPLE 03C04_IfGoto_i.csd 

<CsoundSynthesizer>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

  instr 1
Sfile     = "/Joachim/Materialien/SamplesKlangbearbeitung/Kontrabass.aif"
ifilchnls filenchnls Sfile
if ifilchnls == 1 igoto mono; condition if true
 igoto stereo; else condition
mono:
          prints     "The file is mono!%n"
          igoto      continue
stereo:
          prints     "The file is stereo!%n"
continue:
  endin

</CsInstruments>
<CsScore>
i 1 0 0
</CsScore>
</CsoundSynthesizer>

But if you want to play the file, you must also use a k-rate if-kgoto, because, not only do you have an event at i-time (initializing the soundin opcode) but also at k-time (producing an audio signal). So the code in this case is much more cumbersome, or obfuscated, than the previous if-then-else example.

Pero si quieres reproducir el archivo, también debes usar k-rate if-kgoto, porque no solo tienes un evento en i-time (inicializando el opcode de soundin), sino también en k-time (produciendo un audio señal). Por lo tanto, el código en este caso es mucho más engorroso u ofuscado que el anterior ejemplo if-then-else.

   EXAMPLE 03C05_IfGoto_ik.csd 

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

  instr 1
Sfile     =          "my/file.wav"
ifilchnls filenchnls Sfile
 if ifilchnls == 1 kgoto mono
  kgoto stereo
 if ifilchnls == 1 igoto mono; condition if true
  igoto stereo; else condition
mono:
aL        soundin    Sfile
aR        =          aL
          igoto      continue
          kgoto      continue
stereo:
aL, aR    soundin    Sfile
continue:
          outs       aL, aR
  endin

</CsInstruments>
<CsScore>
i 1 0 5
</CsScore>
</CsoundSynthesizer>

k-Rate Examples

This is the same example as above (03C02) in the if-then-else syntax for a moving gate between 0 and 1:

 

Este es el mismo ejemplo que el anterior (03C02) en la sintaxis if-then-else para una puerta en movimiento entre 0 y 1:

   EXAMPLE 03C06_IfGoto_k.csd 

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

          seed      0
giTone    ftgen     0, 0, 2^10, 10, 1, .5, .3, .1

  instr 1
kGate     randomi   0, 1, 3; moves between 0 and 1 (3 new values per second)
kFreq     randomi   300, 800, 1; moves between 300 and 800 hz
                              ;(1 new value per sec)
kdB       randomi   -12, 0, 5; moves between -12 and 0 dB
                             ;(5 new values per sec)
aSig      oscil3    1, kFreq, giTone
kVol      init      0
 if kGate > 0.5 kgoto open; if condition is true
  kgoto close; "else" condition
open:
kVol      =         ampdb(kdB)
kgoto continue
close:
kVol      =         0
continue:
kVol      port      kVol, .02; smooth volume curve to avoid clicks
aOut      =         aSig * kVol
          outs      aOut, aOut
  endin

</CsInstruments>
<CsScore>
i 1 0 30
</CsScore>
</CsoundSynthesizer>

Loops

Loops can be built either at i-time or at k-time just with the "if" facility. The following example shows an i-rate and a k-rate loop created using the if-i/kgoto facility:

Los bucles pueden ser construidos ya sea en i-time o en k-time sólo con la instalación if. El siguiente ejemplo muestra un bucle i-rate y k-rate creado usando la función if-i / kgoto:

   EXAMPLE 03C07_Loops_with_if.csd 

<CsoundSynthesizer>
<CsInstruments>
;Example by Joachim Heintz

  instr 1 ;i-time loop: counts from 1 until 10 has been reached
icount    =         1
count:
          print     icount
icount    =         icount + 1
 if icount < 11 igoto count
          prints    "i-END!%n"
  endin

  instr 2 ;k-rate loop: counts in the 100th k-cycle from 1 to 11
kcount    init      0
ktimek    timeinstk ;counts k-cycle from the start of this instrument
 if ktimek == 100 kgoto loop
  kgoto noloop
loop:
          printks   "k-cycle %d reached!%n", 0, ktimek
kcount    =         kcount + 1
          printk2   kcount
 if kcount < 11 kgoto loop
          printks   "k-END!%n", 0
noloop:
  endin

</CsInstruments>
<CsScore>
i 1 0 0
i 2 0 1
</CsScore>
</CsoundSynthesizer>

But Csound offers a slightly simpler syntax for this kind of i-rate or k-rate loops. There are four variants of the loop opcode. All four refer to a label as the starting point of the loop, an index variable as a counter, an increment or decrement, and finally a reference value (maximum or minimum) as comparision:

Pero Csound ofrece una sintaxis ligeramente más simple para este tipo de bucles de i-rate o k-rate. Hay cuatro variantes del código de bucle. Los cuatro se refieren a una etiqueta como punto de partida del bucle, una variable de índice como un contador, un incremento o decremento y finalmente un valor de referencia (máximo o mínimo) como comparación:

  • loop_lt counts upwards and looks if the index variable is lower than the reference value;
  • Loop_lt cuenta hacia arriba y busca si la variable de índice es menor que el valor de referencia;
  • loop_le also counts upwards and looks if the index is lower than or equal to the reference value;
  • Loop_le también cuenta hacia arriba y busca si el índice es menor o igual al valor de referencia;
  • loop_gt counts downwards and looks if the index is greater than the reference value;
  • Loop_gt cuenta hacia abajo y busca si el índice es mayor que el valor de referencia;
  • loop_ge also counts downwards and looks if the index is greater than or equal to the reference value.
  • Loop_ge también cuenta hacia abajo y busca si el índice es mayor o igual al valor de referencia.

As always, all four opcodes can be applied either at i-time or at k-time. Here are some examples, first for i-time loops, and then for k-time loops.

Como siempre, los cuatro opcodes se pueden aplicar en i-time o en k-time. Aquí hay algunos ejemplos, primero para bucles de i-tiempo, y luego para k-tiempo bucles.

i-Rate Examples

The following .csd provides a simple example for all four loop opcodes:

El siguiente .csd proporciona un ejemplo sencillo para los cuatro opcodes de bucle:

   EXAMPLE 03C08_Loop_opcodes_i.csd 

<CsoundSynthesizer>
<CsInstruments>
;Example by Joachim Heintz

  instr 1 ;loop_lt: counts from 1 upwards and checks if < 10
icount    =         1
loop:
          print     icount
          loop_lt   icount, 1, 10, loop
          prints    "Instr 1 terminated!%n"
  endin

  instr 2 ;loop_le: counts from 1 upwards and checks if <= 10
icount    =         1
loop:
          print     icount
          loop_le   icount, 1, 10, loop
          prints    "Instr 2 terminated!%n"
  endin

  instr 3 ;loop_gt: counts from 10 downwards and checks if > 0
icount    =         10
loop:
          print     icount
          loop_gt   icount, 1, 0, loop
          prints    "Instr 3 terminated!%n"
  endin

  instr 4 ;loop_ge: counts from 10 downwards and checks if >= 0
icount    =         10
loop:
          print     icount
          loop_ge   icount, 1, 0, loop
          prints    "Instr 4 terminated!%n"
  endin

</CsInstruments>
<CsScore>
i 1 0 0
i 2 0 0
i 3 0 0
i 4 0 0
</CsScore>
</CsoundSynthesizer>

The next example produces a random string of 10 characters and prints it out:

El siguiente ejemplo produce una cadena aleatoria de 10 caracteres e imprime:

   EXAMPLE 03C09_Random_string.csd 

<CsoundSynthesizer>
<CsInstruments>
;Example by Joachim Heintz

  instr 1
icount    =         0
Sname     =         ""; starts with an empty string
loop:
ichar     random    65, 90.999
Schar     sprintf   "%c", int(ichar); new character
Sname     strcat    Sname, Schar; append to Sname
          loop_lt   icount, 1, 10, loop; loop construction
          printf_i  "My name is '%s'!\n", 1, Sname; print result
  endin

</CsInstruments>
<CsScore>
; call instr 1 ten times
r 10
i 1 0 0
</CsScore>
</CsoundSynthesizer>

You can also use an i-rate loop to fill a function table (= buffer) with any kind of values. This table can then be read, or manipulated and then be read again. In the next example, a function table with 20 positions (indices) is filled with random integers between 0 and 10 by instrument 1. Nearly the same loop construction is used afterwards to read these values by instrument 2.

También puede utilizar un bucle i-rate para llenar una tabla de funciones (= buffer) con cualquier tipo de valores. Esta tabla puede ser leída o manipulada y leída de nuevo. En el siguiente ejemplo, una tabla de funciones con 20 posiciones (índices) se rellena con números enteros aleatorios entre 0 y 10 por el instrumento 1. Casi la misma construcción de bucle se utiliza después para leer estos valores por el instrumento 2.

   EXAMPLE 03C10_Random_ftable_fill.csd 

<CsoundSynthesizer>
<CsInstruments>
;Example by Joachim Heintz

giTable   ftgen     0, 0, -20, -2, 0; empty function table with 20 points
          seed      0; each time different seed

  instr 1 ; writes in the table
icount    =         0
loop:
ival      random    0, 10.999 ;random value
; --- write in giTable at first, second, third ... position
          tableiw   int(ival), icount, giTable
          loop_lt   icount, 1, 20, loop; loop construction
  endin

  instr 2; reads from the table
icount    =         0
loop:
; --- read from giTable at first, second, third ... position
ival      tablei    icount, giTable
          print     ival; prints the content
          loop_lt   icount, 1, 20, loop; loop construction
  endin

</CsInstruments>
<CsScore>
i 1 0 0
i 2 0 0
</CsScore>
</CsoundSynthesizer>

k-Rate Examples

The next example performs a loop at k-time. Once per second, every value of an existing function table is changed by a random deviation of 10%. Though there are some vectorial opcodes for this task (and in Csound 6 probably array), it can also be done by a k-rate loop like the one shown here:

El siguiente ejemplo realiza un bucle en k-time. Una vez por segundo, cada valor de una tabla de funciones existente se cambia por una desviación aleatoria de 10%. Aunque hay algunos opcodes vectoriales para esta tarea (y en Csound 6 probablemente matriz), también puede hacerse mediante un k-rate loop como el mostrado aquí:

   EXAMPLE 03C11_Table_random_dev.csd 

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 441
nchnls = 2
0dbfs = 1

giSine    ftgen     0, 0, 256, 10, 1; sine wave
          seed      0; each time different seed

  instr 1
ktiminstk timeinstk ;time in control-cycles
kcount    init      1
 if ktiminstk == kcount * kr then; once per second table values manipulation:
kndx      =         0
loop:
krand     random    -.1, .1;random factor for deviations
kval      table     kndx, giSine; read old value
knewval   =         kval + (kval * krand); calculate new value
          tablew    knewval, kndx, giSine; write new value
          loop_lt   kndx, 1, 256, loop; loop construction
kcount    =         kcount + 1; increase counter
 endif
asig      poscil    .2, 400, giSine
          outs      asig, asig
  endin

</CsInstruments>
<CsScore>
i 1 0 10
</CsScore>
</CsoundSynthesizer>

 

While / Until

Since the release of Csound 6, it has been possible to write loops in a manner similar to that used by many other programming languages, using the keywords while or until. The general syntax is:2

Desde el lanzamiento de Csound 6, ha sido posible escribir bucles de una manera similar a la utilizada por muchos otros lenguajes de programación, usando las palabras clave mientras o hasta. La sintaxis general es: 2

while <condition> do

   ...
od
until <condition> do
   ...
od

The body of the while loop will be performed again and again, as long as is true. The body of the until loop will be performed, as long as is false (not true). This is a simple example at i-rate:

El cuerpo del bucle while se realizará una y otra vez, siempre y cuando la condición sea verdadera. El cuerpo del bucle hasta se realizará, siempre y cuando la condición sea falsa (no es verdadera). Este es un ejemplo simple en i-rate:

   EXAMPLE 03C12_while_until_i-rate.csd 

<CsoundSynthesizer>
<CsOptions>
-nm0
</CsOptions>
<CsInstruments>
ksmps = 32

instr 1
iCounter = 0
while iCounter < 5 do
  print iCounter
iCounter += 1
od
prints "\n"
endin

instr 2
iCounter = 0
until iCounter >= 5 do
  print iCounter
iCounter += 1
od
endin

</CsInstruments>
<CsScore>
i 1 0 .1
i 2 .1 .1
</CsScore>
</CsoundSynthesizer>
;example by joachim heintz

Prints:

instr 1:  iprint = 0.000
instr 1:  iprint = 1.000
instr 1:  iprint = 2.000
instr 1:  iprint = 3.000
instr 1:  iprint = 4.000

instr 2:  iprint = 0.000
instr 2:  iprint = 1.000
instr 2:  iprint = 2.000
instr 2:  iprint = 3.000
instr 2:  iprint = 4.000

The most important thing in using the while/until loop is to increment the variable you are using in the loop (here: iCounter). This is done by the statement

Lo más importante al usar el bucle while / until es incrementar la variable que está utilizando en el bucle (aquí: iCounter). Esto se hace mediante la declaración

iCounter += 1

which is equivalent to the "old" way of writing as

Que es equivalente a la vieja manera de escribir como

iCounter = iCounter + 1

If you miss this increment, Csound will perform an endless loop, and you will have to terminate it by the operating system.

Si pierde este incremento, Csound realizará un bucle interminable, y tendrá que terminarlo por el sistema operativo.

The next example shows a similar process at k-rate. It uses a while loop to print the values of an array, and also set new values. As this procedure is repeated in each control cycle, the instrument is being turned off after the third cycle.

El siguiente ejemplo muestra un proceso similar a k-rate. Utiliza un bucle while para imprimir los valores de una matriz y también establece nuevos valores. Como este procedimiento se repite en cada ciclo de control, el instrumento se apaga después del tercer ciclo.

   EXAMPLE 03C13_while_until_k-rate.csd  

<CsoundSynthesizer>
<CsOptions>
-nm0
</CsOptions>
<CsInstruments>
ksmps = 32

  ;create and fill an array
gkArray[] fillarray 1, 2, 3, 4, 5

instr 1
  ;count performance cycles and print it
kCycle timeinstk
printks "kCycle = %d\n", 0, kCycle
  ;set index to zero
kIndex = 0
  ;perform the loop
while kIndex < lenarray(gkArray) do
    ;print array value
  printf "  gkArray[%d] = %d\n", kIndex+1, kIndex, gkArray[kIndex]
    ;square array value
  gkArray[kIndex] = gkArray[kIndex] * gkArray[kIndex]
  ;increment index
kIndex += 1
od
  ;stop after third control cycle
if kCycle == 3 then
  turnoff
endif
endin

</CsInstruments>
<CsScore>
i 1 0 1
</CsScore>
</CsoundSynthesizer>
;example by joachim heintz

Prints:

kCycle = 1
  gkArray[0] = 1
  gkArray[1] = 2
  gkArray[2] = 3
  gkArray[3] = 4
  gkArray[4] = 5
kCycle = 2
  gkArray[0] = 1
  gkArray[1] = 4
  gkArray[2] = 9
  gkArray[3] = 16
  gkArray[4] = 25
kCycle = 3
  gkArray[0] = 1
  gkArray[1] = 16
  gkArray[2] = 81
  gkArray[3] = 256
  gkArray[4] = 625

Time Loops

Until now, we have just discussed loops which are executed "as fast as possible", either at i-time or at k-time. But, in an audio programming language, time loops are of particular interest and importance. A time loop means, repeating any action after a certain amount of time. This amount of time can be equal to or different to the previous time loop. The action can be, for instance: playing a tone, or triggering an instrument, or calculating a new value for the movement of an envelope.

Hasta ahora, acabamos de hablar de loops que se ejecutan lo más rápido posible, ya sea en i-time o en k-time. Pero, en un lenguaje de programación de audio, los bucles de tiempo son de particular interés e importancia. Un lazo de tiempo significa repetir cualquier acción después de cierto tiempo. Esta cantidad de tiempo puede ser igual o diferente al bucle de tiempo anterior. La acción puede ser, por ejemplo: tocar un tono, activar un instrumento o calcular un nuevo valor para el movimiento de un sobre.

In Csound, the usual way of performing time loops, is the timout facility. The use of timout is a bit intricate, so some examples are given, starting from very simple to more complex ones.

En Csound, la forma habitual de realizar bucles de tiempo, es la facilidad de tiempo. El uso de timout es un poco intrincado, por lo que algunos ejemplos se dan, a partir de muy simple a los más complejos.

Another way of performing time loops is by using a measurement of time or k-cycles. This method is also discussed and similar examples to those used for the timout opcode are given so that both methods can be compared.

Otra forma de realizar bucles de tiempo es usando una medición de tiempo o ciclos k. Este método también se discute y se dan ejemplos similares a los utilizados para el código de operación de temporización para que ambos métodos puedan compararse.

timout Basics

The timout opcode refers to the fact that in the traditional way of working with Csound, each "note" (an "i" score event) has its own time. This is the duration of the note, given in the score by the duration parameter, abbreviated as "p3". A timout statement says: "I am now jumping out of this p3 duration and establishing my own time." This time will be repeated as long as the duration of the note allows it.

El opcode timout se refiere al hecho de que en la forma tradicional de trabajar con Csound, cada nota (un evento de puntuación i) tiene su propio tiempo. Esta es la duración de la nota, dada en la partitura por el parámetro duración, abreviado como p3. Una declaración de timout dice: Ahora estoy saltando de esta duración de p3 y estableciendo mi propio tiempo. Este tiempo se repetirá siempre y cuando la duración de la nota lo permita.

Let's see an example. This is a sine tone with a moving frequency, starting at 400 Hz and ending at 600 Hz. The duration of this movement is 3 seconds for the first note, and 5 seconds for the second note:

Veamos un ejemplo. Se trata de un tono seno con una frecuencia de movimiento, que comienza en 400 Hz y termina en 600 Hz. La duración de este movimiento es de 3 segundos para la primera nota y de 5 segundos para la segunda nota:

   EXAMPLE 03C14_Timout_pre.csd 

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

giSine    ftgen     0, 0, 2^10, 10, 1

  instr 1
kFreq     expseg    400, p3, 600
aTone     poscil    .2, kFreq, giSine
          outs      aTone, aTone
  endin

</CsInstruments>
<CsScore>
i 1 0 3
i 1 4 5
</CsScore>
</CsoundSynthesizer>

Now we perform a time loop with timout which is 1 second long. So, for the first note, it will be repeated three times, and five times for the second note:

Ahora realizamos un bucle de tiempo con temporización que es de 1 segundo de largo. Por lo tanto, para la primera nota, se repetirá tres veces y cinco veces para la segunda nota:

   EXAMPLE 03C15_Timout_basics.csd 

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

giSine    ftgen     0, 0, 2^10, 10, 1

  instr 1
loop:
          timout    0, 1, play
          reinit    loop
play:
kFreq     expseg    400, 1, 600
aTone     poscil    .2, kFreq, giSine
          outs      aTone, aTone
  endin

</CsInstruments>
<CsScore>
i 1 0 3
i 1 4 5
</CsScore>
</CsoundSynthesizer>

This is the general syntax of timout:

Esta es la sintaxis general de timout:

 

first_label:
          timout    istart, idur, second_label
          reinit    first_label
second_label:
... <any action you want to have here>

The first_label is an arbitrary word (followed by a colon) to mark the beginning of the time loop section. The istart argument for timout tells Csound, when the second_label section is to be executed. Usually istart is zero, telling Csound: execute the second_label section immediately, without any delay. The idur argument for timout defines for how many seconds the second_label section is to be executed before the time loop begins again. Note that the reinit first_label is necessary to start the second loop after idur seconds with a resetting of all the values. (See the explanations about reinitialization in the chapter Initialization And Performance Pass section 03A.)

La primera etiqueta es una palabra arbitraria (seguida de dos puntos) para marcar el comienzo de la sección de lazo de tiempo. El argumento istart para timout le dice a Csound, cuando se va a ejecutar la sección second_label. Usualmente istart es cero, diciéndole a Csound: ejecute la sección second_label inmediatamente, sin demora alguna. El argumento idur para timout define durante cuántos segundos la sección second_label debe ejecutarse antes de que el bucle de tiempo comience de nuevo. Tenga en cuenta que el reinit first_label es necesario para iniciar el segundo bucle después de idur segundos con un restablecimiento de todos los valores. (Consulte las explicaciones sobre la reinicialización en el capítulo Inicialización y paso de rendimiento, sección 03A).

As usual when you work with the reinit opcode, you can use a rireturn statement to constrain the reinit-pass. In this way you can have both, the timeloop section and the non-timeloop section in the body of an instrument:

Como de costumbre cuando se trabaja con el opcode reinit, se puede usar una sentencia rireturn para restringir el reinit-pass. De esta manera puede tener tanto la sección timeloop como la sección no timeloop en el cuerpo de un instrumento:

   EXAMPLE 03C16_Timeloop_and_not.csd 

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

giSine    ftgen     0, 0, 2^10, 10, 1

  instr 1
loop:
          timout    0, 1, play
          reinit    loop
play:
kFreq1    expseg    400, 1, 600
aTone1    oscil3    .2, kFreq1, giSine
          rireturn  ;end of the time loop
kFreq2    expseg    400, p3, 600
aTone2    poscil    .2, kFreq2, giSine

          outs      aTone1+aTone2, aTone1+aTone2
  endin

</CsInstruments>
<CsScore>
i 1 0 3
i 1 4 5
</CsScore>
</CsoundSynthesizer>

timout Applications

In a time loop, it is very important to change the duration of the loop. This can be done either by referring to the duration of this note (p3) ...

En un bucle de tiempo, es muy importante cambiar la duración del bucle. Esto puede hacerse refiriéndose a la duración de esta nota (p3) ...

   EXAMPLE 03C17_Timout_different_durations.csd 

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

giSine    ftgen     0, 0, 2^10, 10, 1

  instr 1
loop:
          timout    0, p3/5, play
          reinit    loop
play:
kFreq     expseg    400, p3/5, 600
aTone     poscil    .2, kFreq, giSine
          outs      aTone, aTone
  endin

</CsInstruments>
<CsScore>
i 1 0 3
i 1 4 5
</CsScore>
</CsoundSynthesizer>

... or by calculating new values for the loop duration on each reinit pass, for instance by random values:

... o calculando nuevos valores para la duración del bucle en cada paso reinit, por ejemplo mediante valores aleatorios:

   EXAMPLE 03C18_Timout_random_durations.csd 

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

giSine    ftgen     0, 0, 2^10, 10, 1

  instr 1
loop:
idur      random    .5, 3 ;new value between 0.5 and 3 seconds each time
          timout    0, idur, play
          reinit    loop
play:
kFreq     expseg    400, idur, 600
aTone     poscil    .2, kFreq, giSine
          outs      aTone, aTone
  endin

</CsInstruments>
<CsScore>
i 1 0 20
</CsScore>
</CsoundSynthesizer>

The applications discussed so far have the disadvantage that all the signals inside the time loop must definitely be finished or interrupted, when the next loop begins. In this way it is not possible to have any overlapping of events. To achieve this, the time loop can be used to simply trigger an event. This can be done with event_i or scoreline_i. In the following example, the time loop in instrument 1 triggers a new instance of instrument 2 with a duration of 1 to 5 seconds, every 0.5 to 2 seconds. So in most cases, the previous instance of instrument 2 will still be playing when the new instance is triggered. Random calculations are executed in instrument 2 so that each note will have a different pitch,creating a glissando effect:

Las aplicaciones discutidas hasta ahora tienen la desventaja de que todas las señales dentro del bucle de tiempo definitivamente deben ser terminadas o interrumpidas, cuando comienza el siguiente bucle. De esta manera no es posible tener ninguna superposición de eventos. Para lograr esto, el bucle de tiempo puede usarse para simplemente disparar un evento. Esto se puede hacer con event_i o scoreline_i. En el ejemplo siguiente, el bucle de tiempo del instrumento 1 activa una nueva instancia del instrumento 2 con una duración de 1 a 5 segundos, cada 0,5 a 2 segundos. Por lo tanto, en la mayoría de los casos, la instancia anterior del instrumento 2 seguirá reproduciéndose cuando se active la nueva instancia. Los cálculos aleatorios se ejecutan en el instrumento 2 para que cada nota tenga un tono diferente, creando un efecto glissando:

 

   EXAMPLE 03C19_Timout_trigger_events.csd 

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

giSine    ftgen     0, 0, 2^10, 10, 1

  instr 1
loop:
idurloop  random    .5, 2 ;duration of each loop
          timout    0, idurloop, play
          reinit    loop
play:
idurins   random    1, 5 ;duration of the triggered instrument
          event_i   "i", 2, 0, idurins ;triggers instrument 2
  endin

  instr 2
ifreq1    random    600, 1000 ;starting frequency
idiff     random    100, 300 ;difference to final frequency
ifreq2    =         ifreq1 - idiff ;final frequency
kFreq     expseg    ifreq1, p3, ifreq2 ;glissando
iMaxdb    random    -12, 0 ;peak randomly between -12 and 0 dB
kAmp      transeg   ampdb(iMaxdb), p3, -10, 0 ;envelope
aTone     poscil    kAmp, kFreq, giSine
          outs      aTone, aTone
  endin

</CsInstruments>
<CsScore>
i 1 0 30
</CsScore>
</CsoundSynthesizer>

The last application of a time loop with the timout opcode which is shown here, is a randomly moving envelope. If you want to create an envelope in Csound which moves between a lower and an upper limit, and has one new random value in a certain time span (for instance, once a second), the time loop with timout is one way to achieve it. A line movement must be performed in each time loop, from a given starting value to a new evaluated final value. Then, in the next loop, the previous final value must be set as the new starting value, and so on. Here is a possible solution:

La última aplicación de un bucle de tiempo con el código de operación de temporización que se muestra aquí, es un envolvente que se mueve aleatoriamente. Si desea crear un envolvente en Csound que se mueve entre un límite inferior y un límite superior y tiene un nuevo valor aleatorio en un cierto intervalo de tiempo (por ejemplo, una vez por segundo), el bucle de tiempo con temporización es una forma de lograrlo . Se debe realizar un movimiento de línea en cada ciclo de tiempo, desde un valor inicial dado hasta un nuevo valor final evaluado. A continuación, en el siguiente ciclo, el valor final anterior debe establecerse como el nuevo valor inicial, y así sucesivamente. He aquí una posible solución:

   EXAMPLE 03C20_Timout_random_envelope.csd 

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

giSine    ftgen     0, 0, 2^10, 10, 1
          seed      0

  instr 1
iupper    =         0; upper and ...
ilower    =         -24; ... lower limit in dB
ival1     random    ilower, iupper; starting value
loop:
idurloop  random    .5, 2; duration of each loop
          timout    0, idurloop, play
          reinit    loop
play:
ival2     random    ilower, iupper; final value
kdb       linseg    ival1, idurloop, ival2
ival1     =         ival2; let ival2 be ival1 for next loop
          rireturn  ;end reinit section
aTone     poscil    ampdb(kdb), 400, giSine
          outs      aTone, aTone
  endin

</CsInstruments>
<CsScore>
i 1 0 30
</CsScore>
</CsoundSynthesizer>

Note that in this case the oscillator has been put after the time loop section (which is terminated by the rireturn statement. Otherwise the oscillator would start afresh with zero phase in each time loop, thus producing clicks.

Tenga en cuenta que en este caso el oscilador se ha puesto después de la sección de bucle de tiempo (que se termina por la declaración de rieturn), de lo contrario el oscilador empezaría de nuevo con fase cero en cada ciclo de tiempo, produciendo así clics.

Time Loops by using the metro Opcode

The metro opcode outputs a "1" at distinct times, otherwise it outputs a "0". The frequency of this "banging" (which is in some way similar to the metro objects in PD or Max) is given by the kfreq input argument. So the output of metro offers a simple and intuitive method for controlling time loops, if you use it to trigger a separate instrument which then carries out another job. Below is a simple example for calling a subinstrument twice per second:

El opcode de metro emite un 1 en momentos distintos, de lo contrario emite un 0. La frecuencia de este golpeo (que es de alguna manera similar a los objetos de metro en PD o Max) es dada por el argumento de entrada kfreq. Así que la salida del metro ofrece un método simple e intuitivo para controlar los bucles de tiempo, si se utiliza para activar un instrumento separado que luego lleva a cabo otro trabajo. A continuación se muestra un ejemplo sencillo para llamar a un subinstrumento dos veces por segundo:

  EXAMPLE 03C21_Timeloop_metro.csd 

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

  instr 1; triggering instrument
kTrig     metro     2; outputs "1" twice a second
 if kTrig == 1 then
          event     "i", 2, 0, 1
 endif
  endin

  instr 2; triggered instrument
aSig      oscils    .2, 400, 0
aEnv      transeg   1, p3, -10, 0
          outs      aSig*aEnv, aSig*aEnv
  endin

</CsInstruments>
<CsScore>
i 1 0 10
</CsScore>
</CsoundSynthesizer>

The example which is given above (03C19_Timout_trigger_events.csd) as a flexible time loop by timout, can be done with the metro opcode in this way:

El ejemplo que se da arriba (03C19_Timout_trigger_events.csd) como un bucle de tiempo flexible por timout, se puede hacer con el opcode metro de esta manera:

 

   EXAMPLE 03C22_Metro_trigger_events.csd

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
;Example by Joachim Heintz
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

giSine    ftgen     0, 0, 2^10, 10, 1
          seed      0

  instr 1
kfreq     init      1; give a start value for the trigger frequency
kTrig     metro     kfreq
 if kTrig == 1 then ;if trigger impulse:
kdur      random    1, 5; random duration for instr 2
          event     "i", 2, 0, kdur; call instr 2
kfreq     random    .5, 2; set new value for trigger frequency
 endif
  endin

  instr 2
ifreq1    random    600, 1000; starting frequency
idiff     random    100, 300; difference to final frequency
ifreq2    =         ifreq1 - idiff; final frequency
kFreq     expseg    ifreq1, p3, ifreq2; glissando
iMaxdb    random    -12, 0; peak randomly between -12 and 0 dB
kAmp      transeg   ampdb(iMaxdb), p3, -10, 0; envelope
aTone     poscil    kAmp, kFreq, giSine
          outs      aTone, aTone
  endin

</CsInstruments>
<CsScore>
i 1 0 30
</CsScore>
</CsoundSynthesizer>  

Note the differences in working with the metro opcode compared to the timout feature:

Tenga en cuenta las diferencias en el trabajo con el opcode metro en comparación con la característica de tiempo de espera:

As metro works at k-time, you must use the k-variants of event or scoreline to call the subinstrument. With timout you must use the i-variants of event or scoreline (event_i and scoreline_i), because it uses reinitialization for performing the time loops.

Como el metro trabaja en k-time, debe usar las variantes k de evento o scoreline para llamar al subinstrumento. Con timout debes utilizar las i-variantes del evento o scoreline (event_i y scoreline_i), porque utiliza la reinicialización para realizar los bucles de tiempo.

You must select the one k-cycle where the metro opcode sends a "1". This is done with an if-statement. The rest of the instrument is not affected. If you use timout, you usually must seperate the reinitialized from the not reinitialized section by a rireturn statement.

Debe seleccionar el ciclo k en el que el opcode metro envía un 1. Esto se hace con una sentencia if. El resto del instrumento no se ve afectado. Si utiliza timout, por lo general debe separar la reinicializada de la sección no reinicializada por una declaración rireturn.

Links

Steven Yi: Control Flow (Part I = Csound Journal Spring 2006, Part 2 = Csound Journal Summer 2006)

 

  1. Since the release of the new parser (Csound 5.14), you can also write without parentheses.^
  2. Instead of using "od" you can also use "enduntil" in the until loop.^

There has been error in communication with Booktype server. Not sure right now where is the problem.

You should refresh this page.