2.3.5. Ausgabefunktionen

Common Musik stellt verschiedene Formen für die Ausgabe von Ereignissen bereit.

2.3.5.1. output

Die direkteste Form wird durch die Funktion output bereitgestellt. output gibt immer genau ein Ereignis aus, das der Funktion als Argument übergeben werden muss. Wird die Funktion im 'top-level' evaluiert, wird der :time Slot des Ereignisses von der Funktion ignoriert und das Ereignis direkt ausgegeben. Über das Keywort :to besteht die Möglichkeit, den output-stream zu spezifizieren. Wenn das Keywort :to nicht verwendet wird, erfolgt die Ausgabe auf den Stream, der an das Symbol *rts-out* gebunden ist.

Zusätzlich besteht die Möglichkeit, die Ausgabe mit dem Keywort :at zu verzögern. Der Wert von at wird in Sekunden angegeben, die auf den Moment, an dem der Ausdruck evaluiert wird, bezogen sind. Negative Werte für :at sollten vermieden werden.

;; realtime output einer Note:

(output (new midi))

(output (new midi :keynum 62 :duration 4))

(output (new midi :keynum (+ 48 (random 24)) :duration 4))

;; Ausgabe 1 Sekunde nach Auswertung:

(output (new midi) :at 1)

(* 3 4 5) ;;; -> 60

(sprout
 (process repeat 10 output (new midi :time (now))
          wait 0.2))

Sollen mehrere Ereignisse ausgegeben werden, ist es möglich, mehrere Aufrufen von output mit der special form progn zu einem Block zusammenzufassen. Sämtliche output Ausdrücke in dem progn Block werden dabei simultan ausgeführt. Rhythmen lassen sich durch die Verwendung des Keyworts :at realisieren:

;; Ausgabe eines simultanen Durdreiklangs mit output:

(progn
  (output (new midi :keynum 60))
  (output (new midi :keynum 64))
  (output (new midi :keynum 67)))

;; Ausgabe eines Arpeggios mit output:

(progn
  (output (new midi :keynum 60))
  (output (new midi :keynum 71) :at 0.5)
  (output (new midi :keynum 66) :at 2))

2.3.5.2. sprout

Eine allgemeinere Form der Ausgabe stellt die Funktion sprout bereit. sprout kann sowohl einzelne Ereignisse, als auch eine Liste von Ereignissen oder einen Prozess (siehe nächstes Kapitel) ausgeben. Wenn sprout ein einzelnes Ereignis oder eine Liste von Ereignissen ausgeben soll, ist darauf zu achten, dass der :time Slot der auszugebenden Ereignisse gesetzt sein muss. Auch der Wert dieses Slots bezieht sich auf den Moment der Auswertung des Ausdrucks.

(sprout (new midi :time 0))

;;; Ausgabe 1 Sekunde nach Auswertung:

(sprout (new midi :time 1))

Wenn sprout im 'top-level' evaluiert wird, erfolgt die Ausgabe, wie bei output unmittelbar in Echtzeit. Auch bei sprout ist es möglich, den Ausführungszeitpunkt durch das Keywort :at zu beeinflussen. Hier ist allerdings darauf zu achten, dass der Wert von :at nicht relativ zum Auswertungszeitpunkt, sondern in absoluter Zeit seit Start der Echtzeitverarbeitung angegeben werden muss. Den aktuellen Wert der absoluten Zeit kann man mit der Funktion (now) ermitteln. Auf diese Weise lässt sich eine relative Verzögerung folgendermaßen darstellen:

;;; Ausgabe 1 Sekunde nach Evaluation:

(sprout (new midi :time 0) :at (+ 1 (now)))

;;; Kombination von :time und :at
;;; Ausgabe 2 Sekunden nach Evaluation:

(sprout (new midi :time 1) :at (+ 1 (now)))

Wenn mehrere Ereignisse ausgegeben werden sollen, können die Ereignisse in Form einer Liste an sprout übergeben werden:

;; Ausgabe eines simultanen Durdreiklangs mit sprout:

(sprout
 (list
  (new midi :keynum 60 :time 0)
  (new midi :keynum 64 :time 0)
  (new midi :keynum 67 :time 0)))

;; Ausgabe eines Arpeggios mit sprout:

(sprout
 (list
  (new midi :keynum 60 :time 0)
  (new midi :keynum 71 :time 0.5)
  (new midi :keynum 66 :time 2)))

2.3.5.3. events

events ist eine Form der Ausgabe von Ereignissen, die in Common Music implementiert wurde, bevor die Echtzeitausgabe von Ereignissen mit Computern möglich war.

Ähnlich, wie bei sprout ist es mit der events Funktion möglich, einzelne Ereignisse, Listen von Ereignissen, Prozesse oder andere cm Typen, wie <sequence> auszugeben. Auch bei der Ausgabe durch events muss bei allen auszugebenden Ereignissen der :time Slot gesetzt sein.

Als drittes Argument wird der events Funktion das Ziel (englisch 'destination') übergeben.

Wenn dieses Argument eine Zeichenkette (englisch 'string') ist, wird diese als Dateiname interpretiert und die Ereignisse in eine Datei ausgegeben, deren Typ sich nach der Endung des Dateinamens richtet. Die wichtigsten Endungen sind in der nachfolgenden Tabelle aufgeführt

Dateinamenendung Typ der Ausgabedatei
".midi", ".mid" MIDI-Datei
".ly" Lilypond Datei
".cmn" CMN Datei
".clm" CLM Datei
".aiff", ".snd", ".wav" CLM Audiodatei

Je nach Ausgabeformat existieren Zusatzoptionen, zur genaueren Steuerung des Ausgabeformats, die der events Funktion mit Hilfe von Keywortargumenten übergeben werden. Eine Auflistung der Optionen findet sich im Common Music Dictionary unter midi-file, fomus-file, cmn-file, clm-file und audio-file.

Wenn anstelle einer Zeichenkette ein <incudine-stream> angegeben wird, so werden die Ereignisse ähnlich wie bei sprout auf die Echtzeitausgänge geleitet.

Wird das dritte Argument ausgelassen, wird das Ausgabeformat des letzten Aufrufs der events Funktion verwendet.

;;; Ausgabe in die Midi Datei "/tmp/test.midi":

(events
 (list
  (new midi :keynum 60 :time 0)
  (new midi :keynum 62 :time 0.5)
  (new midi :keynum 64 :time 1))
 "/tmp/test.midi")

;; realtime output einer Note mit der events Funktion:

(events
 (new midi :time 0)
 *rts-out*)

;; wird das zweite Argument weggelassen, wird die zuletzt verwendete
;; Ausgabemethode benutzt:

(events
 (new midi :time 0))

Der Unterschied zwischen events und sprout besteht darin, dass events direkt bei Auswertung sämtliche Ereignisse generiert und dem Echtzeitscheduler mit den entsprechenden Zeitinformationen übergibt, während im Falle von sprout ein process nur das jeweils nächste Element generiert und sich über den scheduler zeitverzögert wiederholt aufruft, bis der Prozess beendet ist. Solch eine Form der schrittweisen, sukzessiven Auswertung erst zu dem Zeitpunkt, an dem ein neues Element benötigt wird, ist eine Programmiertechnik, die unter dem Begriff 'Lazy Evaluation' bekannt ist. Ein Vorteil dieser Technik besteht darin, dass man einen Prozess definieren und starten kann, der prinzipiell unendlich ist. Von aussen kontrolliert werden solche Prozesse dann durch das Setzen einer globalen Variable, die vom Prozess zur Ausführungszeit überprüft wird, und über die er sich, wenn sie gesetzt ist, selbst stoppt.

Für solche eine Methode kann events nicht eingesetzt werden, da ein solcher Prozess sofort einen Überlauf erzeugt, da unendlich viele Werte unmittelbar generiert werden müssten.

Um in eine Lilypond Datei zu exportieren, muss zuvor das Paket "cm-fomus" geladen worden sein.

;;; Ausgabe in eine Lilypond Datei:

(ql:quickload "cm-fomus")

(events
 (list
  (new midi :keynum 60 :time 0)
  (new midi :keynum 62 :time 0.5)
  (new midi :keynum 64 :time 1))
 "/tmp/test.ly")

Nach Evaluation des obenstehenden Ausdrucks sollte sich die Datei "test.ly" im Ordner "/tmp" befinden. Sie lässt sich anschließend mit dem Programm lilypond setzen und ergibt die untenstehende Notengrafik.

lilypond test

results matching ""

    No results matching ""