2.3.4. Ereignisse
Eine Midinote ist in Common Music ein Objekt, das der allgemeinen Klasse von 'Ereignissen' (englisch 'events') angehört.
Um ein Objekt zu erzeugen, verwendet Common Music die Funktion new
8: Die Funktion erhält als Argument den Namen der Klasse, von der eine Instanz erzeugt werden soll. Im Falle einer Midinote ist der Name der Klasse midi
:
(new midi) ;; -> #i(midi keynum 60 duration 0.5 amplitude 0.5 channel 0)
Am Ergebnis des Beispiels kann man erkennen, dass durch die Evaluation des new
Ausdrucks die 'Instanz' einer Midinote (ausgedrückt durch die Zeichenfolge '#i' vor der Klammer) mit der keynum 60, der duration 0.5, der amplitude 0.5 und dem channel 0 erzeugt wurde. Die einzelnen Parameter der Midinote bezeichnet man als 'Instanzvariablen' (bzw. englisch 'slots').
In der Klassendefinition sind Anzahl, Namen und oft auch die Standardwerte (englisch 'default values') dieser Instanzvariablen festgelegt 9: Bei Erzeugung einer Instanz können von den Defaultwerten abweichende Werte für die Instanzvariablen mit Hilfe von Keywords10 übergeben werden.
(new midi :keynum 62 :duration 2) ;; -> #i(midi keynum 62 duration 2 amplitude 0.5 channel 0)
Die Werte der Instanzvariablen lassen sich mit der Funktion sv (slot-value) ermitteln.
(defparameter *testevent* (new midi)) ;;; Lesen der Instanzvariablen/Slots mit Hilfe der sv Funktion: (sv *testevent* :keynum) ;; -> 60 (sv *testevent* :duration) ;; -> 0.5 (sv *testevent* :amplitude) ;; -> 0.5 (sv *testevent* :channel) ;; -> 0
Alternativ kann der Slotname auch als Symbol ohne Doppelpunkt verwendet werden.
(sv *testevent* keynum) ;; -> 62 (sv *testevent* duration) ;; -> 2 (sv *testevent* amplitude) ;; -> 0.5 (sv *testevent* channel) ;; -> 0
Darüber hinaus sind in Common Music auch noch folgende Funktionen zum Adressieren der Instanzvariablen definiert:
(midi-keynum *testevent*) ;; -> 62 (midi-duration *testevent*) ;; -> 2 (midi-amplitude *testevent*) ;; -> 0.5 (midi-channel *testevent*) ;; -> 0
Wenn man den Wert von Instanzvariablen verändern möchte, verwendet man die special form setf
in Verbindung mit sv
:
;;; Verändern der Instanzvariablen/Slots mit Hilfe von setf und der sv ;;; Funktion: (setf (sv *testevent* :keynum) 62) ;; -> 62 (setf (sv *testevent* :duration) 2) ;; -> 2 *testevent* ;; -> #i(midi keynum 62 duration 2 amplitude 0.5 channel 0)
Zur Veränderung der Instanzvariablen mit setf
können alle Formen der Adressierung von Slots verwendet werden, wie das folgende Beispiel zeigt:
(setf (midi-keynum *testevent*) 65) ;; -> 65 (setf (sv *testevent* channel) 3) ;; -> 3 (setf (midi-amplitude *testevent*) 0.3) ;; -> 3 *testevent* ;; -> #i(midi keynum 65 duration 2 amplitude 0.3 channel 3)
2.3.4.1. Der Time Slot
Allen Ereignisklassen in Common Music ist gemeinsam, dass sie eine Instanzvariable :time
besitzen. Beim Auswerten der Instanz einer Ereignisklasse (bzw. im Rückgabewert der new
Funktion) wird dieser Slot nicht dargestellt. Man kann ihn allerdings bei Inspektion einer Instanz mit Hilfe der Funktion inspect
(am besten in der REPL) sehen (Hinweis: Um den Inspektor wieder zu verlassen, muss die Taste "q" gefolgt von der Eingabetaste eingegeben werden) 11
CM> (inspect *testevent*) The object is a STANDARD-OBJECT of type MIDI. 0\. TIME: "unbound" 1\. KEYNUM: 65 2\. DURATION: 2 3\. AMPLITUDE: 0.3 4\. CHANNEL: 3 > q ; No value CM>
Ein Defaultwert für den time
Slot ist in Common Music nicht definiert. Wenn der time Slot eines Events bei der Initialisierung nicht spezifiziert wurde, erzeugt Die Abfrage des Wertes von :time
daher eine UNBOUND-SLOT
Condition:
(sv *testevent* :time) ;;; -> The slot COMMON-LISP:TIME is unbound in the object ;;; #i(midi keynum 65 duration 2 amplitude 0.3 channel 3). ;;; [Condition of type UNBOUND-SLOT]
Die Condition kann man durch das Drücken von "q" bzw. "0" beenden und zum Ausgangspunkt zurückkehren. Anschließend kann man mit den oben beschriebenen Methoden den Wert des :time
Slots setzen:
(setf (sv *testevent* :time) 0) ;;; -> 0 (sv *testevent* :time) ;;; -> 0
2.3.4.2. Andere Ereignisklassen
In Common Music sind verschiedene Ereignisklassen vordefiniert (siehe hierzu auch MIDI event classes unter MIDI im Common Music Dictionary). Es besteht sogar die Möglichkeit, das Paket um benutzerdefinierte Ereignisklassen für spezielle Anwendungsfälle zu erweitern.
Hier ein Beispiel für ein Ereignis der Klasse midi-program-change
, mit der man das Midiprogramm eines Soft- bzw. Hardwaresynthesizers umschalten kann. Für diese Ereignisklasse sind neben dem :time
Slot Instanzvariablen für 'program' und 'channel' definiert.
;; Erzeugen der Instanz einer Midiprogrammwechsels: (new midi-program-change :program 3) ;; -> #i(midi-program-change channel 0 program 3)
8: In der Fachsprache nennt man diesen Vorgang 'instantiieren' und das erzeugte Objekt eine 'Instanz'. ↩
9: Das Beispiel zeigt, dass bei einer Midinote die Defaultwerte für keynum 60, für duration 0.5, für amplitude 0.5 und für channel 0 sind. ↩
10: Keywords sind in Common Lisp Symbole, die mit einem Doppelpunkt beginnen, also beispielsweise:keynum
,:amplitude
oder:dur ation
. ↩
11: Eine erheblich komfortablere Form der Inspektion bietet Slime unter emacs. Dazu positioniert man den Cursor hinter das letzte Zeichen des zu inspizierenden Ausdrucks und drückt die Tastenkombination "C-c I". Im Minibuffer wird der zu inspizierende Ausdruck noch einmal angezeigt, den man durch Eingabe der Returntaste bestätigen muss. Der Inspektor öffnet sich dann in einem neuen Emacs Buffer. Auch hier verlässt man den Inspektor mit der Taste "q". ↩