Wie wir bisher gesehen haben, benötigt ein Oszillator die Frequenz immer in Hertz-Angaben (Hz), genauso muss die Amplitude immer in einer rohen Form (von 0 bis 32.767) angegeben werden. Das ist nicht gerade sehr komfortabel, denn wir drücken unsere Noten nun mal selten in Frequenzen aus, sondern eher in Oktaven und Halbtönen. Csound besitzt dafür einen Tonhöhen Konverter (pitch converter), der die Hertz-Zahl aus einer gegebenen Oktave und Tonhöhenklasse ermittelt (octave point pitch class).

Diese octave point pitch class Darstellung (pch) besteht aus einer Integer-Zahl, die die Oktave angibt und einem Dezimalteil, der die Halbtöne angibt. Die Oktave, die das mittlere C (261,63 Hz) enthält, wurde mit der Zahl 8 festgelegt. Deshalb:

8.00=middle C (261,63Hz)
8.01=C# (277,63Hz)
8.02=D (293,67Hz)
8.03=D# (311,13Hz)
7.09=A below middle C (220Hz)
8.09=A above middle C (440Hz)
9.00=C an octave higher than middle C (523,25Hz)
5.00=the lowest C of a piano (32,7Hz)

Und so sieht der Code aus, der Csound dazu veranlasst pch in Hz umzurechnen:

instr 1
   ifreq = cpspch(p5)
   a1 oscil p4, freq, 1
   out a1
endin

ifreq ist eine Variabale, die zur Initialisierungsphase zugewiesen wird (bevor die erste Note gespielt wird) und sie ändert sich auch nicht mehr. In diesem Fall wird ifreq ein Wert in Hz (oder cps -> cycles per second) zugewiesen, der sich aus der Umwandlung der Tonhöhe in p5 ergibt. Die Umwandlung übernimmt der Opcode cpspch, der die Hertz-Zahl von pch zurückgibt.

<CsoundSynthesizer>

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

<CsInstruments>
  sr = 48000
  ksmps = 10
  nchnls = 1
  instr 1
     ifreq = cpspch(p5)
     a1 oscil p4, freq, 1
     out a1
  endin
</CsInstruments>

<CsScore>
  f1 0 4096 10    1               
  i1 0 1    10000 8.00  
  i1 1 1    10000 8.02 
  i1 2 1    10000 8.04 
  i1 3 1    10000 8.00             
</CsScore>

</CsoundSynthesizer>
Notepitch (pch)
C8.00
C#8.01
D8.02
D#8.03
E8.04
F8.05
F#8.06
G8.07
G#8.08
A8.09
A#8.10
B8.11

Amplitude in Dezibel

Genauso wie Tonhöhen-Konverter, enthält Csound natürlich auch Lautstärken-Konverter. Wenn man die Amplitude in Dezibel (dB) angeben möchte, muss man einen andere Init-Time Variable erstellen, die dann das Ergebnis der Umwandlung von dB in den absoluten Wert der Amplitude speichert. Diese Umwandlung übernimmt der Opcode ampdb. Die maximale Amplitude, die in Csound erlaubt ist, beträgt 90dB (31622,78).

dBabsolute
value
dBabsolute
value
dbabsolute
value
dbabsolute
value
9031622,78601000,03031,6201000
8825118,8658794,332825,12
8619952,6256630,962619,95
8415848,9354501,192415,85
8212589,2552398,112212,59
8010000,0050316,232010,00
787943,2848251,19187,94
766309,5746199,53166,31
745011,8744158,49145,01
723981,0742125,89123,98
703162,2840100,00103,16
682511,893879,4382,51
661995,263663,1062,00
641584,893450,1241,58
621258,933239,8121,26
instr 1
   iamp  = ampdb(p4)   ; db to absolute value conversion
   ifreq = cpspch(p5)  ; pch to Hz conversion
   a2 oscil iamp, ifreq, 1
   out a2
endin

ein komplettes Beispiel:

<CsoundSynthesizer>

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

<CsInstruments>
  sr = 48000
  ksmps = 10
  nchnls = 1
  instr 1
   iamp  = ampdb(p4)   ; db to absolute value conversion
   ifreq = cpspch(p5)  ; pch to Hz conversion
   a2 oscil iamp, ifreq, 1
   out a2
endin
</CsInstruments>

<CsScore>
  f1 0 4096 10    1               
  i1 0 1    60    8.00  
  i1 1 1    70    8.02 
  i1 2 1    80    8.04 
  i1 3 1    60    8.00             
</CsScore>

</CsoundSynthesizer>

Noch etwas über Kompositionen…

Wie im letzten Artikel angekündigt, möchte ich noch etwas zu Scores schreiben und wie man das Schreiben einer Komposition etwas angenehmer machen kann. Denn wenn man ein komplettes Musikstück mit Csound schreibt, kann das schon etwas nervig werden, wenn man jedesmal irgendwelche Werte neu schreiben muss, die sich aber gar nicht ändern.

Man kann sich leicht merken: Wenn sich ein Parameter über mehrere Noten nicht ändert, kann man das vorherige p-Field einfach mit einem Punkt (.) wiederholen. Angenommen wir haben sieben Noten, die alle mit einer Amplitude von 80dB gespielt werden sollen:

i1    0    1    80    220   ; in this note amplitude 80dB
i1    2    3    .     223   ; in this note too amplitude 80dB
i1    6    2    .     .     ; in this note amp 80dB and freq 223
i1    8    3    .     400
i1    8    .    .     420
i1    12   .    .     227
i1    15   1    .     220

Aber vorsicht! Das funktioniert nur mit Noten-Statements, die dasselbe Instrument aufrufen. Wenn das Instrument sich ändert (i2,…), dann muss man wieder den expliziten Parameter eingeben!

Wenn man eine Sequenz von Noten schreibt, die keine Pause dazwischen haben, d.h. die zweite Note startet unmittelbar nach der ersten und die dritte unmittelbar nach der zweiten…, dann kann man anstelle der Startzeit auch ein Plus (+) schreiben:

i1    0    1    80    220
i1    +    3    .     223
i1    +    2    .     .
i1    +    3    84    400
i1    +    .    .     .
i1    +    .    .     .
i1    15   1    80    220
i1    +    .    .     .

Die letzte Note dieser Sequenz beginnt bei 16 Sekunden, dauert 1 Sekunde, hat eine Amplitude von 80dB und eine Frequenz von 220Hz.

Wenn man eine Serie von linear ansteigenden p-Field Werten schreibt, kann man auch das Ramping Feature nutzen. Dies wird genutzt, indem man mittlere Werte mit dem Symbol > ersetzt.

i1    0    1    60    8.03
i1    +    2    >     8.04
i1    +    1    >     8.06
i1    +    3    >     8.08
i1    +    2    80    8.10

ist gleichbedeutend mit:

i1    0    1    60    8.03
i1    +    2    65    8.04
i1    +    1    70    8.06
i1    +    3    75    8.08
i1    +    2    80    8.10

Es wird also ein lineares Crescendo erzeugt, von 60dB bis 80dB. Ramping bedeutet eine lineare Interpolation zwischen zwei gegeben Werten.

Noch ein letzter Tipp: Wenn man eine längere Komposition geschrieben hat und zwischendurch etwas ändert, kann es schon lästig sein, wenn man sich dann die ganze Sequenz immer und immer wieder anhören muss, nur weil man hören will, wie die Änderung klingt. Da hat man die Möglichkeit die Sequenz irgendwo in der Mitte abzubrechen. Das erreicht man, wenn man an dieser Stelle ein e schreibt:

i1    0    1    60    8.03
i1    +    2    65    8.04
i1    +    1    70    8.06
i1    +    3    75    8.08
i1    +    2    80    8.10
e                           ; synthesis stops here
i1    0    1    60    8.03
i1    +    2    65    8.04
i1    +    1    70    8.06
i1    +    3    75    8.08
i1    +    2    80    8.10

Soweit so gut. Im nächsten Artikel geht es kurz um das Tempo eines Musikstücks…