2.3.3. Common Musics erweiterte Streamklasse und Mikrotöne
Über die oben beschriebenen jackmidi input/output streams hinaus stellt common music auch eine eigene, bidirektionale Streamklasse <incudine-stream>
zur Verfügung, mit Hilfe derer auch die Ausgabe von Mikrotönen möglich ist. Auch für diese Streamklasse existiert ein vordefiniertes Symbol *rts-out*
, das für die Standardanbindung von Common Musics Ausgabefunktionen vorgesehen ist.
Im einfachsten Fall einer normalen Midiausgabe wird bei Erzeugung eines solchen Streams der jackmidi Stream/Port als Argument für den zu verwendenden Output Port mit Hilfe des Keyworts :output
übergeben:
(setf *rts-out* (new incudine-stream :output *midi-out1*))
Dieser Stream wird automatisch verwendet, wenn bei den Ausgaberoutinen kein anderer Stream (mit Hilfe der Symbole :to
oder to
) explizit angegeben wurde. Nach der Bindung des Symbols des obigen Beispiels reicht also der folgende Ausdruck, um eine Note über diesen Stream auszugeben:
(output (new midi))
Erheblich interessanter wird es, wenn man die erweiterten Möglichkeiten eines Common Music <incudine-streams>
nutzt, wie beispielsweise das 'channel-tuning', um auf diese Weise Mikrotöne erzeugen zu können.
2.3.3.1. Mikrotöne über MIDI
Das MIDI Protokoll stellt Tonhöhen in Form ganzer Zahlen dar, die die Tastennummern einer Klaviatur bezeichnen. Die Tastennummer 0 steht für das Subkontra-C. In dieser Notation hat also das mittlere C (c') die Tastennummer 60.
Um dennoch Mikrotöne, die über eine 12-tönige Teilung der Oktave hinausgehen, realisieren zu können, verwendet Common Music ein Verfahren, dass sich "channel-tuning" nennt. Bei diesem Verfahren werden mehrere Midikanäle verwendet, die mit Hilfe einer pitch-bend Message leicht gegeneinander verstimmt werden. Wenn ein channel-tuning mit 4 verschiedenen Kanälen verwendet wird, bekommt man also eine Auflösung von 12x4 = 48 Tönen pro Oktave, was Achteltönen (25 Cent) entspricht.
Für die 4 verwendeten Midikanäle ergeben sich dann folgende Verstimmungen 7:
MidiKanal | Verstimmung |
---|---|
1 | 0 Cent |
2 | 25 Cent |
3 | 50 Cent |
4 | 75 Cent |
Um mikrotonale Tonhöhen zu bezeichnen, werden beim "channel-tuning" Gleitkommazahlen für Tastennummern verwendet. Wenn beispielsweise die gewünschte Tonhöhe/Tastennummer 60.5 erzeugt werden soll, wird die Tastennummer 60 auf Midikanal 3 ausgegeben, bei 60.75 die Tastennummer 60 auf Kanal 4, usw.. Dazwischen liegende mikrotonale Werte werden auf den nächstliegenden Kanal//Achtelton gerundet.
Der nachfolgende Code zeigt, wie channel-tuning in Common Music mit Hilfe eines <incudine-streams>
realisiert werden kann. Das Macro make-mt-stream
erzeugt einen solchen mikrotonalen Stream. Das erste Argument gibt den Symbolnamen des zu erzeugenden Streams an, das zweite Argument gibt den incudine Stream/Port an, über den die Mikrotöne ausgegeben werden sollen. Das dritte Argument schließlich besteht aus einer Liste, deren erstes Element die Anzahl der Kanäle angibt, die für das channel-tuning verwendet werden sollen. Das zweite Argument dieser Liste gibt den 'channel-offset' für die Midiausgabe an. Bei dem nachfolgenden Beispiel ist der channel-offset 0, das heißt, der Sampler muss so eingestellt werden, dass auf den ersten vier Midikanälen das gleiche Programm verwendet wird.
Das nachfolgende Beispiel setzt voraus, dass der Code zur Initialisierung der Echtzeitverarbeitung und der jackmidi Streams aus den vorangegangenen Abschnitten bereits ausgeführt wurde.
(in-package :cm) ;;; Mikrotonalität über channel-tuning: ;;; Erzeugen eines midi-streams mit Achteltonquantisierung. Der Stream ;;; wird an das Symbol *mt-out01* gebunden und verwendet zur Ausgabe ;;; den Standardmidioutput, der auf *midi_out1* ausgibt. Die Liste des ;;; letzten Arguments von make-mt-stream gibt durch das erste Element ;;; '4' an, dass ein 4-kanaliger channel-tuning Stream erzeugt werden ;;; soll. Die zweite Zahl '0' gibt den Kanaloffset dieses Streams ;;; an. Im nachfolgenden Beispiel ist der Kanaloffset 0, so daß die ;;; Midikanäle 0-3 verwendet werden. Bei einem Kanaloffset von '4 ;;; würden die Midikanäle 4-7 für das channel tuning verwendet. (make-mt-stream *mt-out01* *midi-out1* '(4 0))
Hinweis: Viele MIDI Software Synthesizer, wie QSynth, verlieren bei Betätigung der 'Panic' oder 'Reset' Taste ihre pitchbend Informationen und alle Midikanäle sind wieder halbtönig temperiert gestimmt. In diesem Fall können die pitchbends mit dem Befehl initialize-io
und dem betreffenden mikrotonalen MidiPort als Argument erneut übertragen und eingestellt werden.
(initialize-io *mt-out01*)
Nachdem der Stream auf diese Weise erzeugt und initialisiert wurde, kann er zur Ausgabe von Mikrotönen verwendet werden. Auch hier muss -wie schon zuvor bei jackmidi Streams- einem Notenabspielbefehl das Keywort :to gefolgt vom Symbol des mikrotonalen Streams zusätzlich übergeben werden, damit die Ausgabe über diesen Stream erfolgt.
;;; Änderung des Midi Programms bei allen 4 ersten Midikanälen: (output (new midi-program-change :program 2) :to *mt-out01*) ;;; Ausgabe verschiedener Tonhöhen mittels channel-tuning: ;;; Ausgabe auf Kanal 1: (output (new midi :keynum 60) :to *mt-out01*) ;;; Ausgabe auf Kanal 2: (output (new midi :keynum 60.25) :to *mt-out01*) ;;; Ausgabe auf Kanal 3: (output (new midi :keynum 60.5) :to *mt-out01*) ;;; Ausgabe auf Kanal 4: (output (new midi :keynum 60.75) :to *mt-out01*) ;;; Ausgabe auf Kanal 1: (output (new midi :keynum 61) :to *mt-out01*) ;;; usw...
Die nachfolgenden Beispiele geben einen Vorgeschmack auf die Anwendungsmöglichkeiten solcher mikrotonaler Streams. Sie enthalten bisher unbekannte Funktionen und Ausdrücke, die in den folgenden Kapiteln vorgestellt und näher erläutert werden.
;;; eine Abfolge von drei mikrotonalen Tonhöhen im Abstand von 0.5 ;;; Sekunden: (sprout (process for keynum in '(60.3 65.7 71) do (output (new midi :time (now) :keynum keynum :duration 1) :to *mt-out01*) wait 0.5)) ;;; Arpeggio einer Partialtonreihe (sprout (process for keynum in (loop for p from 1 to 18 collect (keynum (* p (hertz 30)) :hz)) do (output (new midi :time (now) :keynum keynum :duration 3) :to *mt-out01*) wait 0.05)) ;;; Arpeggio einer Partialtonreihe mit Zufallsreihenfolge (sprout (process for keynum in (next (new heap :of (loop for p from 1 to 18 collect (keynum (* p (hertz 30)) :hz))) t) do (output (new midi :time (now) :keynum keynum :duration 3) :to *mt-out01*) wait 0.04))
7: Die Kanalnummerierung ist leider nicht einheitlich: Zumeist werden bei Softwaresynthesizern die MIDI Kanäle mit den umgangssprachlich naheliegenden Zahlen 1-16 bezeichnet. Bei Common Music hingegen (ähnlich auch bei pure data) ist die Nummerierung um 1 verschoben von 0-15, was mathematisch naheliegender und bei Berechnungen etwas einfacher zu handhaben ist. Bei Codebeispielen wird daher in dieser Publikation die von Common Music erwartete 0-basierte Zählung verwendet, bei allgemeinen Beschreibungen die Zählung von 1-16. ↩