Im letzen Teil habe ich schon etwas zu Kontrollvariablen geschrieben. Ich habe gezeigt, wie man den Opcode line dazu benutzen kann, die Tonhöhe über die Zeit zu ändern. Dasselbe können wir natürlich auch mit der Lautstärke machen.

Amplitude Envelopes

instr 1
      kenv line 0, p3, 10000      ;linear ramp from 0 zo 10000
      aone oscil kenv, 320, 1     ;amplitude envelope (kenv)
      out aone
endin

Diese line Kontrollvariable ändert die Lautstärke des Tons, indem sie einen Amplitude Envelope erzeugt. Wenn man sich schon vorher ein wenig mit Synthesizern beschäftigt hat, dann ist einem solch ein Envelope Generator sicherlich schon einmal über den Weg gelaufen. Das klassische ADSR-Modul kann dafür benutzt werden. In unserem Fall lassen wir die Lautstärke von 0 auf 10.000 ansteigen. Das wäre ein Attack (A) Wert von 3 Sekunden, wobei D, S und R auf 0 gedreht wären.

ADSR in VCV Rack

Wie das klingt kann man im kompletten Beispiel anhören:

<CsoundSynthesizer>

<CsOptions>
-odac      ;realtime audio
</CsOptions>


<CsInstruments>
  sr = 48000
  ksmps = 10
  nchnls = 1

  instr 1
      kenv line 0, p3, 10000      ;linear ramp from 0 zo 10000
      aone oscil kenv, 320, 1     ;amplitude envelope (kenv)
      out aone
  endin
</CsInstruments>

<CsScore>
  f1 0 4096 10 1               ;instr1 sinus

  i1 0 3                       ;instr1, lasts 3sec
</CsScore>

</CsoundSynthesizer>

Wir haben nun also drei verschiedene Möglichkeiten kennengelernt, wie man dem Oszillator seine Lautstärke und Frequenz vorgeben kann. Entweder direkt als Konstante in den Opcode geschrieben, oder indirekt mithilfe von p-Feldern, die wir dann im Score angeben, oder aber mithilfe von Kontrollvariablen.

Kontrollvariablen mit mehreren Segmenten

Es ist auch möglich einen Ton erst ansteigen und dann wieder abfallen zu lassen, ebenso kann man natürlich auch die Lautstärke erst zunehmen und dann wieder abfallen lassen. Das würde dann einem Attack-Decay-Envelope entsprechen. Außerdem sind auch noch komplexere Formen möglich. Erreichen kann man diese mithilfe des linseg Opcodes. Während line nur ein Liniensegment erzeugt, kann linseg gleich mehrere erzeugen – ein Segment gefolgt vom nächsten… Die allgemeine Syntax sieht so aus:

kx    linseg a, dur, b, dur, c ...

Z.B. erzeugt der folgende Code einen Oszillator, dessen Frequenz erst von 300Hz nach 800Hz ansteigt und dann nach 400Hz abfällt.

instr 1
    ksweep linseg 300, p3/2, 800, p3/2, 400
    anew oscil    10000, ksweep, 1
    out anew
endin

ksweep im oberen Beispiel hat zwei Segmente. In diesem Fall wurde die Tondauer (p3) einfach in zwei große Teile aufgeteilt (p3/2).

Um drei Segmente zu erzeugen, könnte man die Zeit bspw. einfach durch 3 teilen und dementsprechend ein Argument zu linseg dazuschreiben.

instr 1
    ksweep linseg 800, p3/3, 1000, p3/3, 400, p3/3, 900
    anew oscil    10000, ksweep, 1
    out anew
endin

Hier wurden die Frequenzen wieder fest in den Opcode linseg geschrieben. Natürlich kann man diese auch erst beim Schreiben des Scores festlegen, somit kann man dann für jede gespielte Note entschieden, welche Tonhöhe wo und wie zu ändern ist.

instr 1
    ksweep linseg p5, p3/3, p6, p3/3, p7, p3/3, p8
    anew oscil    10000, ksweep, 1
    out anew
endin

Im folgenden Code nutzen wir einen zweiten linseg Opcode, der einen Amplitude Envelope erzeugt, mit Attack, Sustain und Decay.

instr 1
    ksweep linseg p5, p3/3, p6,    p3/3, p7,    p3/3, p8
    kenv1  linseg 0,  p3/3, 10000, p3/3, 10000, p3/3, 0
    anew oscil    kenv1, ksweep, 1
    out anew
endin

In diesem Fall steigt die Amplitude von 0 auf 10.000 in p3/3 (attack time), hält dann den Wert für p3/3 Sekunden (sustain) und fällt wieder auf 0 in den verbleibenden p3/3 Sekunden (decay).

Falls wir Zeitsegmente nutzen, die zusammen nicht die gesamte Spieldauer der Note ergeben, dann wird der Wert des letzten Segments für den Rest der Zeit angewandt.

k1    linseg 0, p3/3, 1, p3/3, 0

Kontrollvariablen mit mehreren exponentiellen Segmenten

Zusätzlich zu linearen Segmenten kann Csound auch exponentielle Segmente erzeugen. Es ist nun mal so, das exponentielle Frequenzänderungen einfach natürlicher für’s menschliche Ohr klingen. Das exponentielle Äquivalent zu line ist expon und das exponentielle Pendant zu linseg ist expseg.

kx    expon    ia, idur, ib
kx    expseg   ia, idur1, ib, idur2, ic ...

In beiden Fällen ist die Syntax praktisch dieselbe, wie auch bei line oder linseg. Der einzige Unterschied ist der, dass exponentielle Opcodes keine 0 als Größe akzeptieren. Falls eine 0 benötigt wird, muss man einen sehr kleinen Wert wie 0.01 nehmen.

<CsoundSynthesizer>

<CsOptions>
  -odac      ;realtime audio
</CsOptions>


<CsInstruments>
  sr = 48000
  ksmps = 10
  nchnls = 1

  instr 1                     ;instrument #1
    kglis expon 220, p3, 740  ;exp segment, raising from 220 to 440
                              ;in p3 seconds, outpit in kglis
    a1    oscil p4, kglis, 1  ;oscillator, amp is p4, freq follows kglis,
                              ;waveform function #1
    out   a1
  endin
    
  instr 2                                               ;instrument #2
    ksweep expseg p5, p3/2, p6, p3/2, p7                ;2 exp. segments (freq)
    kenv1  expseg .001, p3/3, 10000, p3/3, 10000, p3/3, .0001 
           ;3 exp. segments (amp)

    a2     oscil  kenv1, ksweep, 1
    out    a2
  endin
</CsInstruments>

<CsScore>
  f1 0 4096 10 1               ;instr1 sinus

  i1 0 3 10000 
  i2 0 3 10000 300 600 300                 
</CsScore>

</CsoundSynthesizer>

Envelopes mit linen

In Csound gibt es einen speziellen Opcode für trapezoide Envelopes: Attack-Sustain-Release.

kenv    linen    kamp, iatt, idur, irel
  • kamp ist die Spitze der Amplitude (die höchste Lautstärke des Sounds)
  • iatt ist die Dauer der Attack-Phase (attack time)
  • idur ist die gesamte Dauer des Sounds (normalerweise die Dauer von p3)
  • irel ist die Dauer der Release-Phase.

Ein Beispiel:

instr 1
  kenv linen 1000, 0.1, p3, 0.5
  a1 oscil   kenv, 440, 1
  out a1
endin

Wenn die Dauer der Note (p3) geändert wird, wird die Dauer des Sustain Parts dementsprechend verändert. Die Attack Time und die Release Time bleiben dabei so, wie angegeben.

Soviel erstmal zu Envelopes. Im nächsten Artikel geht es dann etwas mehr um Frequenzen und Amplituden. Außerdem zeige ich noch, wie man das Schreiben des Scores etwas angenehmer macht.