Meloncillo – eine graphische Benutzeroberfläche zur musikalischen

Transcription

Meloncillo – eine graphische Benutzeroberfläche zur musikalischen
Meloncillo – eine graphische
Benutzeroberfläche zur musikalischen
Raumklangsteuerung mit
Implementierung einer
OSC-Schnittstelle zur Klangsynthese
Magisterarbeit
von Hanns Holger Rutz, Matr.-Nr. 192946
Technische Universität Berlin
Kommunikationswissenschaft
Betreuer: Prof. Dr. Stefan Weinzierl
La musique du futur? Sûrement basée sur le son et au-delà des notes“
”
(Edgard Varèse 1947)
Varèses Denken war empirisch. Er interessierte sich dafür,
”
wie es klang – nicht wie es gemacht war.“
(Morton Feldman 1966)
Die selbständige Anfertigung versichere ich an Eides Statt.
Inhaltsverzeichnis
1 Einführung
1.1 Begriff der Raumklangsteuerung . . . . . . . . . .
1.1.1 Abgrenzung zu Auralisationsverfahren . . .
1.1.2 Abgrenzung zu Live-Diffusionsverfahren . .
1.2 Historische Wurzeln . . . . . . . . . . . . . . . . .
1.3 Vorhandene Software zur Raumklangsteuerung . .
1.3.1 APB-Tools Σ 1 . . . . . . . . . . . . . . . .
1.3.2 zplane.development z.matrix . . . . . . . .
1.3.3 Wonder . . . . . . . . . . . . . . . . . . . .
1.3.4 Surround Panning Objekte . . . . . . . . .
1.4 Hardware basierte Raumklangsteuerung . . . . . .
1.5 Raumklang-Synthese Plug-Ins . . . . . . . . . . . .
1.5.1 VBAP – Vector Based Amplitude Panning
1.5.2 IRCAM Spat˜ . . . . . . . . . . . . . . . .
1.5.3 Spatialisierung mit CSound . . . . . . . . .
1.6 Notwendigkeit einer neuen Raumklangsteuerung .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
5
8
8
9
10
10
12
13
13
14
16
16
17
18
19
2 Entwicklung des Programms Meloncillo
2.1 Tendenzen in der Entwicklung von Musiksoftware . . . .
2.2 Designspezifikation für eine neue Raumklangsteuerung .
2.2.1 Trennung von Oberfläche und Signalverarbeitung
2.2.2 Abstraktion vom Synthesemodell . . . . . . . . .
2.2.3 Anwender mit und ohne Programmiererfahrung .
2.2.4 Unabhängigkeit vom Betriebssystem . . . . . . .
2.2.5 Zwei grundlegende Objekttypen . . . . . . . . .
2.2.6 Echtzeit und Offline Modus . . . . . . . . . . . .
2.2.7 Diskrete Datenströme . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
20
20
21
21
22
23
23
24
24
25
.
.
.
.
.
.
.
.
26
26
28
28
30
31
32
32
33
3 Programmarchitektur
3.1 Sprache und Arbeitsumgebung . .
3.2 Packages Überblick . . . . . . . . .
3.3 Session . . . . . . . . . . . . . . . .
3.4 Receiver, ReceiverCollection . . . .
3.5 Transmitter, TransmitterCollection
3.6 Timeline . . . . . . . . . . . . . . .
3.7 Events . . . . . . . . . . . . . . . .
3.8 Threads . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
3
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Inhaltsverzeichnis
4 Graphische Benutzeroberfläche
4.1 Surface : zweidimensionale Momentansicht
4.1.1 Hilfs-Paletten und Werkzeuge . . .
4.1.2 ReceiverEditor . . . . . . . . . . .
4.1.3 Matrix Meter . . . . . . . . . . . .
4.2 Timeline : horizontale Zeitdarstellung . .
4.2.1 Trajektorien Daten-Format . . . .
4.2.2 Transport Palette . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
35
35
37
39
40
40
41
43
5 Plug-In Schnittstellen
5.1 Offline (Nicht-Echtzeit) . . . . . . . .
5.2 Realtime (Echtzeit) . . . . . . . . . . .
5.3 Common Lisp für Java . . . . . . . . .
5.3.1 Die LispPlugIn Klasse . . . . .
5.3.2 Ein Beispielscript . . . . . . . .
5.4 Open Sound Control . . . . . . . . . .
5.4.1 Protokollübersicht . . . . . . .
5.4.2 Implementierung in Meloncillo
5.4.3 Anbindung an SuperCollider .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
44
44
46
49
50
51
54
54
56
57
6 Resumé
6.1 Anwendungsbeispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2 Probleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.3 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
62
62
67
68
Literaturverzeichnis
70
Anhang: Abbildungen, Quelltexte
73
4
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1 Einführung
Die vorliegende Magisterarbeit beschreibt den Entwurf und die Realisierung einer SoftwareApplikation zur musikalischen Raumklangsteuerung. Das im wesentlichen aus einer graphischen Benutzeroberfläche bestehende Programm mit dem Namen Meloncillo“ erlaubt die
”
Gestaltung von Trajektorien in einem zweidimensionalen Raum und kann in Verbindung
mit einem existierenden Klangsynthese-Programm wie SuperCollider dazu verwendet werden,
verräumlichte Klänge zu berechnen oder in Echtzeit abzuspielen. Für die Echtzeit-Steuerung
ist eine Open Sound Control (OSC) Schnittstelle vorgesehen. Eine script-gesteuerte Plug-In
Schnittstelle ermöglicht es, unterschiedliche Modelle der Verräumlichung zu benutzen.
Die Arbeit ist dadurch motiviert, daß die Raumklangsteuerungen, die dem Autor bekannt
sind, zu wenig gestalterische Freiheiten bieten oder nicht ohne weiteres für die heute gängigen
Computer-Plattformen verfügbar sind. Das hier vorgestellte Programm soll neue Sichtweisen
auf musikalische Räumlichkeit öffnen.
CD-ROM
Der Quelltext und die Quelltext-Dokumentation können aus Platzgründen nicht abgedruckt
werden. Eine CD-ROM ist beigefügt, die alle nötigen Dateien enthält:
•
Quelltext
•
HTML Dokumentation aller Pakete und Klassen (javadoc)
•
Xcode IDE Projekt-Datei
•
kompiliertes Programm und Mac OS X Application Wrapper
•
externe Bibliotheken
•
Beispiel-Script, -Session und -Klänge
1.1 Begriff der Raumklangsteuerung
Der Begriff Raumklang enthält bereits ein musikalisches Element, während die englische
Übersetzung, etwa spatial sound, einen physikalischeren Charakter bekommt – sound kann
rückübersetzt auch Schall heißen. Physikalische Begriffe wären Raumschall oder Raumakustik.1
Zwischen Raumklang und Raumakustik besteht ein wesentlicher Unterschied: Raumakustik
beschreibt den Klang des Raumes, während Raumklang die Gestaltung von Klang im Raum
meint. Da eine musikalische Aufführung meist in einem geschlossenen Raum stattfindet, muß
1
vgl. [Haller 1995], S. 75
5
1 Einführung
sich der Komponist natürlich auch mit Raumakustik befassen. Das ist jedoch nicht Gegenstand dieser Arbeit. Raumakustik tritt beispielsweise nicht bei Kopfhörerübertragung oder
Beschallung im offenen Feld auf. Ein anderer Fall ohne äußere Raumeinwirkung sind Körperschallübertragung und Körperstimulation durch Aktuatoren.2
Die ganz unterschiedlich akzentuierten Aspekte von Räumlichkeit sind eines der Hauptmerkmale von Klangkunst und Klanginstallation. Für einen Überblick sei auf die Artikel des
Katalogs Klangkunst zum Festival Sonambiente 1996 hingewiesen3 . Ein paar Beispiele: In
Bill Fontanas Klangbrücke Köln-Tokyo wird das akustische Bild zweier sehr weit voneinander entfernter Orte auf der Welt durch Satelliten-Transmission ausgetauscht. Die Arbeit steht
in gewissem Kontext zu der von Murray Schafer entwickelten Idee der Klangökologie. Alvin
Lucier läßt dagegen in I’m Sitting in a Room die Resonanzen der Aufführungsorte sprechen,
La Monte Young verwendete stehende Wellen. In soundbits von Robin Minard wird die Räumlichkeit nicht nur durch dem Objekt Gegenüberstehen, sondern gleichfalls durch Herantreten
und Entlangschreiten an diesem ausgedehnten und in die Architektur integrierten Gebilde
erfahren.
Die begriffliche Nähe von Raumklang und Raumakustik kann leicht zu Verwirrungen führen:
Der Komponist orientiert sich am geometrischen Raum und versucht, in dessen
”
erkennbaren Grenzen einen ebenfalls erkennbaren, d.h. erhörbaren Klangraum zu
schaffen. Dieser Klangraum kann dem geometrischen Raum entsprechen, er muß
es nicht.“ 4
Raum“ wird in zwei unterschiedlichen Bedeutungen benutzt, obwohl Hans Peter Haller ver”
sucht, die Verschiedenheit durch die Attribute geometrisch respektive klanglich zu betonen.5
Viele Metaphern in der Musik sind räumlich-geometrischer Natur, so spricht man beispielsweise von einer hohen Tonlage, einer melodischen Linie oder Kontur; die Menge der verwendeten Töne bildet den Ton-Raum6 . Herbert Eimert unterscheidet neben diesem metaphorischen
Raum zwischen dem Musik-Raum, der durch die Raumakustik bestimmt ist, und dem musi”
kalischen Vorstellungsraum, wie er in der Phantasie des Komponisten besteht, wie er vom
Hörer nachvollzogen wird und wie er sich in den Noten, im Notationsraum der aufgezeichneten Musik niederschlägt.“ 7 Wird Musik räumlich verteilt wiedergegeben, so kann dieser
neue Raum für das Ohr ein gekrümmter, nicht euklidischer Raum“ sein. Eimert nennt die”
sen Raum einen Raummusik-R[aum], in dem die Tonbewegung in die räumlich-plastische
”
Konfiguration der Klangfelder überführt wird.“
Die Verortung dieser Arbeit wird klarer, wenn wir den Begriff der Steuerung betrachten.
Haller gibt eine sehr ingenieursmäßige Beschreibung von Klangsteuerung:
2
Beim Klanganzug der Künstlerin Lynn Pook werden sechzehn Lautsprecher am Körper befestigt – Der
”
menschliche Körper wird zum Klangraum“. Das Beispiel zeigt, daß Raumerfahrung nicht nur durch (echte
oder simulierte) von unterschiedlichen Seiten auf das Ohr treffende Schallwellen gemacht werden kann.
Dazu zählen auch einige Arbeiten von Bernhard Leitner.
3
[de la Motte-Haber 1996]
4
[Haller 1995], S. 75. Kurz davor geht Haller explizit darauf ein, daß bei der Gestaltung von Klangwegen die
Interaktion mit der Raumakustik bedacht werden muß.
5
Bezeichnenderweise beginnt Martin Supper in seinem Buch über Elektronische Musik ([Supper 1997]) das
Kapitel über Raumklang mit einem Zitat von Rudolf Carnap über die Konfusion, die durch die unterschiedliche Verwendung des Raumbegriffs entsteht.
6
[Eimert/Humpert 1973], S. 271f
7
ebd.
6
1 Einführung
Klangsteuerung in der Elektronischen Klangumformung bedeutet weder Trans”
formation noch Selektion einer Tonquelle. Sie kann für beide eine kontrollierende
Funktion übernehmen, hat jedoch auf die direkte Erweiterung eines Klangspektrums keinen Einfluß. Klangsteuerung heißt – wie der Name aussagt – Steuerung
von Klanginformationen jeglicher Art, von Instrumenten oder Stimmen, original
oder elektronisch bearbeitet.“ 8
Anders ausgedrückt ist Klangsteuerung ein formgebender Prozeß, der auf einer hierarchisch
übergeordneten Ebene stattfindet. Die Prozeßhaftigkeit, der dynamische Charakter der Klangsteuerung, wird durch weitere Bezugnahme auf Regelungstechnik wie auch die kontrollie”
rende Funktion“ unterstrichen.9 In Hallers Geräten wird zur Kontrolle oft ein Mikrophon
benutzt, das während der Performance eine Klangumformung steuert. In den klassischen
nach MUSIC V modellierten Musiksprachen bezeichnen Kontrolldaten diejenigen Daten, die
dynamisch über die Zeit – und in der Regel mit konstanter Rate abgetastet – Einfluß auf
Klangparameter und -transformationen nehmen.10
Raumklangsteuerung wird nun definiert als ein Mittel zur dynamischen Formgebung von
Bewegungen, Verteilungen und Transformationen von Klängen, die räumlich, das heißt über
mehrere Lautsprecher wiedergeben werden sollen. Das bedeutet, daß die Mehrkanaligkeit
bereits in den Klangverteilungen und -transformationen angelegt ist und explizit gestaltet
werden kann. Beispiel: Wenn ein monophoner Ausgangsklang mit unterschiedlichem Frequenzgang gefiltert und auf verschiedenen Lautsprechern ausgeben wird, ist das eine Form
von Raumklang, denn der Klang wurde räumlich gestaltet. Der benutzte Filter ist jedoch
nur dann als Raumklangsteuerung zu bezeichnen, wenn in ihm selbst a) die dynamische,
zeitveränderliche Steuerung und b) die Variation des Frequenzganges über verschiedene Ausgangskanäle (oder allgemein eine räumliche Situation) vorhanden sind. Umgekehrt wird ein
Objekt zur Raumklangsteuerung, wenn es andere Objekte – ob einen Mixer oder ein Filter
spielt dabei keine Rolle – dynamisch räumlich kontrolliert, zum Beispiel indem es für jeden
Ausgangskanal einen separaten Filter ansteuert.
Das Adjektiv in musikalischer Raumklangsteuerung soll unterstreichen, was in der eingangs
zitierten Aussage Morton Feldmans über Edgard Varèse zum Ausdruck kommt, und was
Trevor Wishart nur unmerklich variiert, wenn er in Audible Design schreibt:
We [composers] may embark on signal-processing procedures which will appear
”
bizarre to the scientifically sophisticated [...] The question we must ask as musicians however is not, are these procedures scientifically valid, or even predictable,
but rather, do they produce aesthetically useful results on at least some types of
sound materials.“ 11
Dies ist nicht als Aufforderung zu verstehen, unwissenschaftlich zu sein, sondern im Gegenteil,
sich wissenschaftlicher Erkenntnisse zu bedienen, aber sich – also hier das Programm – nicht
auf das zu beschränken, was zunächst wissenschaftlich oder physikalisch plausibel scheint.
8
[Haller 1995], S. 67.
vgl. auch [Eimert/Humpert 1973], S. 328
10
Die Rate dieser Daten wird als Controlrate, abgekürzt kr, bezeichnet und liegt aus rechenökonomischen
Gründen meist etwa ein bis zwei Größenordnungen unter der Abtastrate für Audiodaten.
11
[Wishart 1994], S. 5
9
7
1 Einführung
Musikalische Raumklangsteuerung bedeutet sowohl, daß nicht-physikalische Raumvorstellungen umgesetzt werden können, als auch, daß Brücken zu algorithmischer Komposition vorgesehen sind.
1.1.1 Abgrenzung zu Auralisationsverfahren
Auralisation ist ein Verfahren, das unter Verwendung physikalischer oder mathematischer
Modelle das Schallfeld, in dem sich eine Klangquelle befindet, reproduziert und dem Hörer den
Eindruck vermittelt, tatsächlich an einer bestimmten Position in diesem Schallfeld zu sein.12
Ein anderer Ausdruck ist somit Soundfield Reproduction, zu deutsch Schallfeldreproduktion, als Unterkategorie von (virtueller) Raumakustik. Die wichtigsten technischen Verfahren
sind die Binauraltechnik, das heißt die Raumsimulation durch Einbezug der Kopfübertragungsfunktion (HRTF) und Wiedergabe über Kopfhörer, und die als Transaural-Technik
bezeichnete Lautsprecher-Variante im reflexionsarmen Raum. Daneben wird auch die neuere
Wellenfeldsynthese (WFS) als Auralisationstechnik verwendet.13
Das Ziel der Raumklangsteuerung ist nicht die Auralisation. Kurz dargestellt werden soll
jedoch das WFS Programm Wonder (Abschnitt 1.3.3), da es sich explizit als musikalische
Raumklangsteuerung versteht. Das in dieser Arbeit entwickelte Programm kann natürlich mit
einem Auralisationsverfahren verknüpft werden, es ist allerdings nicht speziell dafür konzipiert. Insbesondere sind Binaural- und Ambisonics-Rendering durch Steuerung von CSound
möglich (siehe Abschnitt 1.5.3). Es wird jedoch nicht auf die akustischen Grundlagen der
Schallfeldreproduktion und des räumlichen Hörens eingegangen.14
1.1.2 Abgrenzung zu Live-Diffusionsverfahren
Das Haupteinsatzgebiet der Software soll in der Komposition liegen, das heißt sie soll optimiert werden für eine Arbeitsweise,
•
in der die Zeitebene der Bearbeitung von der Zeitebene der Performance des Stückes
entkoppelt ist
•
in der die Daten nichtlinear bearbeitet werden
•
in der sich die Bearbeitung über mehrere Sitzungen erstreckt
•
in der Bearbeitungen evtl. verworfen werden
Dies resultiert sowohl aus persönlichen Präferenzen als auch aus der Tatsache, daß im Bereich
der Live-Elektronik bereits sehr mächtige Werkzeuge vorhanden sind. Es ist nicht Aufgabe
dieser Arbeit, eine Software wie Max/MSP zu überbieten, stattdessen soll genau an den
Punkten angesetzt werden, die durch die weitgehende Fixierung auf Echtzeit-Fähigkeit in
Max nicht oder nur ungenügend beachtet werden. Weitere Erläuterung dazu folgen in der
Designspezifikation.
12
sinngemäß nach [Kleiner et al. 1993]
Eine sehr knappe Einführung zu WFS geben [de Vries/Boone 1999]; eine mit Medien aufbereitete Website
ist http://wfs.topicbase.net/
14
Siehe dazu z.B. [Stuart 1996] oder [Schneider 1995], S. 1–22. Im Aufsatz von D. G. Malham wird die Schallfeldreproduktion am Ambisonics Verfahren erläutert ([Malham 1998]).
13
8
1 Einführung
Aus diesem Grund wird auch nicht weiter auf spezielle Live-Diffusions-Strategien eingegangen. Kurz genannt werden soll zumindest die akusmatische Diffusion, in der in der Regel
ein ein- oder zweikanaliges Stück mit Hilfe einer Live-Mischung ( Interpretation“) auf eine
”
Vielzahl unterschiedlicher Lautsprecher verteilt wird, wobei die variablen Charakteristiken
der Lautsprecher gezielt als instrumentale Formung des Klanges betrachtet werden.15
1.2 Historische Wurzeln
Obwohl der Raum als Parameter auch in der klassischen Musik nicht unbekannt war, sich
zum Beispiel in der räumlichen Aufteilung der Instrumentengruppen manifestierte, in der
Ausnutzung der Raumakustik in Kirchen für Chöre usw., und ohne auf spezielle Projekte
wie die utopische Universe Symphony von Charles Ives einzugehen,16 beginnt die gezieltere
Auseinandersetzung mit dem Einsatz von Lautsprechern in der elektronischen und konkreten
Musik, das heißt in den 50er Jahren.17 In Karlheinz Stockhausens Gesang der Jünglinge von
1956 werden fünf kreisförmig angeordnete Lautsprecher-Gruppen verwendet, die das Publikum umgeben, statt ihm frontal zu begegnen.18 Auch in der fünf Jahre davor uraufgeführten Symphonie pour un homme seul von Pierre Schaeffer und Pierre Henry (1950) werden
die Klänge von im Raum verteilten Lautsprechergruppen wiedergegeben. Im Gegensatz zu
Stockhausen ist diese Verteilung weniger Ergebnis eines strikten Auskomponierens, sondern
geschieht durch eine Live-Interpretation auf den unterschiedlich klingenden LautsprecherInstrumenten.
Neben der Erfindung des Radios als der Verräumlichung des Klanges – indem zwischen Sender
und Empfänger praktisch beliebige Distanzen liegen können – ist die Auseinandersetzung mit
Zeit in der Malerei als symmetrischer Gegenpart dafür zu nennen, daß Anfang des 20. Jahrhunderts die Musik begann sich zu verräumlichen. Der einer älteren Generation angehörende,
nach Amerika ausgewanderte Franzose Edgard Varèse arbeitete seit 1929 am letztlich nicht
realisierten Werk Espace, das diese neue Aufmerksamkeit bereits im Titel zeigt. Realisiert
worden ist 1958 das bekannte Poème Électronique für den Pavillon der Firma Philips auf
der Weltausstellung jenes Jahres. Mehrere hundert Lautsprecher auf den Innenflächen des
von Le Corbusier und Iannis Xenakis entworfenen zeltartigen Baus standen ihm für eine
räumliche Komposition zur Verfügung. Das Ausgangsmaterial von Varèse hatte die Form
eines Tonbands mit drei Spuren, von denen zwei stereophonisch verteilt werden konnten und
die dritte aufgezeichneten Raumhall enthielt. Die räumliche Verteilung geschah mit Hilfe
von synchronen Bändern, die Steuerbefehle für Relais enthielten. Die Relais schalteten die
Lautsprecher-Gruppen ein und aus, mit denen sich bestimmte Klangbewegungen realisieren ließen. Angeblich hat Varèse die Intonation“ der Bewegungen der Verantwortung der
”
Ingenieure überlassen.19
15
vgl. [Gertig et al. 1995], S. 325
vgl. [de la Motte-Haber 1996], S. 209
17
Mit dem Beginn des Rundfunks datieren die ersten Lautsprecher in die 20er Jahre, vgl. [Ruschkowski 1998],
S. 56–60; der Aspekt der räumlichen Wiedergabe mittels mehrerer Lautsprecher spielte dabei noch keine
Rolle.
18
[Ruschkowski 1998], S. 242, 252f
19
[de la Motte-Haber 1993], S. 83–110. Nach einem Drehbuch von Le Corbusier wurden zur Musik von Varèse
Dias an die Wände projiziert.
16
9
1 Einführung
1.3 Vorhandene Software zur Raumklangsteuerung
Bei der Entwicklung einer neuen Software ist zunächst zu betrachten, welche bestehenden
Lösungen bereits existieren und wo ihre Vorteile und Nachteile liegen. Ohne Anspruch auf
Vollständigkeit und ohne auf die Vielzahl individueller Patches in Sprachen wie Max einzugehen, sollen die gängigsten Programme vorgestellt werden. Die auf Hardware basierenden Implementationen werden kurz im Anschluß dargestellt. Darauf folgt eine kursorische
Übersicht über Raumklang-Syntheseverfahren, die in Form von Plug-Ins durch eine HostApplikation gesteuert werden können.
Die Grundkonzepte unterscheiden sich in den meisten Fällen nicht von der Pionier-Arbeit
John Chownings20 zu Beginn der 70er Jahre. Darin beschreibt er die akustischen Merkmale
der räumlichen Ortung (interaurale Intensitäts- und Laufzeitunterschiede) und schlägt vor,
zur Simulation räumlicher Distanz variable Reverberation und Frequenz-Filterung zu benutzen. Nach seinem Modell wird mit Hilfe von quadrophonisch den Hörer umgebenden Lautsprechern ein virtueller Raum um den tatsächlichen Abhörraum konstruiert. Die Klangquelle
wird zwischen jeweils benachbarten Lautsprechern gepannt21 , durch variables Delay entsteht
ein Doppler-Shift in Abhängigkeit von der Geschwindigkeit der Bewegung. Die Bewegungen können entweder mit einer mechanischen Eingabevorrichtung in Echtzeit22 oder in Form
einfacher geometrischer Pfade direkt vom Computer erzeugt werden.
Eine Verfeinerung dieses Prinzips wurde später unter anderen im CMusic System von F.
Richard Moore vollzogen.23 Dabei werden zusätzlich die ersten Reflexionen der Klangquelle
von den Wänden des virtuellen Raumes mit einer Tapped-Delay-Line simuliert. Desweiteren
besitzen die Klangquellen eine Abstrahlcharakteristik, die sich aus einer richtungsabhängigen
Lautstärke-Dämpfung ergibt. In CMusic können die Dimensionen der vier Wände des virtuellen und des Abhörraumes bestimmt und die Länge der Hallfahne festgelegt werden. Der
Unit-Generator24 space synthetisiert den Klang im Raum. Das separate Programm sndpath
dient dem Erstellen von Trajektorien-Dateien, die mit dem quad UGen in CMusic eingelesen
werden können.25
1.3.1 APB-Tools Σ 1
Σ 1 (sprich Sigma-One) steht am Beginn der Betrachtung, weil es die flexibelste Raumklangsteuerung darstellt und hinsichtlich der Oberfläche als auch für die Receiver Objekte in dem
hier entwickelten Programm Vorbild war. Technische Details und Funktionsweise können so-
20
[Chowning 1971]
Das englische Wort Panning läßt sich leider schlecht übersetzen. Es beschreibt den Einstellvorgang des
Panoramas, das heißt die Positionierung eines Klangs im (Stereo-)Bild.
22
Eine Wiedergabe in Echtzeit war noch nicht möglich; der Klang wurde nach Ende der Aufzeichnung vom
Computer synthetisiert.
23
[Moore 1983]
24
Zu MUSIC-V vgl. [Ruschkowski 1998], S. 287–291. Eine Übersicht über die MUSIC-V Familie mit Verknüpfungen zum Konzept der Unit-Generatoren bietet http://www.wordiq.com/definition/MUSIC-N
25
siehe dazu [Moore 1985], S.61f, 76–78 und [Loy 1985]. Die Pfade sind durch Stützpunkte definiert, zwischen
denen mit Hilfe von Spline-Funktionen interpoliert wird.
21
10
1 Einführung
Abbildung 1.1: Σ 1 Oberfläche
wohl in der Magisterarbeit von Thomas Schneider26 , auf deren Basis das Programm entstand,
als auch im Online-Manual27 nachgelesen werden.
Σ 1 ist eine Standalone-Applikation für Mac OS Classic, die über eine Mixer-Matrix bis zu 32
Eingangssignale auf bis zu 24 Ausgangskanäle verteilen kann. Die Matrix wird auf Digidesign
ProTools TDM Hardware realisiert und verwendet dazu softwareseitig die Digidesign Audio
Engine (DAE). Dies stellt zugleich Hauptmanko und Hauptvorteil des Programms dar. Zum
einen ist teure Hardware nötig28 , zum anderen arbeitet das Programm nicht mehr mit DAE
Version 5.1 und höher zusammen. Bis eine Neuauflage des Programms erscheint, muß also
– da pro Bootpartition nur eine DAE existieren kann – zum Betrieb eine separate Mac OS
8 oder 9 Partition gebootet werden. Vorteil der DAE Benutzung ist die Möglichkeit, TDM
Plug-Ins verwenden und direkt Spuren aus ProTools Sessions einspielen zu können, wobei
allerdings nur die Regionen-Positionen und die Volume-Automation erkannt werden.
Die Flexibilität des Programms resultiert, abgesehen von der hohen Zahl der Ein- und
Ausgänge, aus der Möglichkeit, Schallquellen auf beliebigen zweidimensionalen Pfaden bewegen und die sogenannten virtuellen Lautsprecher frei positionieren und konfigurieren zu
können. Jedem virtuellen Lautsprecher kann eine benutzerdefinierte Richtcharakteristik“
”
gegeben werden, indem zwei sogenannte Coverage-Tables editiert werden. Die Empfindlichkeit der virtuellen Lautsprecher ergibt sich dabei aus der Summe einer distanzabhängigen
und einer richtungsabhängigen Dämpfung, so daß sich neben Kugel, Niere, Keule und Acht
eine Vielzahl möglicher Charakteristiken ergibt.
Die Oberfläche von Σ 1 besteht aus der zweidimensionalen Raumansicht, Stage genannt,
einem Transport-Fenster, einem Mixer- und Aux-Fenster und einer Region-Playlist sowie einer
Reihe von Werkzeug- und Aktions-spezifischen Dialogen. In Abbildung 1.1 sind Beispiele für
26
[Schneider 1995], S. 39–82. Sein Programm wurde mit Hilfe von Max und externem MIDI-Mixer realisiert,
entspricht jedoch vom gesamten Konzept und der Oberfläche her dem späteren Σ 1.
27
http://apbtools.com bzw. http://apbtools.com/PDFs/SIGMA1_MANUAL.pdf
28
Pro Tools d24 + MIX Farm, Pro Tools MIX oder Pro Tools MIX Plus. Es gibt einen sogenannten OfflineModus, darin ist jedoch keine Audioausgabe möglich.
11
1 Einführung
eine Stage-Anordnung (links) und Coverage-Tables (rechts) abgebildet. Die diskusförmigen
Objekte in der Stage-Ebene stellen die Mittelpunkte der virtuellen Lautsprecher dar, um sie
herum ist die Charakteristik durch abgestufte Farben dargestellt. Die kleinen ballförmigen
Objekte stellen die beweglichen Schallquellen dar. Ihre Bewegungspfade sind als Linienzüge
sichtbar.
Neben der Aufzeichnung von Pfaden in Echtzeit durch Bewegen der Maus29 gibt es die
Möglichkeit, im Offline-Modus Linien und Kreise zu zeichnen und Pfade zu kopieren, zu
verschieben und zu löschen.
Die Berechnung der Ausgangsklänge erfolgt als Intensitätspanning mit Hilfe der dynamischen
M × N Matrix, die aus den M Eingangskanälen und N Ausgangskanälen besteht. Jede Zelle
(m, n) enthält den Quellklang (Zeile m) multipliziert mit der Lautstärkeinformation, die aus
dem Abstand des Klanges von und seinem Winkel zu einem Lautsprecher (Spalte n) gewonnen
wird. Die Summierung einer Spalte ergibt das Ausgangssignal für den jeweiligen Lautsprecher.
1.3.2 zplane.development z.matrix
Einen ähnlichen Ansatz wie Σ 1 verfolgt z.matrix der Firma zplane.development. Wie der
Name andeutet, arbeitet z.matrix ebenfalls mit einer Matrix von Eingangs- und Ausgangskanälen, die Größe ist auf 16 × 16 beschränkt. Auch hier hat man sich auf eine HardwarePlattform festgelegt, die DSP-Karten der Firma Creamware (Pulsar und Scope), was dem
Programm ähnlich wie Σ 1 fast zum Verhängnis wurde, als Creamware im Jahr 2003 Insolvenz anmelden mußte. Mittlerweile hat eine Nachfolgefirma die Creamware-Produkte übernommen, aber die Zukunft der DSP-Systeme ist noch nicht endgültig gesichert.
Das Kernelement der Oberfläche ist die Surface, wieder ein zweidimensionales Momentanbild
mit beweglichen Icons für Lautsprecher und Klangquellen. Daneben existieren Level-Meter
für die Ein- und Ausgänge. Ein Element, das in Σ 1 nicht vorhanden ist, ist der Sweat Spot,
der optimale Abhörpunkt, der bei Mehrkanalbeschallung automatisch entsteht, wenn Panning nach dem Prinzip der Phantomschallquellen arbeitet. z.matrix gleicht unterschiedliche
Entfernungen der Lautsprecher zum Sweat Spot durch ein gegensätzliches Delay aus, so daß
– vorausgesetzt der Hörer sitzt in einer identischen Kopie der Szenerie tatsächlich im Sweat
Spot – alle direkten Wellenfronten kohärent (gleichzeitig) beim Hörer ankommen. Da aus der
Forschung zum räumlichen Hören bekannt ist, daß unterschiedliche Indizien bei der Ortung in
komplexer Weise zusammenwirken, versucht man hier, die Ortung durch Laufzeitunterschiede zu minimieren, so daß sie sich nur an den Intensitäten orientieren kann. Interessant ist
ferner die Möglichkeit, mehrere Quellen in Master/Slave Anordnung zu gruppieren, so daß
die Slave-Objekte dem Master entweder in kartesischen oder polaren Koordinaten folgen.
Im Gegensatz zu Σ 1 besteht keine fixierte Pixelauflösung der Surface, sie läßt sich beliebig
vergrößern, und Quellen können frei benannt werden.
In z.matrix lassen sich die Lautsprecher-Charakteristiken nicht explizit einstellen, allerdings
gibt es einen Divergenz-Parameter für jede Quelle und die Möglichkeit einer Lautstärken-
29
Das Handbuch erwähnt außerdem, daß ein MIDI Joystick oder Dataglove verwendet werden können, macht
dazu allerdings keinerlei weitere Angaben, so daß davon auszugehen ist, daß diese Funktion noch in Planung
ist (zumal das Handbuch als preliminary“ bezeichnet wird).
”
12
1 Einführung
Abnahme in Abhängigkeit der Distanz einer Quelle vom Mittelpunkt der Surface. Zusätzlich
ist pro Quelle ein mit variablen Delays realisierter Doppler-Effekt einschaltbar.
1.3.3 Wonder
Wonder von Marije Baalman30 ist ein Akronym für Wavefield Synthesis of New Dimensions of
”
Electronic Music in Realtime“. Es stellt eine Oberfläche für das Faltungsprogramm BruteFIR
dar, das gemäß den Prinzipien der Wellenfeldsynthese die Eingangssignale verzögert, dämpft
und filtert, bevor sie auf die einzelnen Kanäle eines Lautsprecher-Arrays gegeben werden.
Um Klänge im virtuellen Raum zu bewegen, müssen die Wellenfelder dynamisch erzeugt
werden, das heißt die FIR Filter kontinuierlich überblendet werden. Mit einem Raster wird
festgelegt, von welchen Orten aus der Klang abstrahlen kann. Die Abstrahlung kann alternativ
kugelförmig (als Punktquelle) oder planar (als ebene Welle) erfolgen. Zusätzlich können erste
Reflexionen simuliert werden.
Die Bewegungen können linear zwischen manuell eingegebenen Breakpoints stattfinden oder
im Realtime Modus als Mausbewegung aufgezeichnet werden. Um zu gewährleisten, daß die
Bewegungen synchron mit der Audiowiedergabe abgespielt werden, wird Wonder durch eine
von Daniel Plewe programmierte Open Sound Control Schnittstelle ferngesteuert. Beispielsweise kann ein Max/MSP Patch gleichzeitig die Audio Dateien abspielen und BewegungsKoordinaten an Wonder senden.
Sehr interessant ist die geplante Erweiterung um geometrisch ausgedehnte Klangquellen.
1.3.4 Surround Panning Objekte
Mittlerweile sind die Mixer in allen gängigen Harddisk-Recording-Programmen um SurroundFähigkeiten erweitert worden. Mit den Automations-Engines dieser Programme vereint, stellen sie einfache Raumklangsteuerungen dar. Der Aufbau in den verschiedenen Programmen
ähnelt sich dabei sehr stark. Die Automation geschieht meist spurorientiert, das heißt für
jeden Kanalzug des Mischers existieren neben der Audiospur zusätzlich Spuren für jeden
automatisierten Parameter, wie Lautstärke, Equalizer oder Panorama. Die Automation kann
in der Regel live aufgezeichnet werden, also durch Bewegen von Software-Reglern mit der
Maus – oder externen Controllern wie MIDI-Fadern –, während der Transport läuft. Für
eine Offline-Editierung wird eine Breakpoint-Darstellung der Automationsdaten über oder
unter den Audio-Regionen im Arrangier-Fenster eingeblendet. Mehrdimensionale Parameter
wie ein Surround-Pan werden aus separaten eindimensionalen Werten zusammengesetzt, wie
zum Beispiel Front↔Rear.
Die Panner orientieren sich alle an den Filmformaten, so daß man sich lediglich entscheiden
kann, ob man 5.1“ oder 10.2“ usw. mischen möchte. Die graphische Oberfläche ist eine zwei”
”
dimensionale Fläche, auf der die Lautsprecher als Icons abgebildet sind, angeordnet entweder
im Rechteck oder kreisförmig. Entsprechend wird das Panorama in das Informations-Paar
Azimut/Divergenz oder das Tripel Front-Position/Rear-Position/Front-Rear zerlegt. Emagic
30
http://gigant.kgw.tu-berlin.de/~baalman/
13
1 Einführung
Abbildung 1.2: Panning Objekte in Digital Performer
Logic Pro (Version 6) verwendet den polaren Ansatz, Digidesign ProTools TDM (Version 6)
den kartesischen Ansatz mit dem Tripel-Vektor. Mark Of The Unicorn’s Digital Performer
(Version 4) beinhaltet dagegen beide Modelle und darüber hinaus ein weiteres PanoramaPlug-In, das eine Reverb-Einheit und weitere akustische Modellingfunktionen wie Dopplereffekt und Kopfabschattung enthält.31 Abbildung 1.2 zeigt die Surround-Panner von Digital
Performer.
Von Drittanbietern gibt es diverse Plug-Ins für diese Harddisk-Recording-Programme, die
auf Surround-Formate abgestimmt sind, so zum Beispiel das 360◦ Surround Tools“ Paket
”
der Firma Waves, das Mixer-, Reverb-, Spatializer- und Dynamik-Plug-Ins für die TDM
Schnittstelle enthält.32 Ein weiteres Beispiel ist das Reverb-Plug-In RealVerb 5.1 der Firma
Kind Of Loud. Alle erhältlichen Surround-Plug-Ins hier aufzuführen, würde den Rahmen
sprengen, zumal sich der Markt für Plug-Ins laufend ändert.
1.4 Hardware basierte Raumklangsteuerung
Bevor Computer schnell genug waren, mußten Raumklangsteuerungen mit Hilfe von spezieller
Hardware realisiert werden. Da das Anwendungsfeld kaum kommerzielles Potential besitzt –
wenn man von Surround-Joysticks für Digitalpulte absieht –, handelt es meist um einzelne
Spezialanfertigungen für ein Studio oder ein Projekt.
Das von Hans Peter Haller und Peter Lawo gebaute Halaphon hat durch seine Verankerung im Freiburger Experimentalstudio der Heinrich-Strobel-Stiftung (Südwestrundfunk)
und den Einsatz in Konzerten von beispielsweise Luigi Nono einige Bekanntheit erlangt. In
der ursprünglichen Fassung von 1971 wurden die Lautstärken von vier Lautsprechern mittels
spannungsgesteuerter Verstärker (VCA) geregelt.33 Jeder VCA ist mit einem Oszillator ver-
31
Inwieweit hier eine HRTF Filterung stattfindet, ist unklar. Leider stand mir das Programm nicht zur
Verfügung, und MOTU bietet keinerlei Demoversionen an. Auch spricht die Produktbeschreibung von
einem vierten kartesischen Panner mit der Bezeichnung n-Panner ; worin er sich von dem im Bild gezeigten
TriPan unterscheidet, bleibt ebenfalls unklar.
32
siehe http://waves.com/default.asp?url=content.asp?id=56
33
Die Erläuterung folgt den Ausführungen in [Haller 1995], S. 77–90
14
1 Einführung
bunden, der bestimmte Hüllkurvenverläufe realisieren kann. Durch zeitlich programmierten
Ablauf der Hüllkurven und Umschalten der Zuordnung von Kanälen zu Lautsprechern lassen
sich bewegte Phantomschallquellen realisieren. Das Gerät wurde im Laufe der Zeit an neue
technische Entwicklungen angepaßt und die Kanalzahl erhöht. Haller griff die Ideen Chownings auf (vgl. Abschnitt 1.2), erweiterte den Signalweg im Halaphon um Harmonizer zur
Simulation von Doppler-Effekten, einen Frequenz-Filter und ein Hallgerät. Die Hüllkurven
konnten schließlich graphisch an einem Bildschirm erstellt, abgespeichert und wieder geladen werden. Für den Einsatz des Halaphons in Konzert-Situationen kann der Ablauf live
gesteuert werden. So kann eine Klangbewegung zum Beispiel direkt durch die Dynamik des
Mikrophonsignals eines Instruments verlangsamt oder beschleunigt werden.
Andere Hardware basierte Systeme gehen ähnlich dem Halaphon von einer Art programmierbarem Mischpult aus. Das Problem vorhandener Mischpulte ist meist die beschränkte Zahl
von Ausgangskanälen und die eingeschränkten Routingmöglichkeiten. Für den Raumklangeinsatz müssen gerade die Verteilmöglichkeiten groß sein, während die Zahl der Eingangskanäle untergeordnet ist. Ein solches umgedrehtes“ Mischpult ist der Topoph24, den Sukan”
dar Kartadinata für die Installations-Projekte des Duos <sabine schäfer // joachim krebs>
gebaut hat.34 Ein Hauptrechner steuert mit einem Sequenzer sowohl die Klangerzeuger – zum
Beispiel Sampler – als auch per MIDI einen zweiten Computer, der Raumbeschreibungen in
einzelne Steueranweisungen umrechnet, die wiederum per MIDI an den Steuercomputer des
Mischpults geleitet werden. Das Mischpult verteilt die Audiosignale mit Hilfe von VCAs, die
vom Steuercomputer kontrolliert werden.
Ebenso verteilt die Raumklangsteuerung RKS.1 von Werner Schaller Ausgangssignale mit
einem VCA-Mischer auf bis zu 24 Lautsprecher.35 Mit einem graphischen Editor können
Figuren“ erstellt und per MIDI an den Mischer übertragen werden. Die für eine Figur ver”
wendeten Kanäle können beliebig gewählt werden und müssen nicht benachbarte Lautsprecher repräsentieren. Das Mapping von Kanälen auf Lautsprecher kann später leicht angepaßt
werden.
MIDI war eine der wichtigsten Schnittstellen, um Computer mit Hardware Peripherie zu verbinden. Die Vorarbeit von Σ 1 basierte noch auf einem Max-Patch, das einen Mischer über
MIDI ansteuerte. Einige Jahre früher, 1988, wurde an der TU Berlin ein MIDI Mischer
gebaut, der bis zu 15 Eingangssignale auf 4 Ausgangskanäle verteilen konnte. Um einen
hohen Rauschabstand zu gewährleisten, wurden dabei multiplizierende D/A Wandler statt
VCAs eingesetzt. Das Programm arbeitete mit einem Nulldurchgangs-Detektor, der Knackgeräusche minimierte, die durch die grobe Rasterung der Lautstärke-Stufen entstanden. Der
MIDI Mischer von Torsten Radtke wurde dann 1990 von Thomas Seelig um eine graphische Benutzeroberfläche erweitert, die auf einem Atari Computer lief. Dadurch konnten die
Klangquellen geometrisch plaziert und bewegt werden.36
34
http://www.topophonien.de/2.5-w-d-topoph24.html
vgl. [Hein 1999], S. 106
36
[Radtke 1988] resp. [Seelig 1990]
35
15
1 Einführung
1.5 Raumklang-Synthese Plug-Ins
In diesem Abschnitt sollen einige Plug-Ins und Unit-Generatoren vorgestellt werden, die interessante Synthese-Ansätze für Raumklang darstellen, von sich aus jedoch keine oder kaum
graphische Steuermöglichkeiten bieten. Im Zusammenhang mit der Entwicklung einer Steueroberfläche stellen sie potentielle Synthese- Maschinen“ dar (vgl. Abschnitte 2.2.1 und 2.2.2).
”
1.5.1 VBAP – Vector Based Amplitude Panning
Vector Based Amplitude Panning ist, wie der Begriff vermuten läßt, keine feststehende Software, sondern ein bestimmtes Modell von räumlicher Klangverteilung. Dieses wurde von dem
Finnländer Ville Pulkki entwickelt und steht in Form eines freien Plug-Ins für CSound, Max/
MSP und Pure Data zur Verfügung.37
VBAP verallgemeinert ein auf der sogenannten Tangenten-Regel beruhendes Modell des
Stereo-Pannings auf eine beliebige zweidimensionale (2-D VBAP) oder dreidimensionale (3-D
VBAP) Anordnung von Lautsprechern. Dabei erfolgt ein Amplitudenpanning über die jeweils
zwei respektive drei Lautsprecher, die der Klangquelle am dichtesten sind. VBAP liefert
nur die Gain-Werte, die Programm-Umgebung, in der VBAP eingesetzt wird, muß selbst
dafür sorgen, daß unterschiedliche Abstände der Lautsprecher zum Hörer durch entsprechende Delays nivelliert werden, damit als auditorischer Cue nur die Intensitätsunterschiede
wirken.38 Die durch die Tupel oder Tripel aufgespannten Teilebenen bzw. -räume werden so
berechnet, daß sie sich nicht überschneiden und im Falle einer Bewegung der Klangquelle
automatisch ein weicher Übergang von einem Teilraum in den anderen stattfindet.39
Da die Forschung ergeben hat, daß bei diesem Verfahren der Eindruck der Ausdehnung der
Quelle (spread ) unterschiedlich ist, je nachdem ob ein Klang von einem oder mehreren Lautsprechern (Phantomschallquelle) abgestrahlt wird, wurde ein Divergenzverfahren integriert.
Das Grundkonzept des VBAP, daß eine Quelle maximal von zwei respektive drei Lautsprechern repräsentiert wird, wird dabei durch einen Trick aufrecht erhalten: Aus einer Quelle
werden mehrere beieinander liegende Quellen gemacht, die intern summiert werden. Der Abstand dieser Quellen voneinander hängt von der Höhe der gewählten Divergenz ab.40
VBAP als Plug-In allein ist noch keine vollwertige Raumklangsteuerung, allerdings läßt sich
eine solche mit wenigen Klicks erstellen, wie der Max/MSP-Patch in Abbildung 1.3 zeigt.
Hier wurde der Azimut-Parameter automatisiert, indem mit der Maus der Knopf im Panel
links oben bewegt wird. Alternativ wird durch Klicken auf start rotation“ eine gleichmäßige
”
Kreisbewegung ausgeführt.41 Als Klang wird ein Mono-Soundfile verwendet.
Grundsätzlich verarbeitet ein VBAP Objekt die Steuerdaten für einen Quellklang; sollen
mehrere Klänge unabhängig bewegt werden, müssen weitere VBAP Instanzen erzeugt werden.
37
http://www.acoustics.hut.fi/~ville/software/ . Dort ist auch noch ein älteres Standalone-Demo für
SGI Computer zu finden.
38
vgl. [Pulkki 2001], S. 16f
39
Im Falle der dreidimensionalen Anordnung wird der Klang im Übergangspunkt nur noch von den zwei
Lautsprechern abgestrahlt, die beiden Teilräumen gemeinsam sind.
40
ebd., S. 18
41
vorausgesetzt natürlich, die Lautsprecher sind, wie im define_loudspeakers Objekt zu sehen, kreisförmig
angeordnet.
16
1 Einführung
Abbildung 1.3: VBAP Anwendung in Max/MSP
Das Lautsprecher-Setup im abgebildeten Patch ist kreisförmig in der horizontalen Ebene (2D),
daher wird die Bewegung in der Vertikalen (Elevation 42 ) nicht benutzt. Die Divergenz läßt
sich mit dem Schieberegler einstellen.
1.5.2 IRCAM Spat˜
Das Spat˜ Plug-In, von Jean-Marc Jot und Olivier Warusfel am IRCAM entwickelt,43 hat
einen integrierteren Ansatz als VBAP. Das kommerziell vertriebene Paket besteht aus einer
Reihe zusammengehöriger Objekte für Max/MSP oder IRCAM’s jMax. Insgesamt vier Stufen
durchläuft ein Klang, bis er an den Ausgangskanälen oder Lautsprechern angelangt:
•
Source~ versieht ein Quellsignal mit einer optionalen Entzerrung und variablem Delay,
womit ein Doppler Effekt erzeugt werden kann
•
Room~ ist eine synthetische Multikanal-Reverb-Einheit
•
Pan~ verteilt die Quelle und das Hallsignal im Raum
•
Out~ versieht die zu den Ausgangskanälen geleiteten Klänge mit einer optionalen Entzerrung und einstellbarem Delay und kompensiert so Nichtlinearitäten im Frequenzgang
der Lautsprecher und deren Abstand vom Hörer
Prinzipiell lassen sich die Objekte einzeln benutzen, beispielsweise kann ein Klang direkt in
den Panner geschickt und dessen Output direkt an Lautsprecher gegeben werden, wenn man
auf psychoakustische Modellierung und virtuellen Hall verzichten möchte. Etwas ungewöhnlich mag die Reihenfolge der Module wirken, wonach der Panner hinter dem Hallobjekt sitzt.
Der Grund dafür ist, daß in Pan~ die Lautsprecher-Konfiguration bestimmt wird. Das Room~
Objekt produziert einen formatunabhängigen Hall, der dann in Pan~ je nach Aufstellung der
Lautsprecher mit einer Ambisonics-Matrizierung verteilt wird.
42
43
im VBAP External das dritte Inlet
siehe [Jot/Warusfel 1995]
17
1 Einführung
Abbildung 1.4: Perzeptive Parameter in Spat˜
Das Pan~-Objekt von Spat˜ erlaubt bis zu acht Lautsprecher in einer horizontalen Ebene mit
einstellbaren Winkeln. Für Kopfhörer-Wiedergabe kann auch eine Binaural-Faltung benutzt
werden. Die Positionierung der Quelle wird wie beim VBAP mit den Parametern Azimut und
Elevation eingestellt, allerdings läßt sich ein Quellsignal im Source~ Objekt verzögern und
mit dem Raumprozessor so bearbeiten, daß Nähe- oder Ferne-Effekte entstehen.
Für jede der vier genannten Signal-Stufen gibt es ein Low-Level Kontroll-Objekt, mit dem
die wichtigsten Parameter eingestellt werden können, beispielsweise Room_ für die Earlyund Late-Reflections-Charakteristik des Room~ Objekts. Für Spat~ selbst wurde der spezielle Spat_OPer Patch entwickelt, der in Abbildung 1.4 zu sehen ist. Spat_OPer enthält
perzeptions-basierte“ Parameter, die dann intern auf die DSP Parameter umgerechnet wer”
den. Statt direkt die Raumgröße in physikalischen Einheiten bestimmen zu können, hat man
sich dafür entschieden, qualitative Parameter zu benutzen.
Interessant ist vor allem der Subpatcher, der sich hinter der Bezeichnung radiation verbirgt.
Er enthält eigentlich nur zwei parametrische Dreiband-Equalizer. Mit einer geeigneten dynamischen Steuerung jedoch kann die Klangfarben-Änderung simuliert werden, die entsteht,
wenn eine Klangquelle mit richtungsabhängiger Abstrahlung bewegt wird.
Eine einfache Steueroberfläche wird bereits in Form des Circ Patchers von Gerhard Eckel
mitgeliefert. Bis zu drei Klangquellen können auf einem quadratischen Feld bewegt werden.
Neben Azimut und Distanz wird auch die Abstrahlcharakteristik in Form eines Kreissegments
dargestellt. Die Kontrolldaten von Circ können mit den Spat_Circ und Pan_Circ Patches
so umgerechnet werden, daß die Klangquelle entsprechend der Mausbewegung folgt und die
Radiation-Filterkurven verändert werden.
1.5.3 Spatialisierung mit CSound
Für CSound existieren verschiedene Verräumlichungs-Opcodes. Neben dem beschriebenen
VBAP gibt es die einfachen quadrophonen Panner locsig (polar), pan und space (kartesisch), einen Ambisonics-Panner namens spat3d und einen Binaural-Panner namens hrtfer.
Der Ambisonics-Panner benötigt als Parameter die Position der Klangquelle (x, y, z). Eine
Verzögerung ist ebenfalls vorgesehen, diese läßt sich allerdings nicht dynamisch verändern
– in diesem Fall muß ein anderer CSound Opcode wie vdelayx benutzt werden. Für die
Generierung von Nachhall kann eine spezielle Tabelle angegeben werden, die die Distanzen
und Absorptionswerte für die sechs Wände eines virtuellen kubischen Raumes beschreibt.
18
1 Einführung
spat3d erzeugt ausgangsseitig die vier B-Format Signale W, X, Y, Z. Diese kann man sich
als virtuelle Aufnahmen eines Soundfield-Mikrophons vorstellen, das aus drei orthogonalen
Achter-Charakteristiken und einer Kugel besteht. Mit geeigneten Matrizierungsformeln lassen
sich daraus Signale für beliebig angeordnete Lautsprecher gewinnen.44 spat3d beinhaltet
außerdem eine Stereo-Mixdown Option.
Der Binaural-Panner hrtfer benötigt eine Datei mit Impulsantworten für die Kopfübertragungsfunktion. Das Format ist leider nicht dokumentiert, jedoch gibt es eine entsprechende
Datei auf dem CSound FTP Server. Die Synthese-Parameter sind Azimut und Elevation, eine
entfernungsabhängige Dämpfung oder Verhallung muß separat programmiert werden.
1.6 Notwendigkeit einer neuen Raumklangsteuerung
Das Feld an Raumklang-Software, die flexibel zu gebrauchen ist, ohne daß der Komponist
selbst umfangreiche Programmierarbeiten erledigen muß, ist also recht übersichtlich. Auf die
Einführung der DVD und die zunehmende Verbreitung kleiner Surroundsysteme in Wohnzimmerkinos haben zwar alle Hersteller gängiger kommerzieller Software mit der Erweiterung ihrer Produkte um Surround-Ausgabe-Möglichkeiten reagiert. Viel mehr als eine leichte
Extrapolation der bisherigen Stereo-Technologien hat dabei aber kaum stattgefunden.
Eine Raumklang-Steuerung, die einfach zu bedienen ist, dabei jedoch größtmögliche Flexibilität bietet und den Benutzer nicht auf ein enges Anwendungsfeld beschränkt, die außerdem
einen kompositorischen Umgang mit Raumgestaltung nicht nur erlaubt sondern auch fördert,
und mit der an bereits bestehende Klangsynthese-Software angeknüpft werden kann, ist eine
Lücke, die mit diesem Magisterarbeitsprojekt geschlossen werden soll.
44
Zu Ambisonics und dem B-Format siehe [Malham 1998].
19
2 Entwicklung des Programms Meloncillo
2.1 Tendenzen in der Entwicklung von Musiksoftware
In der gegenwärtigen Entwicklung von Software im Bereich experimenteller Musik sind folgende Tendenzen zu entdecken: Zum einen das rasche Anwachsen der Open-Source Community,
das heißt der Entwicklung von Programmen, deren Quelltexte öffentlich zugänglich sind und
die oft in gemeinsamer Arbeit mehrerer Programmierern entstehen. Zu nennen sind CSound
– an Universitäten entstanden, war es bereits vor der Entwicklung im Open-Source Verfahren kostenlos zugänglich –, SuperCollider, das im Zuge des Wechsels des Autors James
McCartney zu Apple Inc. in ein Open-Source Projekt umgewandelt wurde, zahlreiche kleinere
Programme wie RTcmix, und auch ein Teil der IRCAM Software – vielleicht am beachtlichsten, wenn man die ansonsten eher verschlossene Vertriebspolitik bedenkt –, darunter die
graphische Klangsynthese-Sprache jMax und eine Umgebung für algorithmische Komposition, OpenMusic. Für das Betriebssystem Linux, das selbst Open-Source ist, entwickelt sich
momentan eine eigene Audio Community. Mit den Soundeditoren snd und Audacity, dem
MIDI Sequenzer Rosegarden und dem Harddisk-Recording-Tool Ardour, den plattformübergreifenden Klangsynthese-Programmen jMax, SuperCollider, CSound und Pure Data sowie
der Unterstützung professioneller Soundkarten u.a. von RME steht eine günstige Arbeitsumgebung bereit.
Eine logische Folge daraus ist, daß Programmierer viel mehr Möglichkeiten haben, Schnittstellen zwischen diesen Programmen zu entwerfen. Auch kommerzielle Musiksoftwarefirmen
sind sich bewußt, daß sie den Mehrwert ihrer gewerblich angebotenen Programme erheblich
steigern können, wenn sie eine Entwicklergemeinde finden, die für eine Schnittstelle programmiert, die ihre Software unterstützt. Als wichtiger Anstoß darf die Einführung des VST PlugIn Standards der Firma Steinberg gelten, der sich schnell auf mehreren Rechnerplattformen
und über die Basisapplikation Cubase hinaus durchgesetzt hat.
Der Wunsch, mehrere Audioprogramme miteinander zu verbinden, manifestiert sich seitdem
in zahlreichen Schnittstellen. Im kommerziellen Sektor ist ReWire zu nennen, einer gemeinsamen Entwicklung der Firmen Propellerhead und Steinberg. Im Open-Source Bereich ist ein
ähnlicher Versuch mit dem virtuellen Patchsystem Jack zu beobachten, einer zunächst auf
Linux entwickelten Audiotreiber-Schnittstelle, die mittlerweile auch auf den anderen Rechnerplattformen verfügbar ist und die u.a. von SuperCollider, jMax, PD, Ardour, Rosegarden und
snd unterstützt wird. Die durchschlagendste Entwicklung im Open-Source Bereich dagegen
beschäftigt sich nicht direkt mit dem Transport von Audioströmen, sondern der gegenseitigen
Kontrolle und Highlevel-Steuerung von Programmen. Es handelt sich um ein Kommunikationsprotokoll mit dem Namen Open Sound Control (OSC), das von Matt Wright und Adrian
Freed am Zentrum für Neue Musik und Audiotechnologie CNMAT (Universität Berkeley)
entwickelt wurde.
20
2 Entwicklung des Programms Meloncillo
In gewisser Weise als inoffizieller Nachfolger von MIDI1 gedacht, werden in OSC mit einem
Textkommando beginnende Nachrichten versandt. Definiert ist nur die Syntax, welche konkreten Befehle eine Applikation versteht, ist dabei nicht festgelegt. OSC eignet sich damit
besonders für offene Systeme, die der Benutzer zum Teil oder vollständig selbst programmieren kann, wie SuperCollider, dessen Synthese-Engine in der Version 3 vollständig über OSC
gesteuert wird und das damit als Paradebeispiel für OSC gelten kann, Max/MSP oder Pure
Data (PD). Damit wird es zum ersten Mal möglich, daß zum Beispiel ein Max/MSP Patch
Teile oder die gesamte Klangsynthese an SuperCollider delegiert und sich auf die graphische
Oberfläche als wesentliche Stärke von Max konzentrieren kann.2 Und dies, ohne daß der Anwender einen C-Compiler bedienen und eigene sogenannte Externals oder Unit-Generatoren
programmieren muß.
Ein wichtiger Aspekt in der Entwicklung neuer Musiksoftware wird damit die Anstrengung
sein, Stärken bereits bestehender Systeme auf neue Art und Weise miteinander zu verknüpfen.
2.2 Designspezifikation für eine neue Raumklangsteuerung
Die Kernelemente der neuen Software sollen sein:
•
Trennung von Oberfläche und Signalverarbeitung. Dabei weitgehende Beschränkung
auf eine graphische Benutzeroberfläche und Rückgriff auf externe klanggenerierende
Programme
•
Abstraktion der Oberfläche von dem zugrundeliegenden Synthesemodell
•
Unterstützung sowohl von Anwendern ohne Programmiererfahrung, als auch von solchen, die mittels Musikprogrammiersprachen weitergehenden Einfluß auf die BewegungsGestaltung und Klangsynthese nehmen möchten
•
Betriebssystemunabhängige Implementierung
Desweiteren wurden folgende Entscheidungen zur Programmarchitektur gefällt:
•
Komplementarität aus zwei grundlegenden Objekttypen
•
Komplementarität aus Echtzeit und Offline Anwendung mit Schwerpunkt auf NichtEchtzeit-Betrieb
•
Diskretisierung von Datenströmen
Die genannten Aspekte werden im folgenden erläutert:
2.2.1 Trennung von Oberfläche und Signalverarbeitung
Da für die Entwicklung einer graphischen Benutzeroberfläche und eines SignalverarbeitungsKernels grundsätzlich andere Programmiertechniken verwendet werden – weil auch verschie-
1
2
Ein Überblick über die MIDI Schnittstelle ist zum Beispiel in [Ruschkowski 1998], S. 371–412 zu finden.
Tatsächlich war Pyrite“, ein Vorläufer der SuperCollider Language Application, einmal ein Max Objekt,
”
vgl. [McCartney 1996]
21
2 Entwicklung des Programms Meloncillo
dene Designziele existieren3 –, spricht vieles für eine Trennung dieser beiden Programmteile.
Sind diese Teile hinreichend modularisiert, ergibt sich vor allem der Vorteil, daß größere Änderungen in einem Teil vorgenommen werden können, ohne in den jeweils anderen Part eingreifen zu müssen. Dieselbe Oberfläche kann möglicherweise mit unterschiedlichen austauschbaren
Signalverarbeitungs-Modulen arbeiten und umgekehrt. Außerdem können Alterungserscheinungen abgefedert werden:
This architecture allows to define user-interfaces that provide access to exactly
”
the functionality that is needed by the user, while the back-end can be scaled to
a compromise between the current needs and the hardware possiblities.“ 4
Die gegenwärtigen Klangsynthese Programme sind vom Gesichtspunkt der Signalverarbeitung sehr ausgereift und effizient. Dies kann dagegen nicht von ihren Benutzeroberflächen
gesagt werden, wenn man SuperCollider oder CSound betrachtet. Max/MSP hat eine sehr
ausgereifte Benutzeroberfläche, die Programmierung größer angelegter Patches kann jedoch
leicht unübersichtlich werden, und das Programm ist sehr stark auf den Echtzeit Betrieb ausgerichtet. Von normalen Desktop Anwendungen erwartete Features wie Drag-and-Drop oder
Clipboard Austausch sind höchstens rudimentär vorhanden. Eine klare Trennung von einem
Patch als Instrument und den eingestellten Parametern als Dokument oder Stück ist nicht
vorhanden.
Die zu entwickelnde Software soll sich aus dieser Überlegung heraus weitgehend auf die Oberfläche konzentrieren und im Falle der Signalverarbeitung die Stärken der vorhandenen Programme nutzen.
2.2.2 Abstraktion vom Synthesemodell
In dem Moment, wo die Oberfläche prinzipiell von der Signalverarbeitung getrennt ist, läßt
sich noch ein weiterer Abstraktionsschritt vollführen: Zwischen die Datenstrukturen, die hinter den Oberflächen-Elementen verborgen sind, und der Klangsynthese wird eine Vermittlungsinstanz eingesetzt, die dafür sorgt, daß sich trotz einheitlicher Oberfläche unterschiedliche Arten oder Modelle von Signalverarbeitungen realisieren lassen. Diese Instanz soll eine
kompakte und leicht zu programmierende Script-Sprache sein.
Das bedeutet zum Beispiel, daß Meloncillo weder zu wissen braucht, in welchem exakten
Format und in welcher Reihenfolge die Syntheseengine die Quelldaten benötigt, noch, ob bei
der Synthese eine reine Amplituden-Matrizierung oder eine Kombination mit Filtern oder
Delays verwendet wird. Dies ist die Voraussetzung dafür, daß verschiedene Programme als
Syntheseengines benutzt werden können, ohne auf deren Eigenheiten und Stärken verzichten
zu müssen.
3
Während es in der Signalverarbeitung vor allem um Recheneffizienz und -genauigkeit geht, muß eine Oberfläche in erster Linie Anforderungen an Ergonomie und Konsistenz mit betriebssystemspezifischen StyleGuides erfüllen. Die Programmierung des Oberfläche legt grundsätzlich viel stärkeres Gewicht auf die
Wartbarkeit und Flexibilität des Quellcodes, auch wenn dies nicht immer mit bestmöglicher Performanz
vereinbar ist. Da das Event-Handling nicht auf exaktes Timing angewiesen ist, können hier andere Entwurfsschemata verwendet werden.
4
[Zmölnig et al. 2003]. Der Autor weist auch auf den Vorteil hin, Oberfläche und Audio-Engine auf verschiedenen Rechnern laufen lassen zu können.
22
2 Entwicklung des Programms Meloncillo
Diese Abstraktion ist zugleich der Garant dafür, daß ein Komponist mit Meloncillo neue Ideen
verwirklichen kann, ohne daß jede Idee in der Programmstruktur a priori vorgedacht worden
sein muß. Das weiche Element zwischen Oberfläche und DSP Instanz federt die Erfordernis
ab, bei Entwürfen zu neuen Klangsynthese-Verfahren wieder in den Quelltext von Meloncillo
eingreifen zu müssen.
2.2.3 Anwender mit und ohne Programmiererfahrung
In der elektroakustischen Musik sind zwei unterschiedliche Künstler-Charaktere anzutreffen:
Die einen finden Gefallen daran, selbst die instrumentalen Grundlagen ihrer Stücke zu entwickeln – die ja, anders als in der Instrumentalmusik, nicht automatisch gegeben sind – oder
musikalische Strukturen mit Hilfe von Algorithmen zu erzeugen. Sie besitzen Programmiererfahrung und begegnen rein graphisch orientierten Programmen mit Skepsis. Die andere
Gruppe entwickelt ihre kompositorischen Vorstellungen eher unabhängig von den technischen Rahmenbedingungen der Software und sucht nach Mitteln, diese Vorstellungen mit
möglichst intuitiv zu bedienenden Programmen umzusetzen. Der Gedanke, ästhetische Ideen
ingenieursmäßig auf technische Abläufe herunterzubrechen, schreckt sie ab.
Die graphische Oberfläche soll so gestaltet werden, daß sie von Benutzern bedient werden
kann, deren Computer-Kenntnisse nicht viel weiter reichen als nötig ist, um mit ProTools zu
arbeiten. Der tiefere Eingriff in das Programm und die Verknüpfung mit anderen Programmen wie CSound oder SuperCollider soll durch Definition von Plug-In Schnittstellen geöffnet
werden.
2.2.4 Unabhängigkeit vom Betriebssystem
Applikationen, die über den reinen Charakter eines Utility“ hinausgehen, haben in der Regel
”
eine längere Lebensdauer als das Betriebssystem, für das sie ursprünglich vorgesehen waren.
Dies gilt selbstredend für Programme mit langer Tradition wie CSound, Max, CDP oder die
IRCAM Software. Aber auch jüngere Programme waren beispielsweise von dem Neuanfang
Apple’s mit Mac OS X betroffen. Eine zu enge Festlegung auf ein bestimmtes Betriebssystem
kann das frühzeitige Ende eines Programmes bedeuten, wenn Zeit oder Geld fehlen, jede
Migration mitzumachen, oder wenn eine Plattform mehr oder weniger komplett verschwindet
wie im Falle von Atari, NeXT oder SGI. Benutzer sind oft gezwungen, sich für eine bestimmte
Plattform zu entscheiden, weil es ihr Geldbeutel diktiert, weil eine bestimmte für sie wichtige
Software nur auf dieser Plattform existiert, oder weil sie in einem Studio arbeiten, das auf
diese Plattform ausgerichtet ist.
Die momentan wichtigsten Betriebssysteme im Musikkontext sind Mac OS X, Linux und
Windows XP. Mit den meisten Sprachen läßt sich plattformunabhängig programmieren.
Schwierigkeiten entstehen dann, wenn über eine reine Consolen-Ausgabe hinaus zum Beispiel
eine graphische Oberfläche oder Interaktion mit der Computer-Peripherie (Audio-Hardware)
gewünscht sind. Folgende Möglichkeiten stehen zur Verfügung:
23
2 Entwicklung des Programms Meloncillo
•
eine Sprache mit plattformunabhängigen Bibliotheken wie Java.
•
kommerzielle Produkte wie Xanalysis LispWorks5 , die auf den drei genannten Plattformen einschließlich der Bibliotheken kompilieren. Der Preis von LispWorks beträgt
1000 $, eine Weiterentwicklung als Open-Source Projekt scheidet damit auch aus.
•
eine plattformunabhängige Sprache wie ANSI C oder C++, die mit freien Bibliotheken
gelinkt wird. Verbreitet ist Trolltech’s QT Bibliothek6 , die allerdings entweder unter
der GPL (siehe Abschnitt 3.1) oder kostenpflichtig lizensiert ist. Eine Alternative ist
die Verwendung von Tk/Tcl; die Flexibilität und Ästhetik der erstellten GUIs ist eher
bescheiden.7
2.2.5 Zwei grundlegende Objekttypen
Bei der Betrachtung der vorhandenen Raumklang-Software fällt auf, daß die graphische Oberfläche meist zwei Typen von Objekten kennt: Klangquellen und Lautsprecher. Diese korrespondieren im Signalfluß mit den Eingängen und Ausgängen. Die Beschränkung auf zwei
interagierende Objekte trägt dazu bei, daß die Struktur des Programmes sehr klar bleibt. Die
feste Rollenzuteilung steht einer flexiblen Anwendung jedoch im Wege. Diese zwei Objekte
sollen also rollenunabhängig sein und dennoch komplementäre, sich ergänzende Eigenschaften
besitzen:
•
Ein Receiver ist ein statisches Objekt, das eine flächenförmige Ausdehnung besitzt
und seine Charakteristik – genannt Sensitivität – aus einer Funktion des Ortes auf
dieser Fläche gewinnt.
•
Ein Transmitter ist ein punktförmiges Objekt, das seine Charakteristik aus einer
Bewegung als Funktion der Zeit gewinnt.
Die Bezeichnungen wurden aus Ermangelung besserer Begriffe gewählt und sollen nicht
darüber hinweg täuschen, daß ein Receiver keinesfalls die Rolle eines passiven und ein Transmitter keinesfalls die Rolle eines aktiven Elements übernehmen muß. Vielmehr stehen beide
in einer Beziehung zueinander, die je nach gewähltem Synthesemodell nutzbar gemacht werden kann. Obgleich zum Beispiel die Receiver rein optisch den virtuellen Lautsprechern von
Σ 1 ähneln, können sie auch Klangfelder repräsentieren, die durch Transmitter als bewegte
”
Mikrophone“ abgetastet werden.
2.2.6 Echtzeit und Offline Modus
Im Prozeß des Komponierens gibt es unterschiedliche, sich abwechselnde Formen von Zeit
(vgl. Abschnitt 1.1.2). Ein Stück kann über die Dauer von Wochen bis Jahren entstehen, die
einzelnen Sektionen müssen nicht chronologisch gewachsen sein. Der Vorteil von schnellen
Computern – der auch ein Nachteil sein kann – ist die Möglichkeit, unmittelbar die Resultate eines halbfertigen Stückes anhören zu können. Es ist also anzustreben, daß an dem
5
http://www.lispworks.com/
http://www.trolltech.com/products/qt/
7
Der CSound Frontend Cecilia ist ein Beispiel für eine gelungene Nutzung von Tk/Tcl. Trevor Wisharts
Soundloom Frontend für CDP ist ebenfalls in Tk/Tcl geschrieben. Ebenso die Oberfläche von Pure Data.
Ein halbwegs angenehmes Arbeitsgefühl will sich jedoch – zumindest unter Mac OS X – nicht einstellen.
6
24
2 Entwicklung des Programms Meloncillo
Stück gearbeitet werden kann, indem die performative Zeit des Stücks angehalten wird und
beispielsweise Teile verkürzt oder umgruppiert werden, und zugleich in Echtzeit kontrolliert
werden kann, ob das Ergebnis den Wünschen entspricht. Da vielfach auch eine gestische
Beschreibung von räumlichen Bewegungen gewünscht ist, sollen solche Gesten in Echtzeit
aufgezeichnet werden können. Ein Offline Modus ist auch vom signalverarbeitungstechnischen Gesichtspunkt wünschenswert, weil dadurch Modelle realisiert werden können, deren
Berechnung in Echtzeit aus Gründen der CPU-Kapazität derzeit ausscheidet.
2.2.7 Diskrete Datenströme
Die Funktionswerte der in Abschnitt 2.2.5 genannten Basisobjekte können analytischer und
diskretisierter Natur sein. Eine analytische Beschreibung eines Receivers wäre etwa: Die Sensitivität ist umgekehrt proportional zur Entfernung (f (d) ∼ 1/d). Eine diskretisierte Beschreibung wäre: gegeben sei eine Tabelle mit 1000 Punkten, die durch Abtastung der Funktion
f (dn ) = 1/dn ; dn = n · extent/1000 entstanden ist. Die Sensitivität an einem Punkt mit dem
Abstand d vom Receiver entspricht dem Tabellenwert mit dem Index round(d · 1000/extent).
Entsprechend kann die Bewegung eines Transmitters analytisch durch eine beliebige Kette
von Funktions-Abschnitten gedacht werden: Der Transmitter bewege sich zwischen Sekunde 10 und Sekunde 20 mit konstanter Geschwindigkeit von Punkt (0.25, 0.25) nach Punkt
(0.667, 0.8). Die diskrete Beschreibung wiederum wäre eine Abtastung dieser analytischen
Funktion an gleichmäßig voneinander entfernten Stützpunkten.
Der Vorteil einer analytischen Beschreibung ist die Exaktheit, denn durch die Abtastung
entstehen zwangsläufig Aliasing-Fehler. Eine analytische Beschreibung ist auch viel kompakter, denn im vorangegangenen Beispiel wird die Linie durch zwei Punkte beschrieben,
während eine Abtastung bei 100 Hz für die Bewegung über zehn Sekunden bereits 1000
Punkte benötigt. Soll zu einem späteren Zeitpunkt die Linie verkürzt oder verlängert oder
verlagert werden, so entstehen keine Artefakte und die gesamte Komposition bleibt sehr
sauber“.
”
Die Abtastung hat jedoch entscheidende Vorteile: Der Datenstrom kann an beliebigen Stellen
zerschnitten und umgeordnet werden, ohne daß dadurch kompliziertere Berechnungen nötig
sind. Bei einer Beschreibung mit Hilfe von Breakpoints müssen in diesem Fall neue Punkte eingefügt werden. Soll jetzt zusätzlich eine Sektion rotiert werden, beginnt die Umrechnung der
Breakpoint-Funktionen kompliziert zu werden, es sind trigonometrische Funktions-Abschnitte
nötig. Soll weiterhin eine Unregelmäßigkeit erzeugt werden, kann dem diskreten Datenstrom
einfach Rauschen hinzugefügt werden; in der Breakpoint-Darstellung ist dies nicht möglich,
es müßten also zahlreiche zufällige Punkte erzeugt werden, womit man de facto bei einer gesampelten Funktion endet und zugleich einen immensen Verwaltungsaufwand hat. Der Vorteil
der diskreten Datenströme ist ferner, daß der Datendurchsatz unabhängig von der Editierung
konstant bleibt. Aus diesen Gründen soll zumindest den Transmittern ein diskretes Modell
zugrundegelegt werden. Für die Receiver spielt die Wahl eine eher untergeordnete Rolle.
Obwohl bekannt ist, daß das Ohr eine relativ schlechte räumliche Auflösung besitzt, sollen
die Samples der Transmitter-Trajektorien eine Auflösung von 32-Bit Floating Point und eine
beliebige Abtastrate haben. So wird auch durch wiederholte Transformationen die Signalqualität nicht frühzeitig beeinträchtigt. Der Benutzer kann die Rate seinen Wünschen gemäß
anpassen und beispielsweise mit Modulationen im Audio-Frequenzbereich experimentieren.
25
3 Programmarchitektur
Konventionen
Im Fließtext werden programmiersprachliche Schlüsselwörter, Namen von Klassen, Paketen
und Variablen in Schreibmaschinenschrift gesetzt. In den Klassendiagrammen wird eine
Auszeichnung nach Abbildung 3.1 vorgenommen.
3.1 Sprache und Arbeitsumgebung
Meloncillo wurde mit Java 1.4.2 SE entwickelt1 . Als integrierte Programmierumgebung (IDE) diente Apple Xcode Version 1.12 . Die
Entwicklung fand auf einem G4/800 mit Mac OS 10.3 statt.
Interface
implementor/
subclass
Ein Kernelement von Java ist jedoch die Möglichkeit, vollkommen
Abstract Class
plattformunabhängige Programme zu erstellen. Voraussetzung ist,
daß auf der Zielplattform eine sogenannte Virtual Machine (VM)
Class
verfügbar ist. Die VM enthält einen Just-in-Time (JIT) Compiler, der die vorkompilierten Java Klassen in dem Moment, in dem
instance variable
sie benötigt werden, übersetzt. Eine Vielzahl der Bibliotheken des
instanceof
Standard-API arbeitet sehr eng mit nativen (plattformabhängigen)
Collection
Bibliotheken zusammen – dies gilt beispielsweise für die GraphikAusgabe –, so daß die Performance von Java Applikationen im allgemeinen sehr hoch ist. Als für Echtzeitanwendungen hinderlich
wird oft angesehen, daß der Programmierer keine Kontrolle über
Abbildung 3.1: Legende
den automatischen Garbage-Collector hat3 . Tatsächlich entscheidender ist das Fehlen von präzisen Clock Objekten, die erst für
kommende Java Versionen angekündigt sind. Dieses Problem wird
bei der Echtzeit-Schnittstelle erläutert.
1
Zur Sprachspezifikation von Java siehe [Gosling et al. 2000]. Diese hat sich über die verschiedenen Versionen
praktisch nicht geändert, neu in Version 1.4 ist lediglich das Konzept der Assertions (siehe http://java.
sun.com/j2se/1.4.2/docs/guide/lang/assert.html) Die wesentlichen Änderungen zu Vorgängerversionen bestehen stets aus der Erweiterung der Bibliotheken. Wichtige Bibliotheken von Version 1.4, auf die
in Meloncillo zurückgegriffen wird, sind u.a. die java.util.prefs (für Preferences) und java.nio (NewI/O für Eingabe- und Ausgabeströme) Packages. SE ist die Standard-Edition von Java, deren SDK frei
erhältlich ist, daneben gibt es noch eine Enterprise-Edition (EE), die hier jedoch keine Rolle spielt.
2
kurz vor Fertigstellung wurde auf Version 1.5 gewechselt
3
Im Gegensatz zu C++ werden in Java nur in Ausnahmefällen finalize Methoden, d.h. Methoden zur Freigabe von Ressourcen nicht mehr benötigter Objekte, explizit benutzt. Stattdessen verfolgt der GarbageCollector, wann ein Objekt nicht mehr referenziert wird und damit freigegeben werden kann. Diese Freigaben erfolgen in unregelmäßigen Intervallen und können damit das Echtzeit-Timing beeinträchtigen.
26
3 Programmarchitektur
Meloncillo wurde erfolgreich auf Mac OS X und mit der Sun VM auf Windows XP und
Linux/KDE getestet. Sun’s Linux Support beschränkt sich auf Intel-Prozessoren, auf PowerPC
(Macintosh) Computern ist eine alternative VM wie Blackdown erforderlich. Die Blackdown
PPC Version reicht momentan leider nur bis Java 1.2.2.4
Java wurde als Sprache gewählt, weil der objekt-orientierte Ansatz (OOP) sich hervorragend
für die Entwicklung modularer Systeme eignet. Da der Hauptaspekt von Meloncillo auf der
Programmierung der graphischen Oberfläche liegt, spielt Java hier mit den Technologien
Swing und Java2D seine Vorteile gegenüber C++ aus.
Swing ist eine umfangreiche Bibliothek zum Erzeugen von GUI Objekten wie Fenstern,
Menüs, Buttons, Listen, Textfeldern usw. Es bietet ein ausgereiftes Event-Management5 und
eine Vielzahl von Layout-Managern6 an. Für das tatsächliche Aussehen der GUI Elemente
wird ein austauschbares Look-and-Feel verwendet, so daß sich Java Programme an die Optik
nativer Programme anlehnen können.
Java2D ist eine Graphikbibliothek für zweidimensionale Oberflächen, auf die später noch
genauer eingegangen wird. Im Zuge der Anbindung von Meloncillo an Open Sound Control kann auf die Packages java.net (Netzwerk-Funktionen) und java.nio (Input/Output
Funktionen und Buffer) zurückgegriffen werden. Durch die automatische Garbage-Collection
und umfangreiche Debugging Möglichkeiten zur Laufzeit (Java Reflection) wird die Programmentwicklung und -wartung erheblich erleichtert. Nicht zuletzt ausschlaggebend für die
Sprachwahl ist die umfangreiche Erfahrung des Autors mit Java.
Neben den Standard-Java-Bibliotheken werden folgende externe Bibliotheken verwendet:
•
MRJAdapter von Steve Roy stellt Funktionen zur Verfügung, mit denen das Programm
sich besser an das Look-and-Feel von Mac OS anpassen kann, ohne dadurch seine
Plattformunabhängigkeit einbüßen zu müssen.7
•
Jatha von Micheal Hewett stellt eine kompakte Common Lisp Umgebung mit Brückenfunktionen zu Java dar und wird im Plug-In Teil genauer erläutert.
Beide Bibliotheken stehen unter der GNU Lesser General Public License (LGPL) und lassen
sich damit rechtlich unkompliziert benutzen8 .
4
http://www.blackdown.org/java-linux/java2-status/index.html
Events sind hier Ereignisse, die durch Aktionen des Benutzers an GUI Elementen ausgelöst werden. Ein
ActionEvent kann z.B. durch Klicken auf einen Button ausgelöst werden, ein ComponentEvent durch Vergrößern eines Objekts bei Änderung der Fenstergröße. Die Applikation installiert sogenannte Listener, d.h.
Callback-Interfaces, die Benachrichtigungen über diese Events bekommen.
6
Ein Layout-Manager benutzt ein bestimmtes Modell, um die GUI Elemente dynamisch, d.h. zur Laufzeit und in Abhängigkeit von der Fenstergröße, Schriftgröße usw., anzuordnen. Einfache Manager verwenden z.B. ein Raster-Modell, andere benutzen Modelle mit elastischen Modulen zwischen Objekten
(javax.swing.SpringLayout). Im Sinne der Objektorientierung fragen sie die Objekte nach ihren bevorzugten, minimalen und maximalen Ausmaßen.
7
MRJAdapter verwaltet z.B. grundlegende Menü-Punkte wie Preferences und Quit. Es erlaubt das Versehen von Dokumentdateien mit sogenannten Creator-Codes und File-Types. http://www.roydesign.net/
mrjadapter/
8
Diese von der Free Software Foundation erarbeite Lizenz für Open-Source Bibliotheken sichert wie die
bekanntere General Public License (GPL) die Rechte des Benutzers – er darf zum Beispiel die Software
selbst modifizieren –, hat jedoch aus Sicht des Programmierers, der diese Bibliothek benutzen will, den
Vorteil, daß dessen eigene Applikation nicht wie im Falle der GPL ebenfalls frei (unkommerziell und OpenSource) sein muß. http://www.gnu.org/licenses/lgpl.html
5
27
3 Programmarchitektur
3.2 Packages Überblick
Inhaltlich zusammengehörige Klassen werden zu Paketen (packages) zusammengefaßt, dabei
wird üblicherweise eine durch Punkte getrennte, von links nach rechts absteigende Hierarchie
benutzt, die an Internet-URLs anlehnt ist. Dadurch können später andere Pakete ergänzt
werden, ohne daß Namenskonflikte auftreten. Das hierarchisch oberste Paket (root) heißt
de.sciss.meloncillo. Es enthält die Klasse Main, die von der VM gestartet wird und die
Klasse Session, die das Dokument des Programms beschreibt (Abschnitt 3.3). Die untergeordneten Packages sind:
•
debug : Fehlerkontrolle während der Programmentwicklung
•
edit : Editierungen, die rückgängig gemacht werden können (Undo/Redo)
•
gui : Graphical User Interface Elemente
•
io : Datei Input/Output
•
lisp : Lisp-Interpreter und Erweiterungen
•
math : mathematische Funktionen und Signalverarbeitung
•
net : Netzwerkobjekte (Open Sound Control)
•
plugin : allgemeine Plug-In Schnittstelle
•
realtime : Echtzeit Plug-In Schnittstelle
•
receiver : Receiver-Objekte, -Gruppen, -Ereignisse
•
render : Offline Plug-In Schnittstelle
•
timeline : Timeline-Objekte
•
transmitter : Transmitter-Objekte, -Gruppen, -Ereignisse
•
util : verschiedene Hilfsklassen
3.3 Session
Meloncillo ist als Single-Document-Application (SDA) konzipiert, das heißt, der Benutzer
hat es stets mit einem aktuellen Dokument zu tun, das alle relevanten Datenobjekte enthält.
Diese Objekte werden beim Löschen des Dokuments entfernt, beim Laden des Dokuments
ausgetauscht, bestehen also für die Dauer einer Sitzung. Das zentrale Dokument in der Applikation wird daher – in Analogie zu Digidesign ProTools und ähnlichen Programmen9 –
als Session bezeichnet. Die Session Klasse besteht im wesentlichen aus den drei Objekten ReceiverCollection10 , TransmitterCollection und Timeline, wie in Abbildung 3.2
gezeigt. Diese sind direkt als öffentliche Instanzvariablen zugänglich.
9
Ein Gegenbeispiel für eine Multi-Document-Application ist Emagic Logic Pro, bei dem grundsätzlich beliebig viele Dokumente gleichzeitig geöffnet sein können. Dies erhöht allerdings die Anforderungen an den
Programmierentwurf erheblich, so daß auf ein MDA Design verzichtet wurde.
10
Collection ist ein grundlegendes, im Paket java.util enthaltenes interface, das die Gruppierung
von Elementen beschreibt und Methoden zum Hinzufügen und Entfernen von Elementen definiert.
ReceiverCollection und TransmitterCollection enthalten ähnlich benannte Wrapper-Methoden für die
Gruppe von Receivern und Transmittern, die sie verwalten.
28
3 Programmarchitektur
Session
receiverCollection
transmitterCollection
timeline
Timeline
rate
length
position
visibleSpan
selectionSpan
ReceiverCollection
collReceivers
collSelection
TransmitterCollection
collTransmitters
collSelection
Receiver
ReceiverEditor
Transmitter
TransmitterEditor
AbstractReceiver
AbstractReceiverEditor
AbstractTransmitter
AbstractTransmitterEditor
SigmaReceiverEditor
SimpleTransmitter
SigmaReceiver
distanceTable
rotationTable
rcv
SimpleTransmitterEditor
mte
trns
Abbildung 3.2: Session Struktur
Sowohl Session, als auch ReceiverCollection, TransmitterCollection und Timeline
implementieren das Interface11 XMLRepresentation. Dieses ist über zwei Methoden definiert:
Quelltext 3.1: XMLRepresentation.java (io package)
public interface XMLRepresentation
{
public void toXML( Document domDoc, Element node ) throws IOException;
public void fromXML( Document domDoc, Element node ) throws IOException;
}
XML steht für Extensible Markup Language und ist eine aus SGML hervorgegangene Datenbeschreibungs-Sprache, die vom W3C (World Wide Web Consortium) standardisiert wird12 .
Das Interface besagt, daß die Session in eine XML Node umgewandelt werden kann oder
seine Elemente aus einer XML Node regeneriert werden können13 . Diese Methoden werden
benutzt, um die Session abzuspeichern und zu laden. XML bietet zahlreiche Vorteile, darunter
die einfache Lesbarkeit der Dateien im Textformat ( human readable“) und die automatische
”
11
Java Interfaces definieren Methoden, die ein Objekt implementiert. Der Ausdruck Interface ist recht zutreffend, weil es sich dabei in der Regel um Fähigkeiten handelt, die nicht spezifisch für eine bestimmte Klasse
sind, sondern eher die Schnittstelle zu einer anderen Technologie beschreiben. Während eine Klasse nur
eine Superclass beerben kann, kann sie beliebig viele Interfaces implementieren. Das zweite Interface, das
Session implementiert, heißt FilenameFilter und ist im Paket java.io definiert. Es besagt, daß Session
die Fähigkeit besitzt, Dateinamen nach einem bestimmten Prinzip zu filtern. Dies wird benutzt, um beim
Öffnen der Session nur XML Dateien anzuzeigen.
12
http://www.w3.org/XML/1999/XML-in-10-points . Zur Einführung sei auch auf die FAQ http://www.ucc.
ie/xml/ verwiesen.
13
Ein XML Dokument besteht aus einer hierarchischen Baumstruktur mit Knoten, die Nodes genannt werden.
29
3 Programmarchitektur
Verifizierung der Dateien anhand einer Document Type Definition (DTD). Die Entwicklung
einer DTD ist ein nicht ganz triviales Unterfangen, und Meloncillo Sessions benutzen im
Moment noch keine explizite DTD.
Wird die Session abgespeichert, enthält die XML Datei die entsprechenden Repräsentationen
der Session Objekte und der Collection-Elemente – Receiver und Transmitter –, die ihrerseits das Interface unterstützen. Mit abgespeichert werden ferner Programm Preferences, die
für die Session relevant sind. Große binäre Datenmengen wie die Trajektorien der Transmitter können nicht zufriedenstellend mit XML dargestellt werden und werden daher in einem
speziellen Unterordner unabhängig von der Session-Datei abgespeichert.
3.4 Receiver, ReceiverCollection
Das ReceiverCollection Objekt verwaltet die Receiver einer Session. Es beinhaltet Methoden zum Hinzufügen und Entfernen von Receivern. Ein Subset von Methoden dupliziert diese
Collection-Operationen in Hinblick auf eine Untergruppe der Receiver, nämlich die Gruppe
der ausgewählten Receiver. Dies bezieht sich auf die graphische Oberfläche, auf der der Benutzer ein oder mehrere Receiver auswählen kann. Die ausgewählten Receiver werden optisch
anders dargestellt und stellen die Untergruppe der Receiver dar, auf die Editierungs-Befehle
wie Ausschneiden, Kopieren, Umbenennen oder Bewegen wirken. Die selektionsbezogenen
Methoden beginnen mit dem Term selection. Kann zum Beispiel mit ReceiverCollection.
contains() befragt werden, ob ein Receiver in der Gruppe aller Receiver enthalten ist, so
liefert ReceiverCollection.selectionContains() Auskunft darüber, ob ein Receiver der
Gruppe der ausgewählten Receiver angehört usw.
Die eigentlichen Receiver Objekte werden fast ausschließlich über das Receiver Interface
angesprochen, das im folgenden abgedruckt ist:
Quelltext 3.2: Receiver.java (receiver package)
public interface Receiver
{
public static final DataFlavor receiverFlavor =
new DataFlavor( Receiver.class, null );
public void setAnchor( Point2D newAnchor );
public void setSize( Dimension2D newSize );
public Point2D getAnchor();
public Dimension2D getSize();
public Rectangle2D getBounds();
public void setName( String newName );
public String getName();
public void setDirectory( File f );
public File getDirectory();
public void getSensitivities( float[][] points, float[] sense,
int off, int stop, int step );
public Shape getOutline();
public Class getDefaultEditor();
}
Die Entscheidung, für die Receiver ein Interface zu definieren, begründet sich durch den
Abstraktionsgrad, der den Receivern zugeschrieben werden soll. Außerdem erlaubt es einer
30
3 Programmarchitektur
Klasse, gleichzeitig das Receiver und Transmitter Interface zu implementieren. Die Abstraktion besteht darin, beispielsweise nicht festzulegen, daß ein Receiver kreisförmige Ausmaße
haben muß und seine Charakteristik aus einer Distanz- und einer Rotationstabelle schöpft,
sondern nur zu definieren,
•
daß der Receiver über einen Ankerpunkt und ein äußeres, seinen Umriß umspannendes
Rahmenrechteck verfügen soll (getAnchor() und getBounds()).
•
daß der Receiver über einen Namen identifiziert werden kann (getName())
•
daß der Receiver durch eine schematische Umrißlinie dargestellt werden kann (getOutline())14
•
daß der Receiver eine bestimmte ortsabhängige Sensitivität besitzt (getSensitivities).
points ist eine Liste von kartesischen Koordinaten; die Sensitivitäten an diesen Punkten werden als Ergebnis in das Array sense geschrieben.
•
daß es einen Standard-Editor gibt, um den Receiver zu bearbeiten (getDefaultEditor())
Um diese grundlegenden Methoden nicht jedesmal vollständig implementieren zu müssen,
wurde die Klasse AbstractReceiver entworfen, von der dann spezielle Receiver wie der
später beschriebene SigmaReceiver erben können.
Die File bezogenen Methoden waren nötig, um das Laden und Abspeichern der Daten,
die den Receiver konstituieren, zu ermöglichen. Sie hätten vielleicht besser in einem eigenen
Interface untergebracht werden sollen.
DataFlavor gehört zum Paket java.awt.datatransfer und beschreibt die Möglichkeit, ein
Objekt für Clipboard- oder Drag-and-Drop Operationen zu formatieren. Das Feld receiverFlavor beschreibt das Wrapper-Format, mit dem Receiver beim Benutzen der Funktionen
Ausschneiden / Kopieren / Einfügen dargestellt werden.
3.5 Transmitter, TransmitterCollection
Die theoretische Komplementarität von Receivern und Transmittern soll auch in der Programmstruktur deutlich werden. TransmitterCollection beschreibt damit spiegelbildlich
alle Gruppierungsfunktionen, die in ReceiverCollection vorhanden sind, wendet sie jedoch
auf die Transmitter einer Session an. Entsprechend ist Transmitter ein Interface, das verschiedene konkrete Transmitter mit unterschiedlichen Datenmodellen unterfüttern können:
Quelltext 3.3: Transmitter.java (transmitter package)
public interface Transmitter
{
public void setName( String newName );
public String getName();
public void setDirectory( File f );
public File getDirectory();
public Class getDefaultEditor();
public MultirateTrackEditor getTrackEditor();
}
14
java.awt.Shape ist eines der grundlegenden Interfaces von Java2D, das beliebig geformte Umrißlinien oder
Flächen beschreibt
31
3 Programmarchitektur
Mit der Methode getTrackEditor wurde jedoch schon eine weitgehende Festlegung getroffen.
Sie liefert ein Objekt, das die Trajektorien des Transmitters verwaltet. Um in einer späteren Programmversion andere Datenmodelle zu verwenden als das gegenwärtige der Klasse
SimpleTransmitter, sollte hier wahrscheinlich statt der konkreten Klasse MultirateTrackEditor ebenfalls ein Interface TrackEditor zurückgeliefert werden.
Analog zu Receiver gibt es eine basale implementierende Klasse AbstractTransmitter, von
der konkrete Transmitter erben können.
3.6 Timeline
Das Timeline Objekt beschreibt die Länge der Session, die gegenwärtige Zeitposition und die
Sample-Rate der Trajektorien. Sie verwaltet zwei Teilbereiche, selectionSpan – der aktuell
ausgewählte Zeitbereich, der von Editierungs-Operationen betroffen ist – und visibleSpan –
der im TimelineFrame dargestellte Zeitausschnitt.
3.7 Events
Objekte sollten von dem Innenleben anderer Objekte so wenig wie möglich wissen, sie kennen
nur die öffentlich gemachten Methoden.15 Um die Flexibilität zu wahren, sollte die Interaktion
zwischen Objekten von unten“ realisiert werden; das bedeutet, daß ein Objekt sich möglichst
”
selbst darum kümmern sollte, an benötigte Informationen zu gelangen, statt diesen Vorgang
durch ein hierarchisch übergeordnetes Objekt zu initiieren.
Die ReceiverCollection braucht zum Beispiel nicht wissen, welche Objekte daran interessiert sind, auf Receiver zuzugreifen. Stattdessen bietet sie eine standardisierte Schnittstelle
an, über die sich Interessenten registrieren lassen können. Die einzig erforderliche Gemeinsamkeit dieser Interessenten ist die Implementierung eines Listener Interfaces. Hier das Beispiel
des ReceiverCollectionListeners:
Quelltext 3.4: ReceiverCollectionListener.java (receiver package)
public interface ReceiverCollectionListener
extends EventListener
{
public void receiverCollectionChanged( ReceiverCollectionEvent e );
public void receiverCollectionTransformed( ReceiverCollectionEvent e );
public void receiverCollectionSelected( ReceiverCollectionEvent e );
}
Die ReceiverCollection bietet Methoden zum Anmelden und Abmelden eines ReceiverCollectionListeners an. Wenn eine Veränderung eines Receivers oder einer Gruppe von
Receivern auftritt, so werden alle angemeldeten Listener benachrichtigt, indem eine der im
Quelltext 3.4 gezeigten Callback-Methoden aufgerufen wird. Klickt der Benutzer zum Beispiel
einen Receiver an, so stellt dies eine Veränderung der Gruppe der selektierten Receiver dar,
15
Methoden, die mit dem Schlüsselwort public beginnen; Methoden, die protected deklariert werden, sind
innerhalb desselben Pakets öffentlich.
32
3 Programmarchitektur
und die Methode receiverCollectionSelected jedes einzelnen Listeners wird aufgerufen.
Genauere Informationen zu dem Ereignis kann er dem ReceiverCollectionEvent Argument
entnehmen.
Der Vorteil von diesem Konzept, das in ähnlicher Art auch von den Java AWT und Swing Paketen verwendet wird, ist die Möglichkeit, daß sich neue Objekte dynamisch in die Eventverarbeitung einklinken können. Alle Objekte, die Events generieren – neben den drei Bestandteilen der Session sind dies vor allem GUI Elemente wie VectorEditor usw. –, implementieren
das Interface EventManager.Listener. Sie generieren ein Hilfsobjekt, den EventManager,
der den eigentlichen Dispatcher darstellt, das heißt die Verwaltung der Listener und des
Event-Queue übernimmt und neu eingetroffene Ereignisse weiterleitet. Um das Multitasking
berechenbar zu machen, werden in Analogie zum Event System von Java Swing alle Events
von Meloncillo ebenfalls über den Swing Event Thread verteilt.
3.8 Threads
Der Event Thread16 ist der Hauptthread in Meloncillo. Alle Reaktionen auf das GUI werden zunächst innerhalb des Event Threads bearbeitet. Preferences Änderungen, die zumindest in der Apple VM einen separaten Dispatcher verwenden, werden mit der Hilfsklasse
LaterInvocationManager ebenfalls an den GUI Event Thread delegiert.
Wenn zeitaufwendige Prozesse anstehen, zum Beispiel das Öffnen einer Session, das Rendern
von Trajektorien-Daten oder das Bounce-to-Disk, muß ein zweiter Thread gestartet werden,
um die Reaktivität der GUI nicht zu stoppen. Dies geschieht in der Regel durch eine neue
Instanz von ProcessingThread.17
Ein weiterer wichtiger Thread ist der Transport, ein Objekt, das die Echtzeit-Verarbeitung
verwaltet. Dieser Thread wird zum Programmstart generiert und pausiert, wenn der Transport gestoppt ist; während des Wartens auf Transport-Befehle findet keine CPU Belastung
statt. Damit der Rhythmus der Uhr-Ticks im Echtzeit-Betrieb nicht beeinträchtigt wird, versendet das Lisp Realtime Plug-In (Abschnitt 5.3.1) OSC Datenpakete nicht aus dem Transport, sondern aus einem weiteren Thread.
Der letzte wichtige Fall für eigenständige Threads ist der Empfang von OSC Nachrichten,
der von der Klasse OSCReceiver bewerkstelligt wird. Der Thread pausiert automatisch, wenn
keine Nachrichten eintreffen. Erreicht ein neues Datagramm den Empfänger, wird der Thread
16
Threads sind nebenläufige Prozesse. Zwar arbeiten in der Regel nur ein oder zwei Prozessoren im Computer, das Betriebssystem schaltet jedoch in rascher Reihenfolge zwischen den aktiven Threads um, so daß
praktisch mehrere Aufgaben (Tasks) gleichzeitig bewerkstelligt werden können. In Java ist ein bestimmter Thread – der Event Dispatcher Thread – für die gesamte GUI Verwaltung zuständig, einschließlich
der Bekanntmachung von Eingabe-Ereignissen (z.B. Mausbewegungen, Button-Klicks) und dem Aufruf
von Methoden, die die GUI Elemente zeichnen (paint Methode). Zur Einführung in Java-Threads siehe
[Lea 1997], S. 8–26
17
Wenn der Prozeß synchronisiert ist (einen blockierenden sogenannten Monitor auf ein Objekt besitzt),
werden die Dispatcher währenddessen angehalten, so daß Veränderungen erst im Anschluß weitergeleitet
werden. Zum Beispiel werden beim Öffnen einer Session viele verschiedene Änderungen an der Gruppe der Receiver und Transmitter vorgenommen. Diese Veränderungen werden weitergeleitet, wenn der
Lade-Vorgang abgeschlossen ist, um eine Deadlock-Situation, die durch konkurrierende Synchronisierungsversuche entstünde, zu vermeiden.
33
3 Programmarchitektur
fortgesetzt, und er benachrichtigt alle registrierten Listener. OSC wird im Abschnitt 5.4.2
beschrieben.
Objekte, auf die potentiell von verschiedenen Threads zugegriffen werden kann, müssen
synchronisiert werden, das heißt mit einem Mechanismus ausgestattet sein, der Interferenzen unterbindet, die zu undefinierten Zuständen in oder ungültigen Informationen über
diese Objekte führen. Dafür wurde die Klasse LockManager entwickelt, die über das einfache Synchronisations-Konzept von Java hinaus zwischen geteilten Lese- und exklusiven
Schreib-Zugriffen unterscheidet.18 Die Session besitzt einen LockManager für die Objekte
ReceiverCollection, TransmitterCollection und Timeline.
18
vgl. [Lea 1997], S. 133–136 und 169–171
34
4 Graphische Benutzeroberfläche
4.1 Surface : zweidimensionale Momentansicht
Das graphische Hauptelement der meisten Raumklangsteuerungen ist eine schematische Sicht
auf das räumliche Szenario. Dabei handelt es sich oft um eine zweidimensionale Momentansicht. Durch Bewegen der Zeitachsen-Position oder Starten des Transports werden die dynamischen Objekte animiert. Diesem Videoschirm-Paradigma“ folgt auch Meloncillo. Während
”
einige Programme auch dreidimensionale Raumansichten bieten1 oder als Middleware für Virtual Reality 3D-Applikationen fungieren2 , folgt die planare Editierung aus der ausschließlichen Zweidimensionalität gegenwärtiger Computersysteme (Bildschirm, Maus/Joystick/
Tablett).
Die Surface Klasse ist zuständig für die 2D-Sicht in Meloncillo. Eine solche Darstellung ist
in Abbildung 4.1 abgedruckt. Receiver und Transmitter werden durch kleine rote respektive grüne Fadenkreuze dargestellt, die mit dem Namen der Objekte versehen sind. Die
Umrißlinie der Receiver ist gestrichelt dargestellt. Optional wird die Sensitivität der Receiver in Grauschattierungen gezeigt. Wird die Zeitachsen-Position verändert, bewegen sich
die Transmitter entsprechend. Um die Trajektorien besser beurteilen zu können, werden sie
optional eingeblendet: Ein grüner gestrichelter Pfad stellt den Verlauf der Trajektorien der
ausgewählten Transmitter im ausgewählten Zeitabschnitt dar. Die Auflösung, d.h. die Zahl
der Stützpunkte, wird automatisch heruntergeschaltet, wenn der Zeitabschnitt größer wird,
um eine ausreichende Geschwindigkeit der Graphikdarstellung zu gewährleisten. Das Konzept
der stufenweise aufgelösten Trajektoriendaten wird im Abschnitt 4.2.1 erläutert.
Alle Graphikbefehle sind im Rahmen von Java2D realisiert, dadurch läßt sich das Surface
Fenster stufenlos vergrößern. Alle Objektkoordinaten werden in einem virtuellen Raum ausgedrückt, der auf die Größe 1.0×1.0 normalisiert ist. Dazu implementiert Surface das Interface
VirtualSurface:
Quelltext 4.1: VirtualSurface.java (gui package)
public interface VirtualSurface
{
public Point2D snap( Point2D freePt, boolean virtual );
public Point2D screenToVirtual( Point2D screenPt );
public Point2D virtualToScreen( Point2D virtualPt );
public Rectangle virtualToScreenClip( Rectangle2D virtualClip );
public Shape virtualToScreen( Shape virtualShape );
public Shape screenToVirtual( Shape screenShape );
}
1
2
vgl. die IEM-Cube Software in [Zmölnig et al. 2003]. Siehe auch [Momenti/Wessel 2003].
vgl. das Scream Projekt in [Leahy 2004], das eine Anbindung an 3D Spiele und Multimedia vorsieht; ähnlich
das Sonificator Projekt in [Mühlethaler/Schuppisser 2004], für das eine graphische Java3D Anwendung
geschrieben wurde.
35
4 Graphische Benutzeroberfläche
Abbildung 4.1: Surface Fenster
Abbildung 4.2: Hilfspaletten
VirtualSurface beschreibt also Methoden, um Koordinaten (wie sie beispielsweise von
der Maus generiert werden) von der Bildschirm-Ebene in die virtuelle Ebene und umgekehrt zu transformieren. Die Objekte Point2D und Rectangle2D sind Teil des Hauptpakets
von Java2D, java.awt.geom. Darin sind vor allem das Interface Shape und die Klasse
AffineTransform interessant: Shape beschreibt eine beliebige zweidimensionale geometrische Form, die in eine Folge von einfachen Segmenten (den PathIterator) zerlegt werden
kann. Shape Objekte können darauf getestet werden, ob sie bestimmte Punkte enthalten
oder andere Shape Objekte überschneiden. Einige Klassen, die Shape implementieren, bieten
Menge-Operatoren wie UND- oder Exklusive-ODER Verknüpfung.
Mit einer AffineTransform lassen sich geometrische Skalierungen, Scherungen und Rotationen beschreiben. Diese können auf Point2D und Shape Objekte angewandt werden. Die
graphische Realisation findet in einem Graphics2D Kontext statt. Die Methode fill zeichnet dabei mit beliebiger Farbe, Verlauf oder Muster die Flächeninhalte von Shapes. Die
Methode draw zeichnet mit beliebiger Strichstärke und Form die Umrißlinie von Shapes.
Das Graphics2D Objekt bietet die Möglichkeit, sogenannte RenderingHints zu setzen und
damit die Qualität der Graphik, zum Beispiel bei Skalierungen oder der Verwendung von
Anti-Aliasing Techniken, zu kontrollieren.
Trotz der hohen Performance von Java2D muß in der Echtzeit-Umgebung versucht werden,
aufwendige Graphikoperationen wie Skalierungen und semitransparentes Zeichnen zu minimieren. Dazu werden die statischen Elemente in ein Offscreen-Image gerendert, das dann
relativ schnell wiederholt gezeichnet werden kann. Die Darstellung der Receiver-Sensitivität
36
4 Graphische Benutzeroberfläche
selbst ist eine grob aufgelöste Bitmap-Graphik (8-Bit Graustufen), deren Berechnung relativ
langsam ist.
4.1.1 Hilfs-Paletten und Werkzeuge
In der Abbildung 4.2 sind zwei Hilfs-Paletten zu sehen, die weitere Funktionalität für die
Surface und andere Objekte bereitstellen. Die ObserverPalette stellt kontextsensitive TextInformationen dar. Sie enthält verschiedene Karten, die in Abhängigkeit von der BenutzerAktion umgeschaltet werden. Wählt der Benutzer beispielsweise einen Receiver aus, wird
die Rcv“-Karte angezeigt. Sie enthält die exakten Koordinaten des Anker-Punktes (Mittel”
punktes) des Receivers, seine Ausdehnung und seinen Namen. Diese Angaben können durch
Texteingabe geändert werden. Durch Anwählen einer Gruppe von Receivern können diese
gleichzeitig verändert und ausgerichtet werden. Die weiteren Karten des Observers betreffen
die ausgewählten Transmitter und die Timeline. Die Csr“-Karte stellt die aktuellen Maus”
koordinaten (im virtuellen Bezugssystem) dar.
Die ToolPalette stellt die grundlegenden Editierungsfunktionen für die Surface bereit. Von
links nach rechts zu sehen sind
•
Auswahl-Werkzeug : Es dient der Auswahl und dem Bewegen von Receivern
•
Linien-Werkzeug : Zum Generieren linearer Trajektorien-Verläufe
•
Kurven-Werkzeug : Generiert Trajektorien-Verläufe anhand von kubischen Kurven
•
Kreissegment-Werkzeug : Generiert Trajektorien, die entlang einer Kreisbahn verlaufen
•
Freihand-Werkzeug : Dient der Echtzeit-Aufzeichnung von Mausbewegungen
•
Blending-Option : Versieht die Editierungen mit einer Überblendung (Crossfade)
Linien, Kurven und Kreissegmente sind Offline-Werkzeuge, sie arbeiten unabhängig vom
Transport. Der Benutzer bestimmt einen Zeitausschnitt, über den sich der TrajektorienAbschnitt erstrecken soll. Er zieht die werkzeugspezifische Grundform, die durch zwei Stützpunkte definiert ist. Anschließend kann er durch Anfassen und Ziehen der Kontrollpunkte
die Form anpassen. Mit Tastaturbefehlen (Escape und Return) wird die Geste abgebrochen
oder ausgeführt (gerendert). Über eine spezielle Tastenkombination kann eine Serie von zusammenhängenden Segmenten gezeichnet werden.
Da diese drei Werkzeuge analytische (durch eine Funktion beschriebene) Formen darstellen,
können sie an beliebigen Punkten ausgewertet werden. Aufgrund dieser Überlegung wurde
ein Velocity-Modus integriert, der dem Benutzer erlaubt, die Start- und Endgeschwindigkeit
der Bewegung zu beeinflussen. Um zu verdeutlichen, was damit gemeint ist, sehen wir uns
die dafür vorgesehenen Methoden in der Super-Klasse AbstractGeomTool an:
37
4 Graphische Benutzeroberfläche
Quelltext 4.2: AbstractGeomTool.java (gui package)
public abstract class AbstractGeomTool
extends AbstractTool
implements KeyListener
{
[...]
protected boolean canAccelerate()
{
return true;
}
protected boolean initFunctionEvaluation( Point2D[] ctrlPoints )
{
return false;
}
protected void evaluateFunction( float[] warpedTime, float[][] interpBuf,
int len ) {}
[...]
}
Die Fähigkeit, die Funktion an variablen Zeitpunkten auszuwerten, wird durch die Methode canAccelerate erfragt. Die Methode initFunctionEvaluation dient der Initialisierung von Parametern, die nur einmal berechnet werden müssen. Der eigentlichen Methode
evaluateFunction wird ein Array von Zeit-Werten übergeben, die monoton steigend aber
nicht linear verteilt sein müssen. Die Bezeichnung warpedTime besagt, daß die EingangsZeitwerte ungleichmäßig angeordnet sind, die ihnen zugeordneten (in der Methode berechneten) Funktionswerte jedoch als mit konstanter Sampling-Rate abgetasteter TrajektorienAbschnitt aufgefaßt werden.
Mit anderen Worten, wenn eine Strecke mit dem Linien-Werkzeug gezeichnet und die Funktion so ausgewertet wird, daß die Eingangs-Zeitwerte zu Beginn dichter beieinander liegen als
zum Schluß, so ergibt sich eine lineare Bewegung des Transmitters, deren Geschwindigkeit
zunimmt.3 Durch Doppelklick auf die Surface wird dem Benutzer eine einfache Möglichkeit
gegeben, die Start- und Endgeschwindigkeit der geometrischen Form anzupassen. Der Verlauf
der Geschwindigkeit wird mit einer kubischen Funktion so berechnet, daß unabhängig von
den Einstellungen des Benutzers der gewählte Zeitabschnitt exakt ausgefüllt wird. Die Geschwindigkeit wird durch eine transparente gelbe Hüllkurve dargestellt, die der geometrischen
Grundform folgt (Graudarstellung in Abbildung 4.3).
In einer zukünftigen Version sollte die Möglichkeit, mehrere Linienzüge nacheinander zu zeichnen, so erweitert werden, daß auch der Geschwindigkeitsvektor im Schnittpunkt zwischen zwei
Segmenten stetig ist.
Die Funktion des Freihand-Tools wird im Abschnitt über den Transport dargestellt.
Um beim Einzeichnen von Trajektorien-Abschnitten zu vermeiden, daß ein Transmitter
sprunghaft den Ort wechselt, kann durch Aktivierung der Blending-Option ein automatischer Crossfade zwischen den vorherigen und den neuen Trajektorien-Daten erzeugt werden.
Dies ist auch hilfreich beim Filtern der Trajektorien mit Plug-Ins, die in vielen Fällen eine
Unstetigkeit an den Rändern des gefilterten Zeitausschnittes erzeugen. Ebenso kann mit einer
3
Die Geschwindigkeit ist proportional zu ∆twarped /T mit T = Sampleperiode der Trajektorien.
38
4 Graphische Benutzeroberfläche
Abbildung 4.3: Bézier-Kurve mit variabler Geschwindigkeit
langen Blending-Dauer der Output einfacher Filter ein- und ausgeblendet werden, so daß eine
dynamische Transformation stattfindet, obwohl die Filter selbst keine zeitvariablen Parameter
besitzen.
4.1.2 ReceiverEditor
Mit Doppelklick auf den Anker eines Receivers wird ein Editor geöffnet (Abbildung 4.4), mit
dem die Sensitivität des Receivers eingestellt werden kann. Grundsätzlich sind Receiver und
ReceiverEditor Interfaces in Meloncillo, so daß sich verschiedene Modelle für die Berechnung
der Sensitivität integrieren lassen. In der aktuellen Version ist lediglich eine Klasse von Receivern vorhanden, der SigmaReceiver, der in Analogie zu Σ 1 eine Kreuzung zweier Tabellen
vorsieht: Die Distance-Tabelle beschreibt die Empfindlichkeit des Receivers in Abhängigkeit
eines Abstandes vom Anker-Punkt. Die Rotation-Tabelle beschreibt die Abhängigkeit vom
Winkel, den ein Transmitter zum Anker-Punkt des Receivers einnimmt. Die Tabellen-Werte
sind momentan linear skaliert und werden daher multipliziert:
sense(r, φ) = distance table[r] · rotation table[φ]
Dadurch lassen sich alle Standard-Formen von Kugel bis Niere und Acht beschreiben. Da
die Tabellen hinreichend groß sind (jeweils 1024 Punkte4 ), lassen sich durch harte Kanten
oder Rauschen auch experimentelle nicht-stetige Empfindlichkeitsverläufe realisieren. Dazu
stehen per Popup-Menü verschiedene Signalgeneratoren und mathematische Operationen zur
Verfügung. Um Zipper-Noise bei langsamen Bewegungen und tieffrequenten harmonischen
Tönen zu vermeiden, werden die Tabellen-Werte linear interpoliert.
Im klassischen Amplituden-Panning werden die Sensitivitäten direkt auf Lautstärken gemappt. Durch Vergrößern der Receiverfläche und Editieren der Tabellen lassen sich praktisch
alle Panning-Verläufe umsetzen und Divergenzen simulieren. Wird ein anderes Verfahren
benutzt, beispielsweise VBAP, so sind für das reine Panning nur die Receiver-Koordinaten
von Bedeutung; die Sensitivität kann in diesem Fall ganz anders genutzt werden, etwa als
Parameter für die Ansteuerung eines Raumhalls, einer Filterung oder Verzerrung.5
4
5
Dies wird in einer zukünftigen Version vom Benutzer konfigurierbar sein.
In einer zukünftigen Version wird es eine weitere Receiver-Klasse geben, die gar keine Sensitivitäts-Daten
generiert und somit effektiv ist, wenn darauf ohnehin verzichtet wird, wie z.B. in einer HRTF Synthese.
39
4 Graphische Benutzeroberfläche
Abbildung 4.4: Editor für SigmaReceiver
Abbildung 4.5: Matrix Meter
4.1.3 Matrix Meter
Der Observer zeigt während der Tabellen-Editierung die exakte Sensitivität eines Receivers
an. Um zu kontrollieren, wie der Übergang von einem Receiver zum nächsten verläuft, kann
das sogenannte Matrix Meter Fenster eingeblendet werden (Abbildung 4.5). Es zeigt jeweils
eine Zeile oder Spalte der aus Transmittern und Receivern gebildeten Matrix an. Durch Klick
auf einen Transmitter Namen werden die momentanen Empfindlichkeiten aller Receiver an der
Stelle dargestellt, an der sich dieser Transmitter befindet. Umgekehrt werden durch Klick auf
einen Receiver Namen die Sensitivitäten dieses Receivers zu allen momentanen TransmitterPositionen dargestellt. In einer zukünftigen Version wird das Meter optional logarithmisch
dargestellt6 , außerdem sollen die exakten Werte im Observer ausgegeben werden.
4.2 Timeline : horizontale Zeitdarstellung
Für einen simultanen Überblick über den Verlauf der Trajektorien und die Gesamtform der
Komposition sorgt das TimelineFrame (Abbildung 4.6). Ähnlich dem Arrangier-Fenster eines
Harddisk-Recording-Programms ist hier die Zeitachse horizontal aufgetragen, während die
verschiedenen Spuren, die die Trajektorien der Transmitter zeigen, vertikal angeordnet sind.
Jede Spur besteht aus zwei eindimensionalen Vektoren, die die kartesischen Koordinaten
(x, y) der Trajektorien zeigen. Möglicherweise zeigt eine zukünftige Version optional eine
Polar-Koordinaten-Sicht. Die kartesische Darstellung hat jedoch den Vorteil, daß sie der internen Datendarstellung entspricht und somit schnell gezeichnet werden kann, davon abgesehen
müßten Winkel mit der Periode 2π umgebrochen werden.
6
Die jetzige Darstellung ist linear.
40
4 Graphische Benutzeroberfläche
Abbildung 4.6: Timeline Fenster
Abbildung 4.7: Transport
Palette
Die Darstellung der Koordinaten-Vektoren erfolgt mit einem VectorEditor, dadurch ist das
direkte Einzeichnen mit der Maus möglich. Komfortabler ist jedoch die Editierung auf der
Surface oder mittels Filterung, wie sie im Plug-In Kapitel beschrieben wird. Die Editierung,
die typischerweise im Timeline Fenster gemacht wird, ist das Ausschneiden, Kopieren und
Einfügen von Trajektorien-Abschnitten. Am oberen Rand des Fensters ist eine Zeitachse zu
erkennen. Durch Klicken mit der Maus kann die gegenwärtige Zeitposition, die durch die
vertikale rote Linie symbolisiert wird, verschoben werden. Durch Halten der Umschalttaste
kann eine Region selektiert werden, die durch dunklere Schattierung hervorgehoben wird.
Durch Klick auf die Namen der Transmitter-Spuren können diese Transmitter selektiert und
deselektiert werden. Die Cut- und Copy-Befehle wirken auf die Trajektorien-Ausschnitte, die
durch die selektierten Transmitter und den selektierten Zeitausschnitt bestimmt sind. Die
Paste-Operation fügt den Clipboard-Inhalt in die Trajektorien der gewählten Transmitter
ein, an der Stelle, an der sich die Zeitposition befindet.
4.2.1 Trajektorien Daten-Format
Die Darstellung des Timeline Fensters kann horizontal und vertikal vergrößert und verkleinert werden. Durch die Diskretisierung der Trajektorien kann der Fall auftreten, daß durch
Herauszoomen ein Ausschnitt dargestellt wird, dem mehrere Tausend bis Hunderttausende
von Frames entsprechen. Eine solch große Zahl von Frames einzulesen ist sowohl zu zeit- als
auch zu speicherintensiv. Die Lösung besteht in einer Unterabtastung der Trajektorien. Dies
geschieht in mehreren Schritten, um stets eine optimale Auflösung zur Verfügung zu haben.
Jede Dezimations-Stufe verringert die Frame-Rate um den Faktor vier. Da VectorEditor die
Daten als Vektorgraphik darstellt, wird der Umschaltpunkt so gelegt, daß maximal doppelt
soviele und minimal halb soviele Punkte wie die aktuelle Fensterbreite gezeichnet werden.
Insgesamt werden sechs dezimierte Tracks pro Trajektorie berechnet. Angenommen den extrem unwahrscheinlichen Fall, daß die Framerate in der Größenordnung von Audioraten liegt,
zum Beispiel 48 kHz, so besitzt der am stärksten dezimierte Track (Faktor 1/4096) eine Rate
41
4 Graphische Benutzeroberfläche
1/1
:4
1/4
:4
1/16
Abbildung 4.8: Dezimation von Trajektorien
von ca. 12 Hz. Wenn innerhalb einer Fensterbreite eine halbe Stunde dargestellt werden sollte,
wäre damit eine Puffergröße von 21094 Frames verbunden. In dem wahrscheinlicheren Fall
einer Framerate von 4800 Hz oder weniger könnte eine volle Stunde mit gerade 4219 dezimierten Frames dargestellt werden, was einen geringen RAM-Verbrauch und geringe CPU
Belastung bedeutet.
Die gespeicherte Session enthält die Trajektorien in Form von Floating-Point Dateien in einem
separaten Unterordner trns. Die dezimierten Dateien werden momentan nicht gespeichert,
sondern beim Laden einer Session adhoc erstellt, was akzeptabel schnell verläuft. Die im temporären Verzeichnis gespeicherten dezimierten Trajektorien benötigen ca. 1/3 der Größe der
Originaldatei. Die Editierung der Trajektorien geschieht nicht-destruktiv, das heißt, die Originaldatei wird bis zum Abspeichern der Session nicht verändert. Die Verwaltung dieser nichtlinearen und nicht-destruktiven Editierung übernimmt die Klasse MultirateTrackEditor
(MTE), die im wesentlichen sieben SubsampleTrackEditoren verwaltet. Diese repräsentieren
die Trajektorien-Daten in voller respektive dezimierter Rate. Um auch bei stärkerer Dezimation eine möglichst gute Annäherung an die Signaleigenschaften zu erhalten, wird in jeder
Stufe aus den jeweils vier Ausgangsframes jedes dezimierten Frames der Median berechnet.
Abbildung 4.8 zeigt zwei Stufen des Dezimations-Prozesses.
Der MTE verwaltet eine sogenannte TrackList, eine chronologische Liste aus TrackSpan
Objekten, die wie folgt aussehen:
Quelltext 4.3: TrackSpan.java (io package)
public class TrackSpan
{
public Span span;
public final InterleavedFloatFile f;
public long offset;
[...]
}
Span ist eine Klasse, die sehr häufig in Meloncillo benutzt wird. Sie beschreibt eine Zeitspanne
durch Angabe eines Start- und Endframes. Die Spannen der Track-Liste fügen sich nahtlos
aneinander. Wird eine Session geöffnet, so besteht die Liste lediglich aus einem TrackSpan, der
die gesamte Dauer der Session umfaßt. Wird jetzt ein Teil der Trajektorie herausgeschnitten,
so wird diese TrackSpan durch zwei neue ersetzt, die die Spannen vor und nach dem Schnitt
beschreiben. Die Datei vom Typ InterleavedFloatFile, die die Trajektorien-Daten enthält,
42
4 Graphische Benutzeroberfläche
bleibt unverändert. Das Feld offset wird jedoch stets so angepaßt, daß es auf den richtigen
Punkt innerhalb dieser Datei zeigt. Wird jetzt eine Trajektorie zum Beispiel mit dem LinienWerkzeug überzeichnet, so wird der neue Abschnitt in einer temporären Datei gerendert
und in Form einer neuen TrackSpan in die Track-Liste eingefügt. Gegebenenfalls wird am
Insert-Punkt die alte TrackSpan in zwei separate Objekte aufgeteilt.
Der MTE sorgt dafür, daß nach jeder Editierung der Trajektorien die Dezimations-Files
auf den aktuellen Stand gebracht werden. Die SubsampleTrackEditoren enthalten ebenfalls
eine Liste von TrackSpans, deren Spannen jedoch durch die spezialisierte BiasedSpan Klasse
beschrieben werden. BiasedSpan sorgt dafür, daß die Rundungsfehler, die durch die Unterabtastung hinsichtlich der Start- und Stopframes entstehen, stets minimiert werden.
4.2.2 Transport Palette
Abbildung 4.7 zeigt ein Fenster mit einfachen Transport-Funktionen. Der Transport ist eng
mit der Realtime-Engine des Programms verknüpft. Er enthält einen eigenen Event-Dispatcher, der registrierte Listener über Start- und Stop-Vorgänge informiert. Die Palette enthält
einen Play- und Stop-Button und einen Loop-Umschalter. Das ballförmige Symbol ganz rechts
aktiviert das Realtime-Plug-In, das im nächsten Kapitel beschrieben wird.
Der Transport dient neben dem Realtime-Preview auch dem Aufzeichnen von TransmitterBewegungen in Echtzeit. Während der Transport läuft, kann mit dem Freihand Werkzeug
auf der Surface entlanggefahren werden. Die Bewegung wird zwischen den Stützpunkten
linear interpoliert. Die Editierung wird gerendert, wenn der Mausknopf losgelassen wird. Das
impliziert, daß die Bewegung im Moment des Zeichnens noch nicht über das Preview-Plug-In
zu hören ist. Eine Lösung dafür wird in der nächsten Programm-Version angestrebt.
43
5 Plug-In Schnittstellen
An drei Punkten wird im Programm auf ein Plug-In Konzept zurückgegriffen:
•
Filterung von Trajektorien
•
Bouncen (Rendern) der Klang-Synthese auf Harddisk
•
Realtime Vorschau der Klang-Synthese
Die Verwaltung dieser Plug-In Typen übernehmen drei Objekte, die das PlugInHost Interface
implementieren: Es sind FilterDialog, BounceDialog und RealtimeFrame. Das Diagramm
5.1 zeigt die Hierarchie der am Plug-In Konzept beteiligten Klassen und Interfaces.
5.1 Offline (Nicht-Echtzeit)
Die nicht-echtzeit-basierten Filter- und Bounce-Plug-Ins implementieren das Interface RenderPlugIn:
Quelltext 5.1: RenderPlugIn.java (render package)
public interface RenderPlugIn
extends PlugIn
{
public boolean producerBegin( RenderContext context, RenderSource source )
throws IOException;
public boolean producerRender( RenderContext context, RenderSource source )
throws IOException;
public boolean producerFinish( RenderContext context, RenderSource source )
throws IOException;
public void producerCancel( RenderContext context, RenderSource source )
throws IOException;
}
Es übernimmt als Subinterface von PlugIn eine Methode zur Generierung einer Plug-InOberfläche (getSettingsView()), die vom RenderHost innerhalb eines Fensters dargestellt
wird. Der Host reagiert auf die Aktionen des Benutzers. Wenn dieser den Render-Vorgang
startet, ruft er nacheinander nach dem Push-Verfahren die Methoden producerBegin, producerRender und producerFinish des Plug-Ins auf, wobei producerRender gegebenenfalls
mehrfach mit Teilblöcken der zu rendernden Zeit aufgerufen wird.
44
5 Plug-In Schnittstellen
PlugIn
PlugInHost
RealtimePlugIn
RenderPlugIn
RealtimeConsumer
RealtimeHost
Transport
RenderHost
BasicRenderDialog
BounceDialog
LispRealtimePlugIn
LispRenderPlugIn
LispBounce
TimeWarpFilter
RenderConsumer
FilterDialog
VectorTransformFilter
LispFilter
Abbildung 5.1: Plug-In Interfaces und Klassen
Im Falle des Trajektorien-Filters müssen die gefilterten Daten wieder zurück zur Applikation
fließen. Dazu übergibt der Host dem Plug-In ein Objekt, das das Interface RenderConsumer
implementiert. Es ist ganz ähnlich dem RenderPlugIn aufgebaut:
Quelltext 5.2: RenderConsumer.java (render package)
public interface RenderConsumer
{
public boolean consumerBegin( RenderContext context, RenderSource source )
throws IOException;
public boolean consumerRender( RenderContext context, RenderSource source )
throws IOException;
public boolean consumerFinish( RenderContext context, RenderSource source )
throws IOException;
public void consumerCancel( RenderContext context, RenderSource source )
throws IOException;
}
Das Plug-In fungiert dann als eigener Host, der den Consumer mit Datenblocks füttert. Der
FilterDialog ist bidirektional aufgebaut – das heißt, er empfängt die gefilterten Trajektorien
und fügt sie wieder in die Session ein –, implementiert daher sowohl RenderHost als auch
RenderConsumer. Grundsätzlich werden zwei Typen von Daten unterschieden, die während
der Plug-In Bearbeitung Informationen liefern: statische Daten, die in einem PlugInContext
Objekt zusammengefaßt sind – beispielsweise die gesamte zu bearbeitende Zeitspanne, die
beteiligten Transmitter und Receiver. Und dynamische Datenströme, die blockweise generiert
werden und in Form des RenderSource Objekts zur Verfügung stehen.
Wenn das Plug-In durch Aufruf von producerBegin initialisiert wird, kann es sogenannte
Request-Felder im RenderSource ausfüllen und gibt damit bekannt, welche Datenströme
45
5 Plug-In Schnittstellen
Abbildung 5.2: Plug-Ins zur Trajektorien-Filterung
erzeugt werden müssen. Ein Plug-In kann zum Beispiel nur an den Trajektorien-Daten (wie
im Falle der Filter-Klassen) oder nur an den Sensitivitäten der beteiligten Receiver interessiert
sein.
Für die Filterung von Trajektorien stehen momentan drei Plug-Ins bereit, deren SettingsViews in Abbildung 5.2 zu sehen sind.
•
Der TimeWarpFilter ordnet anhand einer Tabelle die Eingangszeitwerte (Ordinate) den
Ausgangszeitwerten (Abszisse) zu, d.h. traj 0 (t) ← traj(f (t)). Eine absteigende Gerade
bewirkt, daß die ursprünglichen Bewegungen rückwärts wieder gegeben werden. Eine
Parabel würde ein Vorwärts- und Rückwärtslaufen simulieren, ein Sägezahn mit drei
Perioden würde die ausgewählte Trajektorie dreimal mit dreifacher Geschwindigkeit
wiederholen.
•
Der VectorTransformFilter bietet die Möglichkeit, x und y Werte (alternativ Radius
und Winkel zu einem Bezugspunkt) mit einer mathematischen Funktion zu bearbeiten. Unter anderem steht ein Funktionsgenerator zur Verfügung, mit dem sich einfache
geometrische Figuren wie Spiralen und Linien oder das Hinzufügen von Unregelmäßigkeiten (Rauschen) realisieren lassen.
•
Der LispFilter stellt ein frei programmierbares Plug-In dar, das über Common Lisp
Scripte gesteuert wird. Es wird in Abschnitt 5.3 erklärt.
5.2 Realtime (Echtzeit)
Aus Abbildung 5.1 geht hervor, daß momentan genau ein RealtimeHost und ein RealtimePlugIn existieren. Die implementierenden Klassen sind Transport und LispRealtimePlugIn. Transport ist der Motor des Echtzeit-Betriebs. Er ist ein spezieller Thread, der läuft,
wenn der Play-Knopf der Transport-Palette gedrückt wird. RealtimeConsumer können sich
bei ihm registrieren, so daß sie im Benachrichtigungs-Rhythmus mit neuen Informationen
46
5 Plug-In Schnittstellen
Klasse
Surface
MeterFrame
TimelineFrame
TransportPalette
Request
traj
sense
clock
clock
Rate
30 Hz
15 Hz
30 Hz
15 Hz
Aktivität
Nachführung der Transmitter Bewegungen
Monitoring der Sensitivitäten
Animation der Zeitachsen-Positions-Linie
Update des Zeitachsen-Positions-Textfeldes
Abbildung 5.3: RealtimeConsumer Profile
versorgt werden. Die Genauigkeit der Uhr-Information in Java liegt bei einer Millisekunde.
Die Methode Thread→sleep( long millis, int nanos ) kann benutzt werden, um den
Thread für eine bestimmte Zahl zu pausieren. Die suggerierte Genauigkeit im Bereich von
Nanosekunden ist jedoch überhaupt nicht gegeben. Selbst wenn eine Millisekunde lang gewartet wird, ist nicht garantiert, daß der Thread wirklich nach einer Millisekunde fortgesetzt
wird. Deshalb wird im Transport-Kern ein Mechanismus benutzt, der laufend die aktuelle
und die geforderte Rate vergleicht und entsprechend kürzer oder länger wartet. Der entstehende Jitter ist optisch irrelevant und tangiert die externe Klangsynthese nicht, die Daten
blockweise erhält und ihren eigenen Scheduler hat.
Im Gegensatz zur Trajektorien-Filterung und Bounce-to-Disk gibt es im Echtzeit-Betrieb
mehrere Consumer. Das bedarf einer Erläuterung: Im Klassen-Diagramm ist zu erkennen, daß
LispRealtimePlugIn sowohl RealtimePlugIn als auch RealtimeConsumer implementiert.
Worin besteht der Unterschied? Das Plug-In ist dafür zuständig, mit externen KlangsyntheseProgrammen zu kommunizieren. Das Interface beinhaltet Methoden zum Aktivieren und
Deaktivieren des Plug-Ins, das heißt, es kann auf Bypass geschaltet werden. Der eigentliche
Datenaustausch jedoch ist Teil des Consumer Interfaces. Neben dem Lisp Plug-In gibt es
weitere Consumer in Meloncillo, die in Abbildung 5.3 gelistet sind.
Je nach Anwendung sind also unterschiedliche Datenraten gefragt. Die tabellierten Klassen
sind alle Teil der graphischen Oberfläche und benötigen daher nur Raten, die einen optisch
fließenden Eindruck vermitteln. Die verschiedenen Requests werden dynamisch verwaltet von
einem Objekt, das eng mit Transport zusammenarbeitet, dem RealtimeProducer:
Quelltext 5.3: RealtimeProducer.java (realtime package)
public class RealtimeProducer
implements LaterInvocationManager.Listener
{
[...]
public RealtimeProducer.Source source;
[...]
public void changeContext( RealtimeContext c ) { [...] }
public void requestProduction( Span blockSpan, boolean even,
long deadline ) { [...] }
public void produceNow( Span blockSpan, boolean even ) { [...] }
public void produceOffhand( long currentPos ) { [...] }
[...]
}
Der RealtimeProducer produziert blockweise die geforderten Daten innerhalb des Event
Threads. Eine neue Anfrage wird vom Transport durch Aufruf der requestProduction Methode gestellt. Der RealtimeProducer soll darin die Daten, die zur Zeitspanne blockSpan
gehören, produzieren. Um Dropouts zu vermeiden, darf er dafür maximal deadline Milli-
47
5 Plug-In Schnittstellen
0
16
32
48
64
80
traj : 1/1
sense : 1/2
96
112
128
plugin sense read : 1/2
plugin notification : 1/8
surface traj read / timeline frame notif. : 1/16
transport palette notif. : 1/32
Abbildung 5.4: Realtime Datenströme
sekunden benötigen. Mit anderen Worten, der RealtimeProducer wird bereits im voraus
beauftragt, einen neuen Block Daten zu generieren. Diese Daten sind in Arrays des source
Objekts gespeichert. Die Consumer streichen im Clock-Rhythmus zirkulär durch diese Puffer.
Jedesmal, wenn die aktuelle Zeit den Puffer-Anfang oder die Puffer-Mitte überschreitet, wird
die jeweils obsolete Puffer-Hälfte, spezifiziert durch den even Parameter, aktualisiert.
Wenn der Transport gestartet wird, muß ein voller Block vorproduziert werden, dazu dient die
Methode produceNow. Da die Oberfläche auch auf manuelles Ziehen der Zeitachsen-PositionsLinie durch den Benutzer reagieren soll, ohne daß der Transport läuft, wurde die Methode
produceOffhand eingeführt, die nur ein einzelnes Zeitframe produziert. Wenn der Benutzer die Session verändert, zum Beispiel Receiver löscht oder hinzufügt, müssen die Puffer
neu angelegt werden. Dazu werden die Consumer kurzzeitig angehalten, der Kontext mittels
changeContext aktualisiert, und ein neues Profil von allen Consumern angefordert.
Wie findet die Koordination zwischen mehreren gewünschten Datenraten statt? Nehmen wir
dazu an, daß neben den in Tabelle 5.3 aufgeführten Consumern ein Lisp-Echtzeit-Plug-In
läuft. Die Session habe eine Trajektorien-Datenrate von 500 Hz1 . Nehmen wir an, das PlugIn steuert den SuperCollider-Synthesizer, dessen Controlrate ca. 690 Hz beträgt. Das Plug-In
fordere aus Gründen der CPU Belastung Sensitivitäten mit maximal 345 Hz an. Nehmen wir
weiter an, ein voller Datenpuffer entspräche etwa 1/4 Sekunde, nämlich 128 Frames. Dann
ergibt sich ein Datenstrom-Produktions- und Konsumptions-Schema nach Abbildung 5.4.
Der RealtimeProducer produziert prinzipiell Trajektorien-Daten (traj ) mit voller Datenrate
– also durchgängig alle 128 Frames eines Blocks –, da sie direkt von der Harddisk gelesen werden und eine Unterabtastung eher Rechenzeit vergeuden als sparen würde. Sensitivitäts-Daten
(sense)werden nur produziert, wenn sie nachgefragt werden. Der einzige Request kommt vom
Realtime Plug-In (345 Hz). Grundsätzlich müssen die Faktoren der Unterabtastungen einer
Zweierpotenz entsprechen, somit ergeben sich hier 250 Hz beziehungsweise eine Schrittweite von zwei Frames. Alle ungeraden Frame-Indices des Puffers werden ignoriert und haben
keinen gültigen Inhalt.
Der Transport sorgt dafür, daß die Consumer mit der von ihnen angegebenen Rate benachrichtigt werden2 . Auch hier gilt die Zweierpotenz-Regel, so daß sich die leicht veränderten
Frequenzen von 31.25 Hz bzw. 15.625 Hz ergeben. Im Falle von blockverarbeitenden Con-
1
2
Die Voreinstellung beträgt 1 kHz.
Notification, in der Abbildung mit notif.“ abgekürzt.
”
48
5 Plug-In Schnittstellen
sumern wie dem Plug-In ist die Benachrichtigungs-Rate in der Regel niedriger als die Rate
der angeforderten Daten-Ströme. Im gezeigten Beispiel beträgt sie 1/8 der vollen Rate. Die
Erklärung dafür wird im Abschnitt 5.4.3 in Zusammenhang mit der SuperCollider Anbindung
geliefert.
5.3 Common Lisp für Java
Die Lisp-Plug-Ins sind weniger dafür gedacht, direkte Manipulationen zum Beispiel der Trajektorien zu vollbringen, vielmehr sollen sie ein elastisches Bindeglied zu externen Klangsynthese Programmen sein. Aus diesem Grund wurde in einer frühen Version des Programms
ein XML-Script zur Steuerung der externen Programme benutzt. XML erweist sich jedoch als
unpraktisch, wenn programmiersprachliche Konstrukte wie Schleifen (do-while) oder Bedingungen (if-then-else) benötigt werden. Diese hätten alle zu Fuß“ in den XML Interpreter
”
eingebaut werden müssen. Stattdessen wurde eine einfach strukturierte, kompakte, in Java
integrierbare Interpreter-Sprache gesucht.
Die Wahl fiel auf Common Lisp: Die Syntax ist sehr überschaubar3 , mehrere algorithmische
Musiksprachen basieren auf Lisp4 , und es gibt mit Jatha eine einfache freie Implementation
in Java. Micheal Hewett entwickelte Jatha über die letzten zehn Jahre, und es erweist sich
als zuverlässig im Betrieb. Ein paar der Vorteile von Jatha:
•
maximale rechtliche Freiheit durch GLPL Lizenz
•
kompakte Bibliothek (232 KB)
•
plattformunabhängig
•
Ausnutzung des automatischen Garbage-Collectors von Java
•
sehr einfache Konvertierung zwischen primitiven Lisp und Java Datentypen
•
neue Funktionen lassen sich durch einfache Java Klassen bereitstellen
•
neue Symbole können von Java aus in das Environment eingefügt werden
•
kann als reines API ohne eigene Console oder GUI verwendet werden
Die wesentlichen Nachteile sind die eher langsame Geschwindigkeit – trotz gegenteiliger Behauptungen des Autors – und der geringe Funktionsumfang. In der Selbstbeschreibung heißt
es sehr zurückhaltend, Jatha implementiere a large part of the core of Common Lisp“ 5 . Das
”
bedeutet unter anderem, daß praktisch keine weitergehenden APIs eingebaut sind. Zum Beispiel gibt es keine Funktionen zum Lesen und Schreiben von Files. Auch Standard-Konzepte
wie Streams, Arrays und Macros fehlen komplett. Im Rahmen der Anforderung als einfaches
Scripting-Bindeglied wurden diese Nachteile in Kauf genommen.
3
zur Sprache Common Lisp vgl. [Mayer 1995]
z.B. OpenMusic und Common Music, RSC als SuperCollider Client in Scheme, sowie die Klangsynthese
Sprache Common Lisp Music.
5
http://jatha.sourceforge.net/doc/short-description.html
4
49
5 Plug-In Schnittstellen
5.3.1 Die LispPlugIn Klasse
Oberklasse für alle Lisp basierten Plug-Ins ist die Klasse LispPlugIn.
•
Sie stellt eine standardisierte Oberfläche bereit, die eine Auswahl-Box für die konkreten
Lisp Scripte (Sourcecodes) enthält und die Möglichkeit bietet, GUI Elemente darzustellen, die direkt von den Scripten erzeugt werden (vgl. Abb. 5.2 rechts).
•
Sie verwaltet die Jatha Umgebung und stellt zusätzliche Funktionen und Symbole zur
Verfügung.
•
Sie stellt die Methode executeLisp zur Verfügung, mit der zur Renderzeit beliebige
im Script definierte Funktionen ausgeführt werden können.
Die Namen dieser Funktionen hängen vom Plug-In Typ ab. Für die Filterung von Trajektorien werden in Analogie zum RenderPlugIn Interface (Quellcode 5.1) die benutzerdefinierten Lisp Funktionen prepare, render und cleanup ausgeführt. prepare ermöglicht dem
Script, grundlegende Initialisierungen durchzuführen und Requests anzumelden. render wird
im Gegensatz zu RenderPlugIn→producerRender() nur einmal ausgeführt. Dies geschieht,
nachdem die angeforderten Datenströme in Form von temporären Dateien bereitgestellt
wurden, so daß hier üblicherweise der Aufruf des externen Klangsynthese-Programms, z.B.
CSound, erfolgen kann. Aufräumarbeiten wie das Schließen oder Löschen von Dateien werden
in der cleanup Funktion erledigt.
Die zusätzlich von Meloncillo bereitgestellten Lisp Funktionen beinhalten unter anderem:
•
Öffnen von Audio-Dateien (AIFF, IRCAM oder AU Format)
•
Allokation und Beschreiben von Byte-Puffern (als Ersatz für den fehlenden VectorDatentyp)
•
Öffnen und Beschreiben von Dateien
•
Erweiterte String-Operationen wie Formatierung von Zahlen und Pattern Matching mit
Regulären Ausdrücken
•
Versenden von UDP Datagrammen (vgl. Abschnitt 5.4.2)
•
Generierung von OSC Paketen (vgl. Abschnitt 5.4.2)
•
Festlegung von Quelldaten und Zieldaten Requests (d.h. welche Trajektorien- und Sensitivitätsdaten benötigt und zurückgeliefert werden)
•
Ausführen von externen Programmen
•
Erzeugen von GUI Elementen
Die GUI Elemente dienen dazu, dem Benutzer die wichtigsten Script Parameter in Form
von Checkboxes und Textfeldern zu präsentieren, ohne daß dieser für jede Session separate
Script-Dateien editieren muß. GUI Elemente werden in der speziellen Funktion create-gui
definiert.
Das Script erhält außerdem ein Dictionary6 , das die wichtigsten statischen Parameter enthält.
Hier kann das Script nachschlagen, wieviele Transmitter und Receiver beim Rendern beteiligt
sind, was ihre Namen sind usw., wie hoch die Datenrate ist und welche Werte die Plug-In
6
in Form des speziellen Lisp-Datentyps LispHashTable
50
5 Plug-In Schnittstellen
relevanten Preferences-Settings haben, etwa die voreingestellte Audio-Rate und der voreingestellte Pfad zur CSound Applikation.
5.3.2 Ein Beispielscript
Während die Besonderheiten für Echtzeit-Scripte im folgenden Abschnitt erläutert werden,
wird hier das Beispiel einer Trajektorien Filterung mit CSound durchgegangen. Nehmen wir
an, CSound soll die Trajektorien tiefpaßfiltern, so daß die Transmitter-Bewegungen weniger
hektisch und dafür flüssiger werden.7 Das Lisp Script ist in der Datei "csfl-smooth.lisp"
gespeichert. Wenn es im Filter Dialog ausgewählt wird (Abb. 5.2 rechts), wird der Quelltext geladen und übersetzt. Anschließend wird die Funktion create-gui ausgeführt, die ein
numerisches Eingabefeld für die Filter-Frequenz erzeugt:
(defun create−gui NIL
(progn
(gadget−make NIL "LABEL" ’(1 1) "Cutoff Frequency" NIL)
(gadget−make filter−freq "NUMBER" ’(2 1) 1.0 (list "Hz" 0.0 1000.0 0.01))
T
; success
)
)
Der erste gadget-make Befehl erzeugt die Beschriftung. Die Argumente für gadget-make
sind (1) ein Lisp-Symbol, das stets den aktuellen Wert des GUI-Elements – in diesem Fall die
Frequenz – enthält, (2) der Gadget-Typ, (3) die Position des Gadget auf der Oberfläche, (4)
der voreingestellte Wert, (5) spezifische Optionen – hier die physikalische Einheit der Werte
und die erlaubten Minimum- und Maximum-Werte. Die Funktion liefert T (wahr) zurück um
zu signalisieren, daß keine Fehler aufgetreten sind.
Durch Klick auf den Process-Knopf wird die Filterung gestartet. Ein RenderContext der
gerade ausgewählten Transmitter und des Zeitausschnitts wird erstellt. Die Lisp-Funktion
prepare wird ausgeführt:
(defun prepare NIL
(progn
(setq colltrns (gethash "TRANSMITTERS" cillo))
(setq numtrns (length colltrns))
(setq prefs (gethash "PREFERENCES" cillo))
(setq timeline (gethash "TIMELINE" cillo))
(setq duration (− (gethash "STOP" timeline) (gethash "START" timeline)))
(setq sense−rate (gethash "SENSERATE" prefs))
(setq trnsidx 0)
(trnsiter ’(progn
(let ((trns (elt colltrns trnsidx))
(bufidx trnsidx)
(temp−input−file (temp−file−make))
(temp−output−file (temp−file−make)))
(audio−file−open bufidx temp−input−file
"raw" "float32" sense−rate 2)
(source−request "TRAJ" trnsidx bufidx)
(target−request "TRAJ" trnsidx temp−output−file)
7
Der Einfachheit halber wird die Ausführung weiter im Indikativ geschrieben.
51
5 Plug-In Schnittstellen
(setf−gethash "INPUT−FILE" trns temp−input−file)
(setf−gethash "OUTPUT−FILE" trns temp−output−file)
)
))
T
; success
)
)
Mit der Funktion gethash werden der RenderContext und die Programm-Preferences ausgelesen. Die Hashtable cillo wird als globales Symbol von LispPlugIn erzeugt. Die Liste
der Transmitter colltrns, die Zahl der Transmitter numtrns, die Länge des Zeitausschnitts
duration und die Datenrate sense-rate werden ermittelt. In einer Schleife8 wird für jeden Transmitter eine Eingabe- und Ausgabe-Datei im temporären Verzeichnis erzeugt. Mit
audio-file-open wird das Eingabeformat festgelegt, hier eine raw“ 9 Datei für 32bit Floa”
ting-Point Samples und zwei Kanäle. Diese Datei wird über den Identifier bufidx als Ziel
für die Quelldaten bestimmt (source-request). Dem Lisp-Plug-In wird mitgeteilt, daß die
Zieldaten in einer Datei temp-output-file zu erwarten sind. Für die spätere Verwendung
in der render Funktion werden die Dateinamen in der Hashtable gespeichert, die für jeden
Transmitter existiert.
Nachdem die Funktion zurückkehrt, arbeitet das Lisp-Plug-In die Requests ab und schreibt
die angeforderten Trajektorien-Daten in die temporären Dateien. Anschließend ruft es die
Script Funktion render auf:
(defun render NIL
(progn
(setq trnsidx 0)
(setq return−code 0)
(trnsiter ’(progn
(let ((trns (elt colltrns trnsidx))
(bufidx trnsidx)
(csd−file (temp−file−make ".csd")))
(file−close bufidx) ; close traj data files
; −−−− create CSound unified Orc/Sco file −−−−
(file−open 1977 csd−file "w")
(file−write 1977 (concat
"<CSoundSynthesizer>\\n<CsInstruments>\\n"
"nchnls = 2\\n"
"#include \"smooth.orc\"\\n"
"</CsInstruments>\\n<CsScore>\\n"
"i88 0 " duration "\\n"
"i14 0 " duration " \"" (gethash "INPUT−FILE" trns) "\" "
filter−freq "\\n"
"</CsScore>\\n</CSoundSynthesizer>\\n"
))
(file−close 1977)
; −−−− launch csound −−−−
(let ((exec−args
(list (gethash "CSOUNDAPP" prefs) "−A" "−3" "−o"
(gethash "OUTPUT−FILE" trns)
"−r" sense−rate "−k" sense−rate csd−file)))
8
Mangels einer Iterations-Funktion in Jatha wurde dafür eine hier nicht abgedruckte rekursive Funktion
trnsiter definiert, die die Variable trnsidx von 0 bis numtrns - 1 hochzählt.
9
D.h. ohne Header – headerless – nur aus den Audio-Frames bestehend
52
5 Plug-In Schnittstellen
(println (concat "\\n∗∗∗∗∗ Transmitter \""
(gethash "NAME" trns) "\" executing:\\n"
(concat−args exec−args)))
(setq return−code (execute parse−cs−output exec−args NIL
(car (path−split csd−file))))
(println (concat "Exited with return code " return−code))
(if (not (eql return−code 0)) (setq trnsidx numtrns) NIL)
)
)
))
(eql return−code 0)
; success if return code is 0
)
)
Da CSound sich etwas schwierig tut, mehrkanalige Dateien zu schreiben, ruft das Script
CSound jeweils getrennt für die einzelnen Transmitter auf; in jedem Durchgang der Iteration
wird eine Text-Datei geöffnet (file-open), in der die CSound Score generiert wird. Das Script
bindet das bereits auf der Harddisk gespeicherte Orchestra-File "smooth.orc" ein (siehe
Quelltext 5.4) und schreibt zwei Instrumenten-Aufrufe: i88 und i14. Instrument 88 ist ein
Hilfsinstrument, daß in Intervallen den Processing-Fortschritt in die Console schreibt. Instrument 14 liest die Trajektorien ein, filtert sie mit einem reson Unit-Generator der gewählten
Frequenz und schreibt das Ergebnis in das CSound Ausgabefile.
CSound selbst wird durch die Lisp-Funktion execute gestartet. Der Pfad zu CSound wird
durch Auslesen des Preferences-Feldes CSOUNDAPP ermittelt. Das erste Argument von execute
ist eine Callback-Funktion im Script, die die Console-Ausgabe des ausgeführten Programmes
auswertet. Sie leitet diese Console-Ausgabe einfach mittels println in die Console von Meloncillo um und filtert die von Instrument 88 generierten Strings heraus, um stattdessen mit
progression-set die Fortschritts-Anzeige von Meloncillo zu aktualisieren:
(defun parse−cs−output (textline)
(if (and (eql 10 (length textline)) (eql "CILLO " (substring textline 0 6)))
(progression−set
(car (format−parse "{0,number}" (substring textline 6 10))))
; else
(println textline)
)
)
Nachdem alle execute Befehle ausgeführt wurden, kehrt die Funktion render zurück. Das
Lisp-Plug-In kopiert nun die von CSound generierten neuen Trajektorien-Dateien zurück in
die Session und ruft abschließend die Script-Funktion cleanup auf.
Quelltext 5.4: smooth.orc
; read a transmitter path and write its lowpass
; filtered transformation back to the output file
; p4 = traj input path; p5 = cutoff frequency [Hz]
instr 14
; bug in CSound 4.23f11 −− channels are swapped
aty atx diskin p4, 1, 0, 0, 6 ; path, pitch, offset, wrap, format
aoutx
reson
atx, 0, p5, 1
aouty
reson
aty, 0, p5, 1
outch
1, aoutx
outch
2, aouty
endin
53
5 Plug-In Schnittstellen
; print progress information every 2 seconds
instr 88
iweight
=
1.0 / p3
kschoko
times
printks "CILLO %.2f\\n", 2, kschoko ∗ iweight
endin
5.4 Open Sound Control
Open Sound Control (OSC) wurde am CNMAT in Berkeley von Matt Wright und Adrian
Freed entwickelt. Es ist als Kommunikationsprotokoll gedacht, mit dem sich Computer und
Computeranwendungen, insbesondere Multimedia-Hardware und -Software verständigen können. Das Grundkonzept wurde von den Autoren auf der ICMC 1997 vorgestellt.10 Nachdem
der Boom im Bereich von Software-Synthesizern begonnen hatte und neue schnelle ComputerSchnittstellen wie Firewire und USB sich durchzusetzen begannen, stellte sich die Frage, wie
voneinander getrennte Komponenten ihre Daten austauschen sollten. Die MusikinstrumenteIndustrie (Yamaha) hatte bereits vorgeschlagen, auf dem etablierten MIDI Standard aufzubauen. OSC hingegen versucht, die offensichtlichen Beschränkungen des damals 14-jährigen
MIDI Standards zu umgehen: MIDI ist unskalierbar – der Befehlssatz ist festgelegt und
überdies hochproblematisch11 –, hat eine viel zu geringe Datenrate (31.25 kbs), kennt nur
eine beschränkte Zahl von Adressaten (MIDI-Kanäle) und kann praktisch keine zwei Befehle
gleichzeitig ausführen.
5.4.1 Protokollübersicht
In der Erkenntnis, daß Transport-Protokolle und Hardware-Interfaces sich schneller ändern
können als ein Musik-Kommunikations-Protokoll, wurde OSC transportunabhängig definiert.
Es ist jedoch an die Erfordernisse von Netzwerk-Transport wie UDP angepaßt und geht von
einer Paket (Datagramm) Struktur aus. OSC Befehle sind in einem OSC-Paket verpackt,12
das leicht als UDP-Datagramm versandt werden kann. Zwei Typen von OSC-Paketen werden
unterschieden: Messages und Bundles. Bundles gruppieren synchron auszuführende Messages oder weitere Bundles in einem einzelnen Paket. Sie beginnen mit dem speziellen String
"#bundle" gefolgt von einem sogenannten Time-Tag, das den Zeitpunkt beschreibt, zu dem
die enthaltenen Messages auszuführen sind.13
Eine Message enthält den eigentlichen Befehl. Sie besteht aus einem URL-ähnlichen symbolischen Adreß-String und einer beliebigen Zahl von binär kodierten Argumenten. Die symbolische Message-Adresse wird vom Empfänger ausgewertet, in einer objekt-orientierten Umgebung üblicherweise von links nach rechts hierarchisch absteigend, so daß eine Adresse wie
10
[Wright/Freed 1997]
Dazu zählt die ideologische Festlegung auf Tasteninstrumente mit 127 Halbtonschritten; natürlich ist MIDI
anders interpretierbar, aber die Umdefinierung von Controller-Changes oder das Hantieren mit SysExBefehlen kann nur als Notbehelf betrachtet werden.
12
Die aktuellen Spezifikationen sind unter der Adresse http://www.cnmat.berkeley.edu/OpenSoundControl/
OSC-spec.html zu finden.
13
Die zwei oder mehreren kommunizierenden Objekte sind dafür verantwortlich, daß sie auf dieselbe SystemZeit zugreifen. Innerhalb desselben Computers ist dies automatisch gegeben, in einem Netzwerk müssen
sich die Systeme ggf. per Network-Time-Protocol (NTP) prüfen an einer Netzwerk-Uhr orientieren.
11
54
5 Plug-In Schnittstellen
z.B. "/synth/oscillators/sawtooth/set-frequency" zuerst an das Synthesizer-Objekt
geschickt wird, das sie an die Oszillator-Sektion weitergibt, die wiederum an den SägezahnGenerator, der dann den Befehl zum Ändern der Frequenz ausführt. Im Gegensatz zu MIDI
kann sich der Adreß-Raum grundsätzlich dynamisch verändern. Das ursprüngliche OSC Protokoll sieht folgende spezielle Message-Adressen vor:
•
Wildcards wie ’*’ oder ’?’, die es erlauben, eine Nachricht an mehrere Adressaten zu
verschicken, deren Adressen auf das Wildcard Pattern passen
•
Objekt-spezifische Informations-Anfragen, die durch Zurücksenden einer Nachricht beantwortet werden14
•
Anfragen zum Adreß-Raum, d.h. zu den verfügbaren Unteradressen eines Objekts
•
Anfragen zu den erwarteten Argumenten und Daten-Typen eines Befehls
•
Eine "/documentation" Anfrage, die einen Text zurückliefern soll, der vom Benutzer
gelesen werden kann
•
Eine "/current-value" Anfrage, die den aktuellen Parameter-Wert (etwa die OszillatorFrequenz im obigen Beispiel) zurückliefern soll
Sechs Jahre nach Einführung von OSC gibt es bereits zahlreiche OSC-Implementationen.
Der Umfang, in dem Time-Tags, Pattern-Matching und die speziellen Messages unterstützt
werden, variiert jedoch erheblich. Eine klarere Rollen-Teilung der kommunizierenden Objekte
wird in den Ausdrücken OSC-Server und OSC-Client deutlich.15 Im Client/Server-Modell
stellt der Server Dienste zur Verfügung, ein oder mehrere Clients benutzen diese Dienste,
die Kommunikation verläuft überwiegend in Richtung Server, der gegebenenfalls AntwortNachrichten zurückschickt.
Das CNMAT führt eine Liste an Applikationen, die OSC unterstützen,16 sie ist allerdings
unvollständig und zum Teil obsolet. Zu den Musik- und Klang-Programmen zählen SuperCollider, Max/MSP, PD, jMax, OpenMusic, RTcmix und Siren. Im Bereich Multimedia
sind OSC-Anbindungen an Macromedia Flash (flosc) und Director (OSCar) zu nennen. Am
IRCAM wurde mit EtherSense ein Sensor-Gerät für Live-Performances entwickelt, das direkt
OSC über Ethernet an einen Computer überträgt. Das vom CNMAT herausgegebene OSCKit, eine OSC-Bibliothek in C, wurde in weitere Sprachen wie Java, Objective-C, Common
Lisp und Ruby übertragen.
In der Implementation von OSC in James McCartneys SuperCollider wurde eine entscheidende Erweiterung des Protokolls vorgenommen, die sich übergreifend durchgesetzt hat: Die
wenigsten Implementationen unterstützen derzeit das Type-Querying, also das Abfragen der
Daten-Typen für Message-Parameter. In der Praxis ist dem Client oder Anwender bereits
bekannt, wie die Messages eines Servers aufgebaut sind. Auf der Server-Seite wiederum muß
ein allgemeines OSC-Empfangs-Objekt in der Lage sein, die Message-Argumente korrekt zu
dekodieren, bevor sie vom eigentlichen Adressaten weiterverarbeitet werden.17 Daher wurde
der Type-Tag-String in OSC-Messages eingeführt. Er stellt das erste Argument jeder Message
14
Der Sender wird nicht direkt in der Message vermerkt, kann jedoch normalerweise vom Transport-Layer
erfragt werden. UDP Datagramme enthalten z.B. eine Return-Adresse.
15
vgl. [Wright et al. 2003]. Die Ausdrücke sind offenkundig von SuperCollider 3 übernommen.
16
http://www.cnmat.berkeley.edu/OpenSoundControl/
17
Das Max-External OpenSoundControl zum Beispiel generiert eine Liste mit Max-Primitives aus den empfangenen OSC-Nachrichten; diese wird dann normalerweise über OSC-route an die Adressaten verteilt. Ohne
Type-Tags kann OpenSoundControl also nur raten“, welche Daten-Typen gemeint sind.
”
55
5 Plug-In Schnittstellen
dar und besteht aus einem Komma-Charakter gefolgt von einer Kette von Type-Charakteren,
die den Daten-Typ aller Argumente angeben. Die wichtigsten Typen sind ’i’ für 32bit lineare
ganze Zahlen, ’f’ für 32bit Floating-Point Zahlen, ’s’ für Strings oder Symbole und ’b’ für den
sogenannten ’Blob’, einen binären Datenblock. Type-Tags machen komplizierte ArgumentPrüfung und Heuristiken überflüssig.
5.4.2 Implementierung in Meloncillo
Die eigentlichen OSC-Klassen von Meloncillo befinden sich im Paket net. Es sind
•
OSCPacket : Superclass von Messages und Bundles, die Methoden zum En- und Dekodieren von Paketen enthält
•
OSCMessage : Die Message Klasse, die Java-Primitives in Binärform kodiert bzw. aus
der binären empfangenen Nachricht dekodiert
•
OSCBundle : Die Bundle Klasse. Messages und Bundles werden zunächst einzeln hinzugefügt und anschließend in Binärform kodiert. Neben den normalen absoluten TimeTags des OSC Standards werden die relativen Time-Tags des SuperCollider NonRealTime-Modus (NRT) unterstützt
•
OSCReceiver : Objekte dieser Klasse können in einem eigenen Thread auf das Eintreffen
von Nachrichten warten
•
OSCListener : Listener für einen OSCReceiver, der beim Empfang von Nachrichten
informiert wird
•
OSCException : Klasse für OSC-bezogene Fehler
Während sich die Klassen zunächst an die bereits existente Java-Bibliothek JavaOSC18 anlehnten, wurden sie aus Gründen der Effizienz und etwas umständlichen Art von JavaOSC
neu programmiert und auf die nötigsten Elemente beschränkt. Sie unterstützen momentan
kein Pattern-Matching19 und keine mit Brackets (’[’, ’]’) getypten Arrays20 , außerdem gibt es
keinen separaten Dispatcher. Stattdessen wird mit entsprechenden Methoden der java.net
und java.nio Pakete einfach ein DatagramChannel geöffnet, die zu versendenden Pakete in
einen ByteBuffer kodiert (dies erledigt OSCPacket) und mit write in den DatagramChannel
geschickt.
Im Paket lisp existieren die Wrapper-Klassen OSCBundleSendPrimitive und OSCBundleSendAndWaitPrimitive. Sie stehen den Lisp Scripten zur Verfügung. Während die erste
Funktion ein OSC-Bundle asynchron verschickt, wartet die zweite Funktion nach dem Versand für eine angegebene Zeit auf eine bestimmte Rückmeldung. Konkrete Beispiele für den
Gebrauch von OSC-Messages in Lisp werden im Abschnitt 5.4.3 gezeigt.
18
http://www.mat.ucsb.edu/~c.ramakr/illposed/javaosc.html
Dies macht nur für OSC-Server Sinn. Ein Client-Listener kann jedoch auf die mächtigen Funktionen von
java.util.regex zurückgreifen. Den gegenwärtigen Diskussionen des Forums osc_dev@create.ucsb.edu
kann darüber hinaus entnommen werden, daß sich das Pattern-Konzept in zukünftigen OSC Versionen
voraussichtlich ändern wird.
20
Dies auch vor dem Hintergrund, daß sclang ebenfalls keine Brackets benutzt, sondern Arrays einfach direkt
in die einzelnen Elemente auflöst.
19
56
5 Plug-In Schnittstellen
5.4.3 Anbindung an SuperCollider
SuperCollider is an environment for real time audio synthesis which runs on a
”
Power Macintosh with no additional hardware“ [McCartney 1996]
Diese knappe Beschreibung der ersten Version von SuperCollider aus dem Jahre 1996 trifft
im wesentlichen noch für Version 3 zu, obwohl das Programm konzeptuell einige Änderungen
erfahren hat.21 Während SuperCollider 1 gerade aus der Fusion zweier Vorläuferprogramme
hervorging, einer Klangsynthese-Sprache (Synth-O-Matic) und einer Interpreter-Umgebung
für Max (Pyrite), besteht der wesentliche Unterschied von Version 3 zu Version 2 darin, daß
es sich eigentlich wieder um zwei unabhängige Programme handelt, die SuperCollider Language Application (kurz sclang) und die SuperCollider Synthesis Engine (kurz scsynth).
sclang bietet eine auf der Sprache SmallTalk basierende Programmierumgebung, die zur
Klanggenerierung mit scsynth über OSC kommuniziert. scsynth hat grundsätzlich nichts
mit SmallTalk oder überhaupt einer höheren Sprache zu tun. Der einfache Befehlssatz, der
aus ca. 50 einzelnen Kommandos eines flachen Adreßraums besteht22 , und die Effizienz der
DSP Algorithmen prädestinieren scsynth dazu, von Frontends verschiedenster Art als reine
Rechenmaschine verwendet zu werden, mit der der Anwender nicht direkt etwas zu tun bekommt. In dieser Konstellation wird SuperCollider als Server und die Steueranwendung als
Client bezeichnet.
Ein Beispiel für einen SuperCollider Client ist die in einer Fußnote in Abschnitt 4.1 erwähnte
Scream Umgebung bzw. die damit erstellte Applikation AmbiGranusampler. Ein weiteres Beispiel ist der dort ebenfalls kurz dargestellte Sonificator, der ähnlich wie Scream als ProgrammSchnittstelle (API) für Audio-Patches konzipiert ist, auf der lightweight Java Applikationen
aufsetzen können.
Da Meloncillo fast nichts von SuperCollider weiß – dies liegt in der Obhut der Scripte –,
läßt sich prinzipiell auch sclang als Server benutzen, wodurch komplexere algorithmische
Verfahren möglich sind. Der Einfachheit halber wird jedoch nur ein Beispiel für die direkte
Kommunikation mit scsynth dargestellt. Im Gegensatz zu sclang wurde der Synth Server
bereits auf andere Plattformen portiert und kann unter Mac OS X, Linux i386, Linux PPC
und Win32 benutzt werden. Da Meloncillo die OSC Messages über UDP an SuperCollider
versendet, kann SuperCollider auch auf einem anderen Rechner als Meloncillo laufen, wenn
diese Rechner über ein LAN verbunden sind. Die Synchronisation der Uhren beider Rechner
ist hingegen noch ungelöst (vgl. Abschnitt 6.2).
SuperCollider kann sowohl in Echtzeit, als auch in einem speziellen NonRealTime-Modus
(NRT) gestartet werden. Mit wenigen Anpassungen lassen sich die Lisp Scripte und SuperCollider Patches gleichzeitig für Realtime-Synthese und Bounce-to-Disk verwenden, da SuperCollider im NRT Modus weiterhin über OSC gesteuert wird. Die OSC-Bundles werden dabei
sequentiell aus einer Datei gelesen, statt sie in Echtzeit zu empfangen.
21
22
siehe dazu [McCartney 2002]
Deren Zahl halbiert sich etwa, wenn man eng verwandte Befehle zusammenfaßt, wie /b_set und /b_setn für
das Beschreiben eines Puffers. Flacher Adreßraum bedeutet, daß Kommandos nicht hierarchisch geschachtelt und durch Schrägstriche getrennt werden, also ein Puffer beispielsweise direkt mit "/b_free 789" statt
"/buffer/789/free" freigegeben wird.
57
5 Plug-In Schnittstellen
Root Node
numTrns = Zahl der Transmitter (5)
numRcv = Zahl der Receiver (4)
Master Group
Input Group
Mix Group
Phasor Synth
Control−Bus
0...numTrns−1
Vektor aus Input Synths
Matrix aus Mix Synths
Audio−File Buffer
Audio−Bus
Audio−File Buffer
Audio−Bus
Audio−File Buffer
Audio−Bus
Audio−File Buffer
Audio−Bus
Audio−File Buffer
Audio−Bus
Sense−Buf
Sense−Buf
Sense−Buf
Sense−Buf
Sense−Buf
Sense−Buf
Sense−Buf
Sense−Buf
Sense−Buf
Sense−Buf
Sense−Buf
Sense−Buf
Sense−Buf
Sense−Buf
Sense−Buf
Sense−Buf
Matrix aus Sensitivitäts−Puffern
Audio−Hardware−Output
Sense−Buf
Audio−Hardware−Output
Sense−Buf
Audio−Hardware−Output
Sense−Buf
Audio−Hardware−Output
Sense−Buf
0...numRcv−1
Abbildung 5.5: Nodes, Busse und Buffer für einen Amplituden-Mixer in SuperCollider
Beispiel eines einfachen Amplituden-Pannings
scsynth verwaltet in gewisser Analogie zum MUSIC V Konzept Synthesizer, die aus UnitGeneratoren bestehen. Ein solcher durch eine UGen-Graph-Function beschriebener Synthesizer ist ein Knoten-Punkt in einem hierarchischen Baum, den scsynth verwaltet. Neben
Synth-Nodes gibt es Group-Nodes, die mehrere Synthesizer oder Gruppen zusammenfassen.
Eine Gruppe ist eine Liste aus Knoten. Neue Knoten werden entweder an den Anfang oder
das Ende der Liste gesetzt. Innerhalb einer Gruppe werden die Knoten in der Reihenfolge ihrer Position in der Liste abgearbeitet. Die Reihenfolge ist entscheidend beim Entwurf
eines Patches – wird zum Beispiel ein Soundfile eingelesen (Input-Knoten) und auf einen
Bus geschickt, auf den ein Mixer zugreifen soll (Mix-Knoten), so muß der Input-Knoten vor
dem Mix-Knoten ausgeführt werden. In den OSC Messages werden Synthesizer und Gruppen
durch eine eindeutige ganze Zahl, die Node-ID, angesprochen, die jedoch keinen Einfluß auf
die Reihenfolge der Abarbeitung hat.
58
5 Plug-In Schnittstellen
Ebenfalls klassisch in SuperCollider ist die Trennung zwischen Controlrate- und AudiorateSignalen. Diese laufen über ein globales Bussystem, was vor allem hinsichtlich der AudioDaten den Vorteil hat, daß beliebig viele Synthesizer aus einem Audio-Bus lesen oder in einem
Audio-Bus zusammengemischt werden können. Neben Bussen gibt es Puffer, die intern oder
per OSC blockweise beschrieben werden können.
Um einen einfachen Matrix-Mixer nach dem Amplituden-Panning Prinzip zu realisieren, werden Gruppen und Synthesizer nach dem in Abbildung 5.5 dargestellten Schema kreiert. Drei
verschiedene Synthesizer kommen zum Einsatz, die in sclang programmiert wurden:
Quelltext 5.5: synthdef-sources.sc
// reads input from sound file
// and writes it to an audio bus
SynthDef( "cillo−input", {
arg i aInBuf, i aOutBus, i gain = 1.0;
Out.ar( bus: i aOutBus, channelsArray:
DiskIn.ar( numChannels: 1, bufnum: i aInBuf ) ∗ i gain );
}).writeDefFile( p );
// mixing pipe taking an input audio
// bus, a control buf for amplitude
// modulation and an audio output bus
SynthDef( "cillo−mix", {
arg i aInBus, i aOutBus, i kInBuf, i kPhasorBus;
Out.ar( bus: i aOutBus, channelsArray: In.ar( bus: i aInBus ) ∗
BufRd.kr( numChannels: 1, bufnum: i kInBuf,
phase: In.kr( bus: i kPhasorBus )));
}).writeDefFile( p );
// one phasor object represents something
// like a synchronized motor for all
// control rate amplitude buffer reads.
// a trigger is fired twice per buffer cycle
SynthDef( "cillo−phasor", {
arg i rate, i bufSize, i kPhasorBus;
var clockTrig, phasorTrig, clockRate, phasorRate, controlRate;
controlRate
phasorRate
clockRate
clockTrig
phasorTrig
=
=
=
=
=
SampleRate.ir / 64;
i rate / controlRate;
2 ∗ i rate / i bufSize;
Impulse.kr( freq: clockRate );
PulseDivider.kr( trig: clockTrig, div: 2, start: 1 );
SendTrig.kr( in: clockTrig, id: 0, value: PulseCount.kr( trig: clockTrig ));
Out.kr( bus: i kPhasorBus, channelsArray: Phasor.kr( trig: phasorTrig,
rate: phasorRate, start: 0, end: i bufSize ));
}).writeDefFile( p )
cillo-input liest mit dem DiskIn UGen ein Soundfile ein und schreibt es auf einen Bus,
cillo-mix mischt einen Eingangsbus (Soundfile) auf einen Ausgangsbus (Soundkarten-Ausgang). Die Lautstärke wird aus Puffern gelesen, die blockweise mit dem OSC Befehl "/b_setn"
von Meloncillo gefüllt werden. Der Phasor-Synthesizer generiert ein Sägezahn-Signal, das
diese Puffer zyklisch abtastet. Die Instantiierung der Gruppen und Synthesizer erfolgt vom
Lisp-Script aus mit der osc-bundle-send[-and-wait] Funktion. Hier ein Beispiel:
59
5 Plug-In Schnittstellen
(datagram−channel−open 1977 "localhost" 57110)
(if (null (osc−bundle−send−and−wait 1977 0.0 (list
(list "/g new" master−group 1 0
input−group 0 master−group
mix−group
1 master−group)
(list "/d load" synthdefs))
"/done" 2000
))
(println "TIMEOUT! group creation, definition load")
; else
NIL
)
1977 ist der Identifier für den in der ersten Zeile geöffneten Datagramm-Kanal. Das Bundle
enthält die zwei Messages "/g_new" zur Erzeugung der Gruppen-Knoten und "/d_load" zum
Einlesen der Synthesizer-Definitionen aus einer Festplatten-Datei. Die letzten beiden Argumente der OSC-Funktion legen fest, daß maximal zwei Sekunden auf die Antwort-Nachricht
"/done" gewartet werden soll. Die Funktion liefert diese Antwort-Nachricht zurück oder NIL,
wenn innerhalb dieser Zeitspanne nicht geantwortet wurde.
Während der Realtime Modus aktiv ist, werden die Transport-Befehle an das Lisp-Script
weitergegeben. Es muß dafür die Funktionen position, play und stop definieren. Aus
Performance-Gründen wird das Script nicht damit beauftragt, kontinuierlich OSC-Nachrichten
zum Auffüllen der Sense-Puffer zu erzeugen. Stattdessen übergibt es der im Realtime-Modus
etwas modifizierten source-request Funktion einen vorher mit dem Skelett der OSC-Message
("/b_setn") initialisierten Byte-Buffer und eine Liste von Anweisungen, die auf diesem Puffer
ausgeführt werden sollen:
(source−request "SENSE" (cons trnsidx rcvidx) 1978 (list
(list "INT" bufidx msgbuf−off)
(list "VAR" "BUFOFF" (+ msgbuf−off 4))
(list "STREAM" (+ msgbuf−off 12))
(list "SEND" 1977)
))
1978 ist der Identifier des Byte-Buffers, in den die Nachricht kodiert wird. Die Befehlsliste bewirkt, daß der (SuperCollider-)Puffer-Index und der Puffer-Lese-Index jeweils ersetzt und die
Sensitivitätsdaten ("STREAM") übertragen werden, bevor die Nachricht an den DatagrammKanal mit dem Identifier 1977 versandt wird.
Meloncillo kennt darüber hinaus einen speziellen Sync-Befehl23 : Der Phasor in Quelltext 5.5 sendet zweimal pro
Durchlauf mit dem SendTrig UGen eine OSC-Nachricht "/tr" an Meloncillo. Dadurch wird der Versand neuer
Sensitivitäts-Puffer ausgelöst. Würde Meloncillo nach seiner internen Uhr die Puffer versenden, könnten diese
manchmal zu früh ankommen. Neue Trigger-Befehle werden mehrfach pro Puffer-Periode ausgewertet, dies ist
der Grund für die spezielle Notification-Rate in Abbildung 5.4. Gleichzeitig kann das Programm überprüfen,
ob Drop-Outs aufgetreten sind und meldet dies dem Benutzer. Für eine zukünftige Version wird geprüft, ob
sich die Synchronisierung einfacher durch die Time-Tags der Bundles lösen läßt.
Das Script und die SynthDefs können als Ausgangspunkt dienen, mit neuen Synthese-Modellen
zu experimentieren. Die Input-Synths könnten zum Beispiel durch Live-Inputs ersetzt wer-
23
(target-request "SYNC" 0 <datagram-channel-id>)
60
5 Plug-In Schnittstellen
den24 , zwischen die Input- und Mix-Stufe kann eine Filter, (Doppler-)Delay oder VerzerrerEinheit gesetzt werden. Die Mix-Stufe selbst kann modifiziert werden, oder ihre Ausgänge
auf weitere Busse statt direkt auf die Hardware-Outputs geschickt werden.
24
Da scsynth allerdings kein MIDI versteht, muß noch eine Lösung zur Synchronisierung z.B. mit einem
Harddisk-Recording-Programm gefunden werden. Man kann versuchen, dazu sclang zu verwenden.
61
6 Resumé
6.1 Anwendungsbeispiel
Abschließend sollen an einem SuperCollider Patch ein paar Möglichkeiten des Programms
demonstriert werden. Ausgangspunkt ist ein Synthesizer nach Abbildung 5.5. Er soll wie
folgt erweitert werden:
•
zuschaltbarer Doppler-Effekt für die Transmitter-Bewegungen
•
zuschaltbarer räumlich gerichteter Verzerrer
•
zuschaltbarer Hall
•
optionale Umkehrung des Modells, so daß die Receiver die Ausgangsklänge symbolisieren und die Transmitter diese Klangfelder als bewegte Mikrophone“ abtasten und zu
”
den Lautsprechern leiten
Doppler-Effekt
Der Doppler-Effekt beschreibt das Phänomen, daß sich die wahrgenommene Tonhöhe eines
Klangkörpers in Abhängigkeit von seiner Bewegung relativ zum Beobachter verändert. Nähert
sich der Klangkörper dem Beobachter, so wird die Wellenlänge effektiv verkürzt und die
Tonhöhe steigt, der umgekehrte Fall tritt auf, wenn sich der Klangkörper wegbewegt. Um
einen Doppler-Effekt zu realisieren, bedient man sich einer variablen interpolierenden DelayLine. Die momentane Delay-Zeit korrespondiert mit dem Abstand der Klangquelle vom Beobachter und beträgt im Medium Luft bei Raumtemperatur etwa ∆t = ∆d/(344m/s).
Der Doppler-Effekt wird als Insert in den Signalfluß gesetzt. Ein Insert kann in SuperCollider realisiert werden, indem ein Audio-Bus mittels In.ar eingelesen und das Ergebnis mit
ReplaceOut.ar zurückgeschrieben wird. Zur Berechnung des Doppler-Shifts werden im Lisp
Script mit weiteren (source-request) Befehlen nun zusätzlich zu den Sensitivitäten auch
die Trajektorien-Koordinaten angefordert. Für die Beobachter-Position wird vereinfachend
der Surface-Mittelpunkt (0.5, 0.5) angenommen, dies läßt sich später leicht parametrisieren.
Die Trajektorien-Daten werden analog zum Mix-Synth (Quelltext 5.5) mit einem durch den
Phasor betriebenen BufRd abgetastet. Das aus X- und Y-Koordinaten bestehende StereoSignal wird mit Select UGens aufgetrennt und die Distanz nach dem Satz des Pythagoras
berechnet:
62
6 Resumé
Quelltext 6.1: cillo-doppler.sc
SynthDef( "cillo−doppler", {
arg i aBus, i kInBuf, i kPhasorBus, i extent = 0.04;
var traj, dly;
traj= BufRd.kr( numChannels:
phase: In.kr( bus: i
dly = ((Select.kr( which: 0,
(Select.kr( which: 1,
2, bufnum: i kInBuf,
kPhasorBus ));
array: traj ) − 0.5).squared +
array: traj ) − 0.5).squared).sqrt ∗ i extent;
ReplaceOut.ar( bus: i aBus, channelsArray: DelayC.ar(
in: In.ar( bus: i aBus ), maxdelaytime: 2 ∗ i extent, delaytime: dly ));
}).writeDefFile( p );
Der Benutzer bestimmt die Raum-Größe auf der graphischen Oberfläche des Lisp Plug-Ins.
Der Normalisierungsfaktor für die Delay-Zeit i_extent wird bereits im Lisp Script berechnet. DelayC ist eine kubisch interpolierende Delay-Line. maxdelaytime bestimmt die interne
Puffergröße und muß so gewählt sein, daß keine Verzögerungen auftreten, die größer als dieser
Wert sind.
Verzerrer
Unter Verzerrung kann man allgemein eine Signaltransformation verstehen, die nicht durch
ein lineares System beschrieben werden kann. Eine einfache Verzerrung ist beispielsweise die
Transformation y ← x2 . Ein Verzerrer kann mit einem Median-Filter gebaut werden. Wenn
man jeweils von wenigen benachbarten Samples den Median berechnet, werden kurze Spikes
eliminiert. Subtrahiert man nun das Originalsignal, bleiben hauptsächlich diese kurzen Signalspitzen übrig. Das Differenz-Signal wird mit dem geglätteten Median-Signal moduliert. Mit
einem Amplituden-Envelope-Follower kann das verzerrte Signal grob an die ursprüngliche
Lautstärke angepaßt werden.
Der Verzerrer soll von einem Richtungsvektor gesteuert werden. Ein zusätzlicher Transmitter
wird dafür benutzt. Er bekommt den speziellen Namen ’d’ (Distortion) und wird aufgrund
dieses Namens vom Lisp Script erkannt und separat behandelt. Für jeden Ausgangskanal wird
ein Distortion-Synth erzeugt, der in Abhängigkeit von diesem d-Transmitter zwischen dem
trockenen und verzerrten Signal überblendet. Das Mischungsverhältnis wird aufgrund des
Winkels, den der d-Transmitter und der jeweilige Receiver zum Surface-Mittelpunkt bilden,
gewählt. Wenn A die gegenwärtige Position des d-Transmitters, B der Surface-Mittelpunkt
und C der Ankerpunkt des Receivers sind, ergibt sich der Winkel nach
arctan
(Cx −Bx )·(Ay −By )−(Cy −By )·(Ax −Bx )
(Cx −Bx )·(Ax −Bx )+(Cy −By )·(Ay −By)
Das Mischungsverhältnis wird daraus so berechnet, daß bei einem Winkel von 0◦ nur die
Verzerrung, bei 180◦ nur das trockene Signal zu hören ist. Mit einem Divergenz-Parameter
i_narrow läßt sich die Verlauf zwischen 0◦ und 180◦ einstellen. Hier die Synthesizer-Definition:
63
6 Resumé
Quelltext 6.2: cillo-distortion.sc
SynthDef( "cillo−distortion", {
arg i aBus, i kInBuf, i kPhasorBus, i locX, i locY,
i gain = 2.0, i narrow = 4.0;
var traj, dtrajx, dtrajy, dstatx, dstaty, da, dry, mix, med, flt,
norm mul, norm add;
dstatx =
dstaty =
norm mul=
norm add=
traj
dtrajx
dtrajy
i locX − 0.5;
i locY − 0.5;
−1.0 / pi;
1.0;
= BufRd.kr( numChannels: 2, bufnum: i kInBuf,
phase: In.kr( bus: i kPhasorBus ));
= Select.kr( which: 0, array: traj ) − 0.5;
= Select.kr( which: 1, array: traj ) − 0.5;
// delta angle normalized to 0.0 ... 1.0
// (where 1.0 is 0 degrees, 0.5 is +/− 90 degrees,
// 0.0 is 180 degrees)
da
= abs( atan2( (dstatx ∗ dtrajy) − (dstaty ∗ dtrajx),
(dstatx ∗ dtrajx) + (dstaty ∗ dtrajy) )) ∗ norm mul + norm add;
mix
= min( 1.0, (dtrajx.squared + dtrajy.squared) / 0.125 ) ∗
da.pow( i narrow );
dry
med
flt
= In.ar( bus: i aBus );
= Median.ar( length: 3, in: dry );
= Normalizer.ar( in: (dry − med) ∗ med,
level: Amplitude.kr( in: dry, mul: i gain ), dur: 0.005 );
ReplaceOut.ar( bus: i aBus, channelsArray: Median.ar(
length: 3, in: flt, mul: mix, add: DelayN.ar(
in: dry, mul: 1.0 − mix, delaytime: 0.1, maxdelaytime: 0.01 )));
}).writeDefFile( p );
Das trockene Signal muß mit DelayN verzögert werden, um den Look-Ahead des MedianFilters auszugleichen und Kammfilter-Effekte bei der Überblendung zu verhindern.
Hall
Mit Allpass-Filtern kann man einen primitiven Hall simulieren. Ähnlich dem Verzerrer verwenden wir ein Session-Objekt zur Steuerung des Halls: Einen zusätzlichen Receiver mit dem
speziellen Namen ’e’ (Echos). Angenommen, die normalen Receiver befinden sich in einer
kreisförmigen Anordnung. Dann kann der e-Receiver einfach in deren Mitte plaziert werden;
wird ein Transmitter von der Kreisbahn zur Mitte hin abgelenkt, so wird sein Signal in die
Hall-Sektion gegeben. Der Einfachheit halber ist der Input dieser Hall-Sektion ein Mono-Bus,
und für jeden Ausgangskanal wird dieses Mono-Signal mit einem Allpass-Filter verhallt, das
eine zufällige variierende Delay-Zeit hat:
64
6 Resumé
Normaler Modus
Input Group
Doppler Group
Mix Group
Echo + Distortion Group
Input−Synth
Echo−Synth
Mix−Synths
Matrix
...
Input−Synth
Sense−Bufs
(e−Receiver)
...
numInputs
Sense−Buf
Matrix
Echo−Synth
(insert)
Doppler−Synth
Audio−Output
Audio−Output
...
Traj−Buf
Matrix
Distortion−Synth
...
(insert)
...
Doppler−Synth
Distortion−Synth
Traj−Buf
(d−Transmitter)
numInputs = Zahl der Transmitter
numOutputs = Zahl der Receiver
numOutputs
Umgedrehter Modus
Distortion Group
Input−Synth
Mix Group
Doppler Group
Sense−Buf
Matrix
Mix−Synths
Matrix
...
Input−Synth
(insert)
(insert)
Distortion−Synth
...
Audio−Output
...
Traj−Buf
(d−Transmitter)
Audio−Output
Distortion−Synth
Doppler−Synth
...
numInputs
Input Group
Doppler−Synth
Traj−Buf
Matrix
numInputs = Zahl der Receiver
numOutputs = Zahl der Transmitter
numOutputs
Abbildung 6.1: Erweiterter SuperCollider Synthesizer
65
6 Resumé
Abbildung 6.2: Steuerelemente und Script Oberfläche für den erweiterten Synth
Quelltext 6.3: cillo-echo.sc
SynthDef( "cillo−echo", {
arg i aInBus, i aOutBus;
Out.ar( bus: i aOutBus,
channelsArray: LPZ2.ar( in: AllpassL.ar( in: In.ar( bus: i aInBus ),
maxdelaytime: 0.31, delaytime:
LFNoise1.kr( 0.1, mul: 0.1, add: 0.2 ), decaytime: 3 )
)
);
}).writeDefFile( p );
Der Lowpass-Filter LPZ2 dunkelt die Hallfarbe etwas ab.
Modell-Umkehrung
Um das Modell so umzukehren, daß die Receiver Klangfelder darstellen und die Transmitter bewegte Mikrophone/Lautsprecher, muß das Lisp Script so verändert werden, daß Receiver durch abstrakte Output-Objekte und Transmitter durch abstrakte Input-Objekte ersetzt werden. In der Initialisierung kann dann die Zuordnung einfach umgetauscht werden.
Zusätzlicher Aufwand entsteht dadurch, daß die Indices der Transmitter und Receiver bei
der Quelldaten-Anforderung mit (source-request) nicht umgedreht werden dürfen. Auch
müssen die Gruppen-Knoten unterschiedlich angeordnet werden, damit die Reihenfolge der
DSP-Blöcke korrekt bleibt. Wenn man davon ausgeht, daß die Verzerrer unabhängig vom
Modell immer die Receiver bearbeiten und der Doppler immer auf die Transmitter einwirkt
(die Receiver sind ja unbewegt und können daher keinen Doppler-Shift erzeugen), ergeben
sich die beiden Schemata nach Abbildung 6.1.
Das Lisp Script scrt-demo.lisp ist zusammen mit einer Beispiel-Session und BeispielKlängen auf der beigefügten CD-ROM enthalten. Die vom Script generierten GUI Para-
66
6 Resumé
meter sind in Abbildung 6.2 rechts zu sehen. Der Normal-Modus, in dem die Transmitter
den Soundfiles zugeordnet sind, ist angewählt. Die Surface links zeigt einen Ausschnitt der
d-Transmitter Trajektorie zum Steuern der Verzerrung. Zu sehen ist auch der kreisförmige
Umriß des in der Mitte plazierten e-Receivers zum Ansteuern des Halls.
6.2 Probleme
Während der Entwicklung der vorliegenden Arbeit sind keine ungelösten Probleme im internen Programmverhalten aufgetreten. Die Thread-Synchronisierung hat einige Zeit in Anspruch genommen und insbesondere in der Anfangsphase viele Bugs enthalten. Dasselbe gilt
für die dynamische Anpassung an Preferences-Änderungen mit dem java.util.prefs Paket.
Insbesondere hat sich als nachteilig erwiesen, daß es einen eigenen Event-Dispatcher verwendet, der außerhalb des AWT Threads läuft, und daß die Ereignisse keine Informationen
darüber tragen, wer die Preferences verändert hat, so daß umfangreiche Vorkehrungen zur
Verhinderung von Deadlocks getroffen werden mußten. Die interne Umstellung aller Objekte
beim Laden einer Session hätte eleganter durch einen zentralen Mechanismus gelöst werden
können.
Das Programm enthält in der aktuellen Version 0.66 noch zahlreiche kleinere Bugs, die nicht
vital für die Benutzung sind. Mit dem Update der Apple Java VM von Version 1.4.2 03 nach
1.4.2 05 kurz vor Fertigstellung der Arbeit wurde die Graphikdarstellung des Timeline Fensters im Echtzeit Modus leider sehr langsam und flackert.1 Dieses Problem ist vermutlich auf
eine Änderung des Double-Buffering Mechanismus zurückzuführen und muß in der nächsten
Version von Meloncillo dringend beseitigt werden.
Ungelöst sind noch Probleme beim Betrieb im Netzwerk. Obwohl in der Anfangsphase ein Test erfolgreich lief, in dem auf einem Computer Meloncillo und auf dem anderen SuperCollider lief, wurde die Realtime-Engine von Meloncillo aus Performance-Gründen
später neu geschrieben. Weitere jüngst vorgenommene Tests ergaben, daß die beiden Rechner nicht synchron bleiben. Die Zeitspanne, die vergeht, bis die ersten Dropouts auftreten,
schwankt je nach Rechner-Paar zwischen einer halben Minute und einer Viertelstunde. Da die
Clock-Unterschiede eigentlich so klein sein sollten, daß bei entsprechend gewählten PufferGrößen ein Synchronisationsverlust erst nach einer Zeitspanne in der Größenordnung von
Stunden auftreten kann, muß die Ursache im Timing-Schema des OSC-Datenversands gesucht werden. Möglicherweise läßt sich das Problem lösen, indem die OSC-Befehle zum
Puffer-Update mit Time-Tags versehen werden.2 Nichtsdestotrotz sollte langfristig eine SlaveSynchronisierung in Meloncillo integriert werden, um eine synchronen Betrieb mit HarddiskRecording-Programmen zu ermöglichen.
1
Man kann sich momentan nur behelfen, indem das Fenster zeitweilig geschlossen wird. Ein positiver Aspekt
des VM Updates ist das Verschwinden eines Bugs, der sich in gelegentlichen Stack-Overflows äußerte, die
innerhalb der Bibliotheken auftraten und damit unmöglich zu eliminieren waren.
2
Ein Vorteil des gegenwärtigen Mechanismus – der Versand nach Aufforderung durch eine /tr Nachricht –
besteht darin, daß eine Anbindung an Max/MSP leichter zu realisieren ist, denn die OSC-Externals von
Max/MSP behandeln Time-Tags derzeit nicht automatisch.
67
6 Resumé
6.3 Ausblick
Die weitere Entwicklung des Programms kann in Detailverbesserungen und größere Ergänzungen und Umstrukturierungen unterteilt werden. Zur ersten Kategorie zu zählen sind
•
Anpassung der Oberfläche und Tastatur-Shortcuts unter Linux und Windows
•
konfigurierbare Farbgebung
•
Dehnen und Kürzen des Zeitabschnitts im Filter Dialog (Resampling)
•
Verbesserung der geometrischen Zeichentools
•
Entwicklung einer DTD für die Session-Datei
•
Shuffle- und Slip-Modus für Timeline-Operationen analog zu ProTools
Die größeren Ergänzungen hängen im wesentlichen davon ab, wie sich das Programm in der
Praxis bewährt. Wichtige Elemente werden sein
•
Stabile Realtime Performance im Netzwerk
•
Synchronisierung mit Harddisk-Recording Programmen
•
Anbindung an Max/MSP 4.5
•
Erweiterung der Timeline um frei setzbare Markierungen
•
evtl. Erweiterung um eine Layer-Struktur
•
Erweiterung der Receiver und Transmitter Interfaces um Attribute
•
script-generierte Preferences Karten
Wie bereits geschildert, bricht die Synchronisation momentan bei Betrieb im Netzwerk
früher oder später zusammen. Obwohl sich das Problem voraussichtlich leicht lösen läßt,
wird eine Unterstützung von OSC-Time-Tags angestrebt. Wenn eine Slave-Synchronisierung
in Meloncillo eingebaut wird, sollte zugleich ein grundlegendes Konzept für eine OSC-Server
Schnittstelle entworfen werden.
Eine einfache Timecode Steuerung (z.B. auf MIDI-Timecode Basis) sollte entwickelt werden,
so daß ein synchrones Einspielen von Spuren aus einem Harddisk-Recording Programm
möglich wird; momentan müssen die zu spatialisierenden Klänge zunächst gebounct werden,
was sehr hinderlich ist. Eine Zwischenlösung kann wahrscheinlich mit sclang erreicht werden.
Es läßt sich ebenso wie scsynth von einem OSC-Client steuern. Ein OSCresponderNode
Objekt müßte auf den Transport-Start in Meloncillo reagieren und einen entsprechenden
MIDI Befehl an eine Applikation wie Logic Pro weiterleiten.
Das Ansteuern von Max/MSP macht momentan wenig Sinn, weil das OSC-Objekt otudp
read von Matt Wright alle Message-Argumente in primitive Max-Typen übersetzt, was für
das Senden großer Floating-Point Puffer ungeeignet ist. Max/MSP 4.5 bietet eine integrierte Java-Schnittstelle (mxj) an. Ein einfaches Plug-In soll dafür entwickelt werden, das die
Sensitivitäts-UDP-Pakete empfängt und direkt in MSP-Puffer schreibt.
Um ein Stück besser überblicken zu können, sind Zeitmarker erforderlich. Diese könnten
auch mit Scripten generiert werden oder von Scripten ausgelesen und zur Klangsynthese
benutzt werden.
68
6 Resumé
Wenn, wie im letzten Beispiel gezeigt, mit mehreren Klangtransformationen gearbeitet wird,
kann die Surface schnell unübersichtlich werden. Zu überlegen ist, wie möglichst einfach die
Form einer Ebenen-Struktur in die Session gebracht werden kann. Diese Ebenen könnten
entweder optisch umgeschaltet oder überlagert dargestellt werden.
Receiver und Transmitter sollten mit einer Attribute-Mappe ausgestattet werden. Um
einfache Features zu integrieren, wie zum Beispiel die Möglichkeit, Transmitter stummzuschalten oder solo abzuhören, müssen die Scripte momentan spezielle GUI Felder auf ihre
Plug-In Oberflächen addieren. Er wäre effektiver, mit einem einfachen get und set Mechanismus den Transmittern und Receivern beliebige Attribute hinzuzufügen, die dann auch
von den Editoren unterstützt werden. Ein Transmitter Editor könnte dann Solo- und MuteButtons direkt im Timeline Fenster darstellen. Getrennte Methoden wie getName, setName,
getAnchor, setAnchor würden in diesem allgemeinen Attribute-System aufgelöst werden.
Von Beta-Testern ist der Wunsch geäußert worden, eine Input/Output Konfiguration für
die Audio-Hardware in Meloncillo vornehmen zu können. Das kollidiert zunächst mit der
Grundidee, daß das Programm nichts über konkrete Signalverarbeitung weiß. Eine Alternative
wären Preferences-Karten, die dynamisch von Scripts generiert werden. Wenn in einer der
nächsten Versionen die Anbindung an Max/MSP realisiert ist, müßten die Preferences nicht
innerhalb des Programmes erweitert, sondern lediglich ein zusätzliches Preferences-Script
angemeldet werden.
Die Hauptaufgabe wird jedoch sein, das Programm ausführlicher durch möglichst viele verschiedene Anwender in der Praxis zu erproben.
69
Literaturverzeichnis
[Chowning 1971]
John Chowning, The Simulation of Moving Sound Sources. Journal
of the AES Vol. 19, No. 1, Januar 1971 (Nachdruck in Computer
Music Journal Vol. 1 No. 3, Juni 1977, S. 48–52)
[Eimert/Humpert 1973]
Herbert Eimert / Hans Ulrich Humpert, Das Lexikon der elektronischen Musik (Artikel Raum“, Raumton“, Raumakustik“ und
”
”
”
Steuerung“). Regensburg 1973
”
Frank Gertig / Julia Gerlach / Golo Föllmer, Musik..., verwandelt
– Das Elektronische Studio der TU Berlin 1953–1995. Hofheim
1995
[Gertig et al. 1995]
[Gosling et al. 2000]
James Gosling / Bill Joy / Guy Steele / Gilad Bracha, The Java
Language Specification, 2nd Edition. Boston 2000. Online publiziert: http://java.sun.com/docs/books/jls/second_edition/
html/j.title.doc.html
[Haller 1995]
Hans Peter Haller, Das Experimentalstudio der Heinrich-StrobelStifung des Südwestfunks Freiburg 1971–1989 : Die Erforschung
der Elektronischen Klangumformung und ihre Geschichte (Band 1,
Zur Technik der Elektronischen Klangumformung). Baden-Baden
1995
[Hein 1999]
Folkmar Hein, Von der Quadrophonie zur Raumklangsteuerung –
Überlegungen zur Konzeption des neuen TU-Studios. In: Bernhard
Feiten / Folkmar Hein / Axel Röbel / Werner Schaller (Hrsg.),
Impulse und Antworten – Festschrift für Manfred Krause. Berlin
1999, S. 85–110
[Jot/Warusfel 1995]
Jean-Marc Jot / Olivier Warusfel, Spat˜ : A Spatial Processor for
Musicians and Sound Engineers. CIARM: International Conference
on Acoustics and Musical Research, Mai 1995
[Kleiner et al. 1993]
Mendel Kleiner / Bengt-Inge Dalenbäck / Peter Svensson, Auralization – An Overview. Journal of the AES Vol. 41, No. 11, November 1993, S. 861-875
[Lea 1997]
Doug Lea, Concurrent Programming in Java – Entwurfsprinzipien
und Muster. Bonn 1997
[Leahy 2004]
Michael Leahy, SCREAM – SuperCollider Resource for ElectroAcoustic Music. Online-Publikation 2004:
http://audio.egregious.net/scream/whitepapers/scream_
whitepaper.v1.1.1.pdf
70
Literaturverzeichnis
[Loy 1985]
Gareth Loy, SNDPATH. In: Computer Audio Research Laboratory
(CARL) Program Guide. La Jolla 1985
[Mayer 1995]
Otto Mayer, Programmieren in COMMON LISP. Heidelberg, 1995
[Malham 1998]
D. G. Malham, Spatial Hearing Mechanisms and Sound Reproduction. Online-Publikation 1998: http://www.york.ac.uk/
inst/mustech/3d_audio/ambis2.htm
[McCartney 1996]
James McCartney, SuperCollider: A New Real Time Synthesis Language. ICMC Paper 1996
[McCartney 2002]
James McCartney, Rethinking the Computer Music Language:
SuperCollider. In: Computer Music Journal Vol. 26, No. 4, Winter
2002, S. 61–68
[Momenti/Wessel 2003]
Ali Momenti / David Wessel, Characterizing and Controlling Musical Material Intuitively with Geometric Models. Proc. of the 2003
Conference on New Interfaces for Musical Expression (NIME-03),
Montreal, S. 54–62
[Moore 1983]
F. Richard Moore, A General Model for Spatial Processing of
Sounds. Computer Music Journal Vol. 7, No. 3, Herbst 1983,
S. 6–15
[Moore 1985]
F. Richard Moore, The CMusic Sound Synthesis Program. La Jolla
1985
[de la Motte-Haber 1996] Helga de la Motte-Haber (Red.), Klangkunst. Katalog von Sonambiente – Festival für Hören und Sehen. Hrsg. von der Akademie
der Künste, Berlin 1996
[de la Motte-Haber 1993] Helga de la Motte-Haber, Die Musik von Edgard Varèse. Hofheim
1993
[Mühlethaler/Schuppisser 2004] Christian Mühlethaler / Alexander Schuppisser, Sonificator
– A Java Framework for writing Applications that use SuperCollider as Sound-Engine. Vortrag auf der Linux Audio Developer
(LAD) Conference 2004. Online-Slides: http://www.linuxdj.
com/audio/lad/contrib/zkm_meeting_2004/slides/friday/
muehletaler+schuppisser-supercollider.pdf
[Pulkki 2001]
Ville Pulkki, Spatial Sound Generation and Perception by Amplitude Panning Techniques. Espoo, 2001
[Radtke 1988]
Torsten Radtke, Entwurf und Bau eines computergesteuerten 4Kanal-Mischers nach ARD-Pflichtenheft. Diplomarbeit TU Berlin
1988
[Ruschkowski 1998]
André Ruschkowski, Elektronische Klänge und musikalische Entdeckungen. Stuttgart 1988
[Schneider 1995]
Thomas Schneider, Programm zur Steuerung multipler Audiosignale zur Simulation räumlich bewegter Schallquellen. Magisterarbeit TU Berlin 1995
71
Literaturverzeichnis
[Seelig 1990]
Thomas Seelig, Entwicklung einer grafischen Benutzeroberfläche
für ein MIDI-gesteuertes quadrophones Mischpult. Magisterarbeit
TU Berlin 1990
[Stuart 1996]
J. Robert Stuart, The Psychoacoustics of Multichannel Audio. AES
UK Audio for New Media Conference, Paper ANM-12, 1996
[Supper 1997]
Martin Supper, Elektroakustische Musik und Computermusik:
Geschichte, Ästhetik, Methoden, Systemen. Darmstadt 1977
[de Vries/Boone 1999]
Diemer de Vries / Marinus M. Boone, Wave Field Synthesis and
Analysis Using Array Technology. Proc. IEEE Workshop on Appl.
of Signal Proc. to Audio and Acoustics, New Paltz, Oktober 1999
[Wishart 1994]
Trevor Wishart, Audible Design : A Plain and Easy Introduction
to Practical Sound Composition. York 1994
[Wright/Freed 1997]
Matthew Wright / Adrian Freed, Open SoundControl : A New
Protocol for Communicating with Sound Synthesizers. Proc. of
the 1997 Intl. Computer Music Conference (ICMC), Thessaloniki,
S. 101–104
[Wright et al. 2003]
Matthew Wright / Adrian Freed / Ali Momenti, OpenSound Control : State of the Art 2003. Proc. of the 2003 Conference on New
Interfaces for Musical Expression (NIME-03), Montreal, S. 153–159
[Zmölnig et al. 2003]
Johannes Zmölnig / Alois Sontacchi / Winfried Ritsch, The IEMCube : A Periphonic Re-/Production System. Proc. of the AES
24th Intl. Conference, 2003, S. 21–25
72
Anhang: Abbildungen, Quelltexte
Abbildungsverzeichnis
1.1
1.2
1.3
1.4
Σ 1 Oberfläche . . . . . . . . . . . . .
Panning Objekte in Digital Performer
VBAP Anwendung in Max/MSP . . .
Perzeptive Parameter in Spat˜ . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
14
17
18
3.1
3.2
Legende . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Session Struktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
29
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
Surface Fenster . . . . . . . . . . . . . . . .
Hilfspaletten . . . . . . . . . . . . . . . . .
Bézier-Kurve mit variabler Geschwindigkeit
Editor für SigmaReceiver . . . . . . . . . .
Matrix Meter . . . . . . . . . . . . . . . . .
Timeline Fenster . . . . . . . . . . . . . . .
Transport Palette . . . . . . . . . . . . . . .
Dezimation von Trajektorien . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
36
36
39
40
40
41
41
42
5.1
5.2
5.3
5.4
5.5
Plug-In Interfaces und Klassen . . . . . . . . . . . . . . . . . . . . . .
Plug-Ins zur Trajektorien-Filterung . . . . . . . . . . . . . . . . . . . .
RealtimeConsumer Profile . . . . . . . . . . . . . . . . . . . . . . . . .
Realtime Datenströme . . . . . . . . . . . . . . . . . . . . . . . . . . .
Nodes, Busse und Buffer für einen Amplituden-Mixer in SuperCollider
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
45
46
47
48
58
6.1
6.2
Erweiterter SuperCollider Synthesizer . . . . . . . . . . . . . . . . . . . . . .
Steuerelemente und Script Oberfläche für den erweiterten Synth . . . . . . .
65
66
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Quelltexte
3.1
3.2
3.3
3.4
4.1
4.2
4.3
5.1
5.2
XMLRepresentation.java (io package) . . . . . .
Receiver.java (receiver package) . . . . . . . . . .
Transmitter.java (transmitter package) . . . . . .
ReceiverCollectionListener.java (receiver package)
VirtualSurface.java (gui package) . . . . . . . . .
AbstractGeomTool.java (gui package) . . . . . .
TrackSpan.java (io package) . . . . . . . . . . . .
RenderPlugIn.java (render package) . . . . . . .
RenderConsumer.java (render package) . . . . . .
73
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
29
30
31
32
35
38
42
44
45
Quelltexte
5.3
5.4
5.5
6.1
6.2
6.3
RealtimeProducer.java
smooth.orc . . . . . .
synthdef-sources.sc . .
cillo-doppler.sc . . . .
cillo-distortion.sc . . .
cillo-echo.sc . . . . . .
(realtime package)
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
74
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
47
53
59
63
64
66