DOKUMENTATION Fachhochschule Wedel Praktikum Virtual Reality Sommersemester 2010 Thema: djBench Andreas Fischer (Matr.-Nr. 6380) Christoph Kipping (Matr.-Nr. 6086) Marcel Nüss (Matr.-Nr. 61 55) Philipp Zabel (Matr.-Nr. 3206)
Inhalt 1. Allgemeine Problemstellung ....................................................................................................................... 1 1.1 Einleitung ................................................................................................................................................. 1 1.2 Das „djBench“-Projekt ............................................................................................................................ 1 1.3 Zielgruppe ................................................................................................................................................ 1 2. Benutzerhandbuch ....................................................................................................................................3 2.1 djBench - die CoBench-App.....................................................................................................................3 2.1.1 Ablaufbedingungen ........................................................................................................................3 2.1.2 Programminstallation ....................................................................................................................4 2.1.3 Programmstart ..............................................................................................................................4 2.1.4 Bedienungsanleitung .....................................................................................................................4 2.1.4.1 Die Oberfläche .............................................................................................................................4 2.1.4.1.1 Konfigurations-Menü.............................................................................................................5 2.1.4.1.2 Hauptbildschirm....................................................................................................................6 2.1.4.2 Der Programmablauf ................................................................................................................ 10 2.1.4.2.1 Die Musikbibliothek wechseln.............................................................................................. 10 2.1.4.2.2 Eine Platte auflegen............................................................................................................. 11 2.1.4.2.3 Einen Übergang zwischen zwei Tracks erzeugen ................................................................. 11 2.1.4.2.4 Einen Effekt hinzufügen ....................................................................................................... 11 2.1.4.2.5 Die Slipmats tauschen ......................................................................................................... 11 2.1.5 Fehlermeldungen .......................................................................................................................... 11 2.1.5.1 Settings-Menü ........................................................................................................................... 11 2.1.5.2 Plattenkoffer ..............................................................................................................................12 2.1.5.3 Dateibrowser .............................................................................................................................12 2.1.6 Wiederanlaufbedingungen ............................................................................................................12 2.2 Lightshow - die CAVE-App .....................................................................................................................12 2.2.1 Ablaufbedingungen .......................................................................................................................12 2.2.2 Programminstallation ..................................................................................................................12 2.2.3 Programmstart ............................................................................................................................12 2.2.4 Bedienungsanleitung ...................................................................................................................13 2.2.5 Fehlermeldungen .........................................................................................................................15 2.2.6 Wiederanlaufbedingungen ...........................................................................................................15 3. Programmierhandbuch ........................................................................................................................... 16 3.1 Entwicklungskonfiguration ..................................................................................................................... 16 3.2 Problemanalyse..................................................................................................................................... 16 3.2.1 Benutzeroberfläche ..................................................................................................................... 16 3.2.2 Sound ......................................................................................................................................... 19 3.2.3 Lightshow ...................................................................................................................................20 3.3 Realisierung............................................................................................................................................21 3.3.1 Benutzeroberfläche ......................................................................................................................21 3.3.2 Sound .........................................................................................................................................29 3.3.3 Lightshow ....................................................................................................................................31 3.4. Beschreibung grundlegender Datenstrukturen .....................................................................................32 3.4.1 CoBench-App ..............................................................................................................................32 3.4.2 CAVE-App ...................................................................................................................................33 3.5 Programmorganisationsplan .................................................................................................................34 3.6 Programmtests .....................................................................................................................................35 I
ALLGEMEINE PROBLEMSTELLUNG
1. Allgemeine Problemstellung 1.1 Einleitung Bei dem vorliegenden Bericht handelt es sich um eine Dokumentation für die Software djBench, welche im Rahmen des Praktikum Virtual Reality 1 an der FH Wedel zum Wintersemester 2010 entstand. Die Dokumentation soll sowohl die Funktionsweise bzw. Bedienung der Anwendung verdeutlichen, als auch die bei der Umsetzung eingeflossenen Ideen und aufgetauchten Probleme aufzeigen. 1.2 Das „djBench“-Projekt Es soll eine Multitouch-Anwendung entstehen, die einem realen DJ-Set nachempfunden ist. Zusätzlich ist eine Lichtshow zu realisieren, die sich ebenfalls über die Multitouch-Applikation steuern lässt. Das DJ-Set besteht dabei aus zwei Plattenspielern, einem Audiomischpult und einem virtuellem Plattenkoffer. Wie in der Realität soll es möglich sein, Musikstücke aus dem Koffer zu wählen und diese dem jeweiligen Abspielgerät zuzuordnen. Die Plattenspieler erlauben dann das getrennte Starten und Stoppen des Tracks, das Setzen einer beliebigen Liedposition und das Anen der Abspiel-Geschwindigkeit. Anschließend lassen sich über das Mischpult für jeden Kanal (also für jeden Plattenspieler) spezifische Lautstärken und Effekte einstellen. Auch das Überblenden zwischen den Kanälen mit Hilfe eines Schiebereglers (Crossfader) gilt es umzusetzen. Da beim simultanen Mischen von Musikstücken eine Vorhörfunktion nahezu unerlässlich ist, soll es später auch möglich sein über eine „Cue“-Funktion beliebige Kanäle auf einen Kopfhörerausgang umzuleiten, um diese vorab synchron abmischen zu können. Die CoBench, eine Art „Computer-Werkbank“, die das Steuern einer Anwendung mit Hilfe von Multitouch erlaubt1, bietet im Zusammenspiel mit dem SDK (Vers. 1.1.585.5456) und der Tracking-Engine „EVOVIS“ der eyefactive GmbH eine gute Grundlage für eine derartige Anwendung. Eine Lichtshow soll das „Club-Gefühl“ für den Anwender noch steigern und dem „Virtual Reality“-Aspekt mehr Ausdruck verleihen. Diese wird dreidimensional in die CAVE, einem Würfel mit vier Projektionsflächen, der dem Betrachter dank „Shutter-Technik“ einen 3D-Eindruck vermittelt2, projiziert. Sie ist so zu realisieren, dass sie sich der gespielten Musik ant und mit Hilfe eines zusätzlichen s auf der CoBenchAnwendung über eine Netzwerkverbindung steuern lässt. Darüber hinaus ist es angedacht, die in die CAVE integrierte Bodenplatte über Filtern verschiedener Frequenzbereiche derart anzusteuern, dass der Bass für den Benutzer verstärkt und somit deutlicher wahrgenommen wird. Die vielen Konfigurationsmöglichkeiten verlangen ein Menü, über das sich z.B. die einzelnen Ausgabekanäle (Soundkarten/Stream) wählen lassen. Auch für die optional aktivierbare Lichtshow bedarf es einiger zur Laufzeit änderbarer Einstellungen wie dem Hinzufügen bzw. Entfernen des Steuer-s und dem Anen der IP-Adresse und des Lichtshow-Server-Ports. Optional könnte dieses Menü auch der Darstellung eines Dateibrowsers dienen, über den sich der MusikOrdner oder auch die Textur der „Slipmat“, also der Filzmatte auf einem der Plattenspieler, aussuchen lassen. 1.3 Zielgruppe In erster Linie ist die Software zu Präsentationszwecken gedacht. Sie soll die Möglichkeiten der modernen Computertechnik aufzeigen und z.B. auf Messen technikinteressierte Jugendliche für einen Informatik-Studiengang begeistern. Darüber hinaus soll es das CoBench-Programm jedoch auch einem „normalen“ DJ erlauben, mit Hilfe von Multitouch aufzulegen. Aus diesem Grund ist, ganz im Sinne der VR, unbedingt auf eine intuitive und realitätsnahe Abbildung des DJ-Equipments zu achten. 1 FH Wedel – Prof. Dr. Christian-A. Bohn: VR-Lab, Prof. Dr. Christian-A. Bohn, vers. 9. August 2010, 20. Dezember 2010
. 2 FH Wedel – Prof. Dr. Christian-A. Bohn: VR-Lab, Prof. Dr. Christian-A. Bohn, vers. 9. August 2010, 20. Dezember 2010
.
1
ALLGEMEINE PROBLEMSTELLUNG
Die CAVE-Anwendung muss voraussichtlich speziell auf die Gegebenheiten im VR-Labor der FH Wedel abgestimmt werden, weshalb ihr Einsatzbereich weitestgehend auf interne Veranstaltungen (z.B. Tag der offenen Tür) beschränkt sein wird.
2
BENUTZERHANDBUCH
2. Benutzerhandbuch Die djBench ist eine Multitouch-DJ-Simulation die es dem Anwender erlaubt, wie mit einem realen DJ-Set aufzulegen. Zusätzlich lässt sich mit der Software optional eine 3D-Lichtshow steuern. Auf den folgenden Seiten finden Sie alle notwendigen Informationen zu den Anwendungen, ihrer Installation und der Bedienung. Dabei unterscheidet dieses Handbuch zwischen der Multitouch-Applikation djBench für die CoBench auf der einen Seite und dem CAVE-Programm für die Lichtshow auf der anderen. 2.1 djBench - die CoBench-App 2.1.1 Ablaufbedingungen Damit Sie die djBench-Anwendung ausführen können, muss Ihr Multitouch-System folgende Anforderungen erfüllen: Mindestens: Hardware Prozessor:
Intel Pentium mit 2.4GHz oder kompatibel
Speicher:
2GB Arbeitsspeicher, sowie 200MB freier Festplattenspeicher
Grafik:
256MB Grafikkarte mit 3D-Beschleunigung, Projektor mit 1280 x 800 Pixeln (dann keine Lichtshow-Steuerung möglich)
Sound:
Eine Stereo-Soundkarte
Eingabegerät:
Standard-Tastatur (102 Tasten) und Maus zum Starten, Infrarot-Kameras (zur Steuerung der Anwendung per Multitouch)
Software Betriebssystem:
Linux: Ubuntu 9.10
Tracking-Software:
EVOVIS 1.0.918
Streaming-Server:
Icecast 2 in Verbindung mit Lame 3.98 (Encoding-Software)
Abhängigkeiten (Linux): Alle Abhängigkeiten, die vom eyefactive-SDK gefordert sind (install_dependencies.sh) Empfohlen: Hardware Prozessor:
Intel Pentium mit 2.7GHz oder kompatibel
Speicher:
4GB Arbeitsspeicher, sowie 300MB freier Festplattenspeicher
Grafik:
512MB Grafikkarte mit 3D-Beschleunigung, zwei Projektoren mit einer Auflösung von insgesamt 2048 x 768 Pixeln (Lichtshow-Steuerung damit möglich)
Sound:
Zwei Stereo-Soundkarten
Eingabegerät:
Standard-Tastatur (102 Tasten) und Maus zum Starten, Infrarot-Kameras (zur Steuerung der Anwendung per Multitouch)
Software Betriebssystem:
Linux: Ubuntu 9.10
Tracking-Software:
EVOVIS 1.0.918
Streaming-Server:
Icecast 2.3 in Verbindung mit Lame 3.98.4 (Encoding-Software)
Abhängigkeiten (Linux): Alle Abhängigkeiten, die vom eyefactive-SDK gefordert sind (install_dependencies.sh)
3
BENUTZERHANDBUCH
2.1.2 Programminstallation Vor der Installation von djBench müssen zunächst alle Quelldateien aus dem Subversion-Repository heruntergeladen werden. In dessen Wurzel-Verzeichnis befindet sich ein Shell-Skript mit dem Namen setup.sh, welches dafür sorgt, dass alle benötigten Bibliotheken in die dafür vorgesehenen Ordner entpackt. Da beide Anwendungen (CoBench und CAVE) aus dem gleichen Repository erzeugt werden, braucht dieser Schritt nur einmalig durchgeführt werden. Um eine ausführbare Datei des Programms zu erhalten, muss die Anwendung mit Hilfe des enthaltenen Makefiles kompiliert werden. Dazu genügt ein Aufruf von make -f djb_Makefile über eine Shell Konsole. Anschließend befindet sich im bin-Ordner die Datei, mit der die Applikation gestartet werden kann. 2.1.3 Programmstart Bevor Sie djBench starten, muss die Tracking-Engine EVOVIS aktiviert werden. Beim Starten auf einem System mit den Mindestanforderungen, sollte EVOVIS mit Hilfe des taskset-Befehls3 fest an den ersten verfügbaren Prozessor gebunden werden. Andernfalls kann es beim Verwenden der djBench zu Tonaussetzern oder Grafikfehlern kommen. Wenn Sie bereits im Vorfeld wissen, das Sie als Ausgabekanal einen Stream nutzen möchten (z.B. wenn Sie die djBench zusammen mit der Lichtshow in der CAVE betreiben wollen), muss vor Programmstart auch ein Icecast-Server gestartet werden. Hierfür nutzen Sie bitte die Icecast-Konfigurationsdatei icecast_djBench.xml aus dem Ordner bin/djBench/ des Installationspfades. Standardmäßig sind die Einstellungen so vorkonfiguriert, dass sich die Anwendung bei Bedarf mit einem lokal gestarteten Icecast-Server (IP-Adresse: 127.0.0.1 Port: 8000) verbindet. Alternativ können sie den Server auch auf einem externen System starten und über das Netzwerk eine Verbindung aufbauen. Hierzu müssen Sie lediglich mit Hilfe eines Editors in der Datei settings_djBench.ini im Ordner bin/djBench/data/ (Installationspfad) die Einträge shoutcastSource und shoutcastListener anen. Weitere Einstellungsmöglichkeiten sind in der Datei dokumentiert. Beachten sie bitte, dass Änderungen in der Icecast-Konfigurationsdatei (z.B. das Umstellen der Portnummern) in jedem Fall eine Anung der INI-Datei nach sich ziehen! Anschließend starten Sie die djBench-Anwendung, indem Sie das Shell-Skript djBench_gamemode.sh bzw. djBench_gamemode_taskset.sh im Ordner bin/djBench/ ausführen. Im ersten Fall wird die Software „normal“ gestartet, sodass das Betriebssystem die Verteilung der Prozesse auf die verschiedenen Us vornimmt. Diese Variante ist für Systeme gedacht, die den empfohlenen Hardware-Anforderungen entsprechen. Das zweite Shell-Skript bindet das Programm fest an den zweiten Prozessor. Wenn Sie EVOVIS, wie bereits im ersten Absatz dieses Kapitels beschrieben, fest an den ersten Prozessor gebunden haben, sollten Sie zum Starten der Anwendung dieses Skript benutzen. Somit ist gewährleistet, dass sich die ressourcenhungrige Tracking-Software und die DJ-Simulation gegenseitig nicht negativ beeinflussen und es zu keinen Soundoder Grafikfehlern kommt. 2.1.4 Bedienungsanleitung In diesem Kapitel wird Ihnen anschaulich der Umgang mit der djBench sowie den enthaltenen Funktionen und Einstellungsmöglichkeiten erklärt. 2.1.4.1 Die Oberfläche Unmittelbar nach Programmstart erscheint der Hauptbildschirm des Programms mit dem Konfigurationsmenü im Vordergrund. Die folgenden Unterabschnitte bringen Ihnen die Oberfläche näher und zeigen Ihnen, wo Sie welche Funktionalität finden.
3 taskset(1) - Linux man page, Robert M. Love, 27.02.2011
.
4
BENUTZERHANDBUCH
2.1.4.1.1 Konfigurations-Menü
Abbildung 2a: Settings-Menü mit Hauptfenster im Hintergrund.
Im Konfigurations-Menü können Sie die Ausgabegeräte für den Ton wählen und eine Verbindung zur CAVE herstellen, um zusätzlich ein Steuerpult für die Lichtshow zu aktivieren. Es erscheint beim Programmstart, lässt sich jedoch auch zu einem später jederzeit über den „Settings“-Button im Hauptfenster (siehe Pkt. 2.1.4.1.2) öffnen. Die Optionen für die Soundausgabe (Dialoggruppe „Sound“) erscheinen beim berühren des Eingabefeldes als Dropdown-Menü. Der „Master Output“ bezeichnet dabei den Haupt-Ausgabekanal, also den Ton, der nach dem Mixen und Belegen mit Effekten ausgegeben wird. Wenn Sie die Option „Streaming-Server“ wählen, stellen Sie bitte im Vorfeld sicher, dass ein Icecast-Server gestartet und alle Voreinstellungen hierfür korrekt getroffen wurden. Über den „Cue Output“ lässt sich zusätzlich ein Ausgabegerät für das „Vorhören“ wählen. Wenn Sie die Steuerung der Lichtshow (Dialoggruppe „Lightshow“) aktivieren möchten (durch Berühren des Eingabefeldes „Enable“ einen Haken setzen), sind zuvor die CAVE-Applikation zu starten (siehe dazu: 2.2.3) und als „Master Output“ (unter „Sound“) die Option „Streaming-Server“ zu wählen. Im Feld „IP-Adress“ und „Port“ müssen die IP-Adresse und der Port der CAVE angegeben werden, auf der die Lichtshow läuft. Hier erscheint jeweils eine virtuelle Tastatur beim Berühren des Feldes, die die Eingabe der gewünschten Werte erlaubt. Sollten entweder das Lichtshow-Programm noch nicht gestartet worden oder die IP- bzw. PortEinstellung fehlerhaft sein, erscheint beim Bestätigen des Dialogs mit „OK“ eine Fehlermeldung im unteren Fensterbereich.
5
BENUTZERHANDBUCH
2.1.4.1.2 Hauptbildschirm
Abbildung 2b: Das Hauptfenster mit aktiviertem Lichtmischpult.
Auf dem Hauptbildschirm befinden sich alle für das Auflegen benötigten Geräte, also zwei virtuelle Plattenspieler, ein Mixer und ein virtueller Plattenkoffer. Optional können Sie über das Konfigurations-Menü zusätzlich ein Lichtmischpult aktivieren (s.o.). Zwei Buttons erlauben sowohl das Anzeigen des Konfigurationsmenüs („Settings“), als auch das Festsetzen bzw. Lösen der Gerätepositionen („Positions“). Erscheint das Schloss-Icon auf dem „Positions“-Knopf geschlossen und rot gefärbt, sind die Geräte an ihrer aktuellen Position fixiert. Ist es hingegen geöffnet und grün, können sie an bestimmten Punkten mit den Fingern angefasst und beliebig auf der Oberfläche verschoben werden. Der Plattenkoffer
Abbildung 2c: Die virtuelle Plattenkiste.
Ähnlich wie beim von Apple-Produkten bekannten „Cover Flow“4 stehen auch auf der djBench die einzelnen Stücke der Musik-Bibliothek zur Verfügung. Wahlweise kann man hier über das Wischen mit einem einzelnen Finger über den Cover-Bereich (Abb. 2c, Nr.1) oder das Verschieben des Scroll-Balken (Abb. 2c, Nr. 2) durch die Musik-Bibliothek navigieren. Zur besseren Orientierung werden in der Statusleiste (Abb. 2c, Nr. 3) außerdem der Titel des Songs, der Künstler und der Albumname des hervorgehobenen Musikstücks (in der Mitte des Cover-Bereichs) angezeigt. Das betätigen des Buttons „Change Folder“ im oberen, rechten Bereich des Plattenkoffers öffnet das Menü 4 Cover Flow – Wikipedia, vers. 5. Oktober 2010, 26.02.2011
.
6
BENUTZERHANDBUCH
für die Auswahl des Musikordners (siehe Punkt 2.1.4.1.3), dessen Inhalt zur Verfügung gestellt werden soll. Der Knopf „Reload Library“ neben der Statusleiste erlaubt das Leeren des Bibliothek-Caches und neu-laden des kompletten Ordner-Inhalts. Diese Option ist vor allen Dingen dann wichtig, wenn neue MP3-Dateien in einen Ordner kopiert wurden und diese noch nicht im Cache enthalten sind bzw. in der Bibliothek angezeigt werden. Die Plattenspieler
Abbildung 2d: Der Plattenspieler mit aufgelegtem Musikstück.
Von der Gestaltung der Oberfläche ähnelt der Plattenspieler sehr seinem realen Pendant. Um ihn zu starten, muss der „Start/Stop“-Schalter (Abb. 2d, Nr. 1) betätigt werden. Ist zusätzlich eine Platte aus dem Plattenkoffer aufgelegt (Beschreibung siehe Kapitel 2.1.4.2.2), lässt sich der Tonarm (Abb. 2d, Nr. 2) per „Drag & Drop“ mit dem Finger an die gewünschte Liedposition bewegen, wobei der Lied-Anfang außen und das Lied-Ende innen liegen. Alternativ können Sie die Position auch über den Scroll-Balken im Track-Display (Abb. 2d, Nr. 3) setzen. Außerdem werden in dieser Anzeige noch das Coverbild, der Song- und Künstler-Name, sowie die aktuell verstrichene und die verbleibende Track-Zeit des spielenden Liedes dargestellt. Zur Anung der Abspielgeschwindigkeit dient der Pitch-Regler (Abb. 2d, Nr. 4). Den aktuellen Pitch-Wert können Sie vom LC-Display (Abb. 2d, Nr. 5) ablesen und über die nebenstehenden Plus-/Minustasten feinjustieren. Der Plattenteller ist komplett beweglich und erlaubt somit zusätzlich ein Anschieben Abbremsen und „Scratchen“ der Platte. Beim Berühren mit zwei gespreizten Fingern, wird der Teller leicht um einen konstanten Wert (1,5%) gebremst, was das Anen zweier parallel laufender Tracks vereinfacht. Rechts neben dem Track-Display befinden sich schließlich noch zwei Buttons (Abb. 2d, Nr. 6). Der Linke öffnet mit einem Touch das Slipmat-Auswahlmenü (siehe Punkt 2.1.4.1.3) über das Sie eine eigene Hintergrund-Textur für den Plattenteller wählen können. Der rechte Eject-Knopf entfernt, ähnlich wie bei einem CD-Player, die aufgelegte Platte vom Spieler und stoppt den Drehteller.
7
BENUTZERHANDBUCH
Der Mixer
Abbildung 2e: Das 2-Kanal-Mischpult.
Der Mixer stellt das Herzstück der djBench dar. Mit ihm kann der komplette Ton bearbeitet und anget werden. Neben der getrennten Lautstärkeregelung für jeden Kanal und einem Crossfader, stehen zusätzlich eine Effekt-Einheit und eine separate Vorhör-Regelung für den Kopfhörerausgang zur Verfügung. Der Master Output lässt sich mittels zweier Drehregler, „Balance“ und „Level“, in seiner räumlichen Verteilung (links/rechts) und seiner Intensität anen (Abb. 2e, Nr. 1). Eine Bargraph-Anzeige der dB-Werte hilft Ihnen außerdem bei der korrekten Justierung. Für jeden Plattenspieler stehen eine Gruppe von Dreh- und Schiebereglern, sowie ein „Cue“-Knopf zur Verfügung (Abb. 2e, Nr. 2). Dem bei Programmstart linken Plattenspieler ist dabei der Kanal mit der „1“ zugeordnet und dem Rechten der Kanal „2“. Über die Schieberegler lässt sich intuitiv die jeweilige Kanal-Lautstärke wählen und mit der dB-Anzeige überprüfen. Ein Drehen der Knöpfe mit den Bezeichnungen „Hi“, „Mid“ und „Low“ verändert den entsprechenden Bereich des Frequenzbandes, sodass sich beispielsweise Bässe verstärken lassen. Bei besonders leise oder laut aufgenommenen Musikstücken hilft der „Gain“-Regler und hebt bzw. senkt die Lautstärke des Tracks auf ein erträgliches Niveau. Durch aktivieren des „Cue“-Knopfes wird der dazugehörige Kanal zusätzlich auf den Cue Output gelegt und kann mit dem Kopfhörer vorgehört werden. Um zwischen den beiden Kanälen hin und her zu blenden, muss der „Crossfader“ (Abb. 2e, Nr. 3) entweder nach links (Kanal 1) oder rechts (Kanal 2) verschoben werden. Über den „Mixing“-Drehknopf im „Phones“-Bereich (Abb. 2e, Nr. 4) können Sie, ähnlich wie beim Crossfader, zwischen dem Cue Output und dem Master Output umschalten, sofern der „Cue“-Button aktiviert ist. Der gemixte Ton ist dann ausschließlich über den Vorhör-Kanal, also in der Regel über an die Cue Soundkarte angeschlossene Kopfhörer, zu hören. Auch die Lautstärke für den Cue Ausgang lässt sich über „Level“ separat anen. Die Effekt-Einheit (Abb. 2e, Nr. 5) bietet Ihnen eine weitere Möglichkeit den Sound aktiv zu verändern. Hierfür stehen zwei Effekte zur Verfügung, ein „Echo“ (Button Nr. 1) und ein sogenannter „Flanger“ (Button Nr. 2), zwischen denen Sie per Knopfdruck wählen können. Zusätzlich sind diese Effekte über die Drehknöpfe „Time“ und „Depth“ veränderbar. Über „Time“ stellen Sie die Millisekunden ein, um die der Effekt verschoben wirkt. Den aktuellen Wert können Sie im Display über den Effekt-Auswahl-Buttons ablesen. Mit „Depth“ lässt sich die Stärke beeinflussen. „Dry“ bedeutet dabei wenig hörbar und „Wet“ beschreibt einen deutlich wahrnehmbaren Effekt. Der gewählte Effekt lässt sich dann bei Bedarf über den „Effect On/Off“-Schalter zuschalten. Ist er eingeschaltet, leuchtet der Knopf gelblich.
8
BENUTZERHANDBUCH
Das Lightshow-Pult
Abbildung 2f: Das Lichtmischpult.
Wenn Sie die djBench zusammen mit der CAVE-Lichtshow betreiben, können Sie diese über das LightshowPult steuern. Die Lichtshow beinhaltet in der Regel mehrere Visualisierungen, zwischen denen Sie mit Hilfe der Pfeiltasten im Display (Abb. 2f, Nr. 1) hin- und herschalten können. Die aktuell gewählte Visualisierung erscheint jeweils im Display, links neben den Pfeiltasten. Zusätzlich befinden sich in der unteren Reihe des Displays anschaulich die Zahlenwerte der darunter liegenden Schieberegler. Im Feld „Light-Color“ (Abb. 2f, Nr. 2) finden Sie verschiedenfarbige Schalter mit eine Färbung für die Visualisierung ausgewählt werden kann. Der Knopf „Shuffle“ (weiß) bedeutet, dass die Färbung sich in regelmäßigen Abständen automatisch ändert. Vier Slider unterhalb der Lichtfarbe (Abb 2f, Nr. 3) ermöglichen eine weitere Konfiguration der Show. Ist als Lichtfarbe „Shuffle“ gewählt, beeinflussen „Fading“ die Überblendzeit zwischen den verschiedenen Farben und „Pause“ die Zeit zwischen den Überblendungen. Im Display erscheint die jeweilige Zeit in Millisekunden. „Lucency“ steht für den prozentualen Grad der Transparenz der erscheinenden Objekte. Außerdem bieten einige Visualisierungen die Möglichkeit, einen weiteren Parameter zu beeinflussen (z.B. die Detailgenauigkeit einer Kugeldarstellung). Hierfür ist der „Custom“-Regler gedacht, der in diesem Fall entsperrt wird und über den Sie dann einen Prozentwert einstellen können.
9
BENUTZERHANDBUCH
Der Dateibrowser
Abbildung 2g: Der Dateibrowser für die Musikordner-Auswahl.
Den Dateibrowser erreichen Sie entweder beim Wechseln des Musikordners oder bei der Auswahl einer Slipmat-Textur. Da er in beiden Fällen gleich funktioniert, wird hier exemplarisch die Musikordner-Auswahl beschrieben. Nach dem Öffnen des Menüfensters erscheint der Browser in Form einer Dialoggruppe. In der Überschrift werden (maximal) die letzten drei Ordner des aktuellen Pfades und das „Ordner aufwärts“-Symbol abgebildet, wobei der gewählte Ordner hellgrau erscheint (Abb. 2g, Nr. 1). Durch Berühren eines der Pfadelemente wechseln Sie in diesen Ordner. Die Unterordner des aktuellen Pfades werden im Bereich „Browse Folder“ (Abb. 2g, Nr. 2) dargestellt. Wenn Sie in der Ordnerstruktur eine Ebene tiefer gehen möchten, können Sie hier den entsprechenden Ordner wählen. Die Ansicht aktualisiert sich unmittelbar nach Ihrer Wahl. Sollten mehr Objekte im Ordner enthalten sein als die Auswahlbox Platz bietet, können Sie durch Wischen über den dunkelgrauen, mit Pfeilen markierten Bereich hoch- und runter-scrollen. Im „Select“-Bereich (Abb. 2g, Nr. 3) erscheinen alle auswählbaren Objekte. Beim Musik-Ordner-Auswahlmenü sind es Dateiordner, im Falle des Slipmat-Menüs eine Reihe von Bilddateien. Auch diese Liste ist scrollbar. Wenn Sie das gewünschte Objekt gefunden haben, ist dieses über einen Touch selektierbar. Der Hintergrund eines selektierten Objekts verfärbt sich dunkelgrau. Durch Bestätigen Ihrer Auswahl mit „Ok“ wird diese übernommen und das Menüfenster wird geschlossen. 2.1.4.2 Der Programmablauf Nach Konfiguration des „Settings“-Menüs zu Programmstart ist die djBench einsatzbereit. In diesem Abschnitt werden einige Situationen beschrieben, die Ihnen den Einstieg in die Verwendung der Software erleichtern sollen. 2.1.4.2.1 Die Musikbibliothek wechseln Im Plattenkoffer werden stets alle der im gewählten Ordner und seinen Unterordnern enthaltenen MP3-Dateien angezeigt. Um einen neuen Ordner als Bibliothek zu laden, müssen Sie den Button „Change Folder“ im Plattenkoffer berühren und im Dateibrowser einen neuen Ordner auswählen.
10
BENUTZERHANDBUCH
2.1.4.2.2 Eine Platte auflegen Wählen Sie bitte zunächst den gewünschten Musiktitel im Plattenkoffer aus. Anschließend müssen Sie das Cover des Tracks mit zwei gespreizten Fingern berühren und die erscheinende Kopie des Coverbilds auf den gewünschten Plattenspieler ziehen. Beim Loslassen verschwindet das Coverbild und die Platte wird aufgelegt. 2.1.4.2.3 Einen Übergang zwischen zwei Tracks erzeugen Legen sie die beiden Musikstücke auf je einen Plattenspieler auf. Den Crossfader verschieben Sie anschließend in die Richtung des zuerst abzuspielenden Liedes. Starten Sie beide Musikstücke und schieben Sie den Lautstärkeregler des ersten Stücks hoch. Der Titel ist über den Master Output zu hören. Anschließend schieben Sie entsprechend den Regler des zweiten Kanals hoch und aktivieren seinen „Cue“. Dieser Track ist dann einzig über den „Cue“-Ausgang, also in der Regel per Kopfhörer, zu hören. Wenn Sie nun auch den „Cue“-Button des Kopfhörer-Ausgangs aktivieren, hören Sie den auf dem Master-Ausgang liegenden ersten Titel parallel im Kopfhörer. Jetzt haben Sie die Möglichkeit den zweiten Titel (z.B. in seiner Geschwindigkeit) auf den Ersten abzustimmen. Anschließend können Sie mit dem Crossfader zum anderen Kanal überblenden. 2.1.4.2.4 Einen Effekt hinzufügen Um einen Effekt auf den Master Output zu legen, wählen Sie diesen bitte zunächst aus und konfigurieren ihn über die Drehknöpfe der Effekt-Einheit. Danach lässt sich der eingestellte Effekt jederzeit über die „Effect On/ Off“-Taste zuschalten. 2.1.4.2.5 Die Slipmats tauschen Über das „Slipmat wechseln“-Symbol des entsprechenden Plattenspielers gelangen Sie zum Dateibrowser. Hier können Sie durch Ihr Dateisystem browsen und die gewünschte Grafikdatei auswählen. Nach der Bestätigung mit „Ok“ wird die Textur auf den Plattenspieler geladen. 2.1.5 Fehlermeldungen Bei der Ausführung des Programms kann es zu Fehlern bei der Bedienung kommen. In den folgenden Listen finden Sie alle möglichen auftretenden Fehler mit Erklärung und entsprechenden Lösungsvorschlägen. Die Listen sind nach Erscheinungsort gegliedert. 2.1.5.1 Settings-Menü Fehlermeldung
Bedeutung
Lösung
Select StreamingServer as Master!
Die Lichtshow wurde aktiviert aber als Master Output wurde kein Stream gewählt.
Da die Lichtshow als Eingangssignal einen Stream benötigt, müssen Sie einen Streaming-Server starten und diesen als Master Output wählen.
Please start StreamingServer first!
Es konnte keine Verbindung zum in der „settings_djBench.ini“ angegebenen Server aufgebaut werden, da dieser entweder nicht gestartet wurde oder falsch konfiguriert wurde.
Icecast starten bzw. die Einstellungen in der „settings_djBench.ini“ (im Unterordner bin/data/) und „icecast_djBench.xml“ (im Ordner bin/djBench/icecast/) korrigieren.
Display too small!
Lichtshow soll aktiviert werden, aber es ist nicht genug Platz auf Bildschirm, um das Steuerpult anzeigen zu lassen.
Anwendung ohne Lichtshow oder auf einem Device mit höherer Auflösung starten.
Could not connect to Cave!
Lichtshow-Steuerung soll aktiviert IP-Adresse und Port korrigieren bzw. werden, aber es konnte keine Verbin- Lichtshow-Applikation auf der CAVE stardung zur CAVE aufgebaut werden. ten.
Device could not be found!
Fehler bei der Auswahl der Soundkarte.
Falls z.B. eine USB-Soundkarte nach dem Programmstart entfernt wurde, die Software neustarten. 11
BENUTZERHANDBUCH
2.1.5.2 Plattenkoffer Fehlermeldung
Bedeutung
Lösung
No Library could be found!
In dem eingestellten Musikordner wurde keine Musik gefunden.
Über „Change Folder“ kann im Dateibrowser ein anderer Musikordner gewählt werden.
Fehlermeldung
Bedeutung
Lösung
Please select a file.
Im „Select“-Feld wurde noch keine gültige Datei gewählt.
Eine im Select-Feld angezeigte Datei wählen und mit „Ok“ bestätigen.
2.1.5.3 Dateibrowser
Please select a folder. Im „Select“-Feld wurde noch kein gültiger Ordner gewählt.
Einen im Select-Feld angezeigten Ordner wählen und mit „Ok“ bestätigen.
2.1.6 Wiederanlaufbedingungen Im Falle eines unplanmäßigen Programmabbruchs (z.B. durch Stromausfall oder Systemfehler) gehen sowohl die Daten über den derzeit geladenen Musikordner, als auch alle aktuellen Einstellungen auf dem Mischpult, den Plattenspielern und im „Settings“-Menü verloren. Sobald Ihr System wieder ordnungsgemäß arbeitet, kann auch die djBench wie gewohnt ausgeführt werden. 2.2 Lightshow - die CAVE-App 2.2.1 Ablaufbedingungen Für die Lighshow wird eine spezielle Umgebung benötigt, die die Bilder der Anwendung dreidimensional darstellen kann. Das CAVE-System der Fachhochschule Wedel bietet hierfür ein geeignetes Framework, um möglichst einfach mehrdimensionale Anwendungen zu entwickeln. Die CAVE besteht aus mehreren einzelnen Rechnern ist nach außen als geschlossenes System mit dem Netzwerk verbunden. Um die Software zu starten wird deshalb zusätzlich eine SSH-Verbindung von einem beliebigen Computer aus benötigt. Unabhängig davon gelten folgende Anforderungen an die verwendete Hard- bzw. Software: Hardware Eingabegeräte:
Tracking-Kameras zur Bestimmung des Ortes des Benutzers (optional)
Sound:
Mindestens 2 Lautsprecher, empfohlen wird eine 5.1 Soundanlage
Software Abhängigkeiten (Linux): Boost (vers. 1.38) - für Netzwerk-Kommunikation 2.2.2 Programminstallation Um eine ausführbare Datei des Programms zu erhalten, muss die Anwendung mit Hilfe des enthaltenen Makefiles kompiliert werden. Dazu genügt ein Aufruf von make release über eine Shell Konsole. Anschließend befindet sich im bin-Ordner die Datei, mit der die Applikation gestartet werden kann. Soll das Verzeichnis nach dem Kompiliervorgang bereinigt werden, ist make clean der entsprechende Befehl. Neben der ausführbaren Datei im bin-Ordner existiert ein Shell-Skript zum Starten, das einige Einstellungen automatisch vornimmt. 2.2.3 Programmstart Bevor das Programm gestartet werden kann, muss zuerst die CAVE vorbereitet werden. Dazu gehört, dass die dazugehörigen Computer gestartet und die Projektoren eingeschaltet sind. Dies wird hier nicht weiter erläutert. Für nähere Informationen befindet sich eine Anleitung auf dem Handout-Server der FH Wedel (Ordner: https://stud.fh-wedel.de/handout/Egge/VR/). Optional können noch die Tracking-Kameras gestartet werden. 12
BENUTZERHANDBUCH
Da die Anwendung Musik-Daten benötigt, um ein vernünftiges Bild zu erzeugen, verbindet sie sich nach dem Starten mit einem Streaming-Server. Deshalb sollte vorher eingestellt werden, wie die IP dieses Servers ist und ob ein Proxy verwendet wird. Dafür müssen die Adressen in einer INI-Datei stehen, die als erster Parameter in das Programm gegeben wird. Wenn die Lichtshow zusammen mit djBench benutzt wird, muss außerdem die IP des Streaming-Servers, der die Daten der CoBench empfängt, angegeben werden. Mit folgenden Zeilen wird der Server konfiguriert: 01 [DJBENCH] 02 ; URI des Streaming Servers 03 CAST_SERVER_URI = http://127.0.0.1:8001/stream.m3u 04 ; Proxy-Server verwenden? (leer lassen, falls kein Proxy verwendet werden soll) 05 ; Beispiel: http://cwlan-cache.fh-wedel.de:3128 06 PROXY =
Für das CAVE-Framework sind zusätzliche Einstellungen notwendig. Dafür gibt es vorgefertigte INI-Dateien, die sich im Verzeichnis bin/djBenchVisualizer/res befinden. Dort stehen die obigen Zeilen bereits drin. Wird zum Starten die start_stereo.sh verwendet, wird die 4Screens_iveStereo_chromium_fullscreen.ini benutzt. Zum Testen des Programms auf einem normalen PC gibt es die start.sh, die alle vier Bilder der Projektoren in einem Fenster darstellt. Sobald die Verbindung mit dem Streaming-Server hergestellt wurde, steht in der Konsole die Zeile Create Mixer... done!. Nun können Befehle wie das Wechseln der Visualisierung ausgeführt werden. Die CoBench-Anwendung kann sich zudem nun verbinden und die Steuerung übernehmen. 2.2.4 Bedienungsanleitung Bei der Anwendung handelt es sich um ein Konsolen-Programm, weshalb es keine grafische Oberfläche zur Verfügung stellt, mit der Aktionen durchgeführt werden können. Aber es ist möglich die Visualisierungen über das Netzwerk zu steuern. Das CoBench-Programm nutzt diese Schnittstelle, um die Lichtshow zu beeinflussen. Nachdem die CAVE-Applikation gestartet wurde und mit einem Streaming-Server verbunden ist, können Kommandos gesendet werden. Folgende Befehle sind möglich: • Wechseln zur vorherigen bzw. nächsten Visualisierung (insgesamt vier mögliche Visualisierungen) • Setzen einer bestimmten Farbe oder des automatischen Farbwechsels • Den Zeitabstand zwischen zwei Visualisierungen und zwischen zwei konfigurieren • Die Transparenz der Visualisierung einstellen • Einen von der aktuellen Visualisierung beliebig genutzten Wert verändern Wird die CoBench-Anwendung verwendet, muss das Lichtshow-Modul in den Einstellungen aktiviert werden. Anschließend stehen einige Knöpfe und Regler mit den oben beschriebenen Funktionen zur Verfügung. Nähere Informationen hierzu befinden sich im Abschnitt 1.2.4.
13
BENUTZERHANDBUCH
Visualisierungen Towers
Abbildung 2h: Towers-Visualisierung.
In einer matrixförmigen Anordnung in der Größe 5x5 sind quadratische Blöcke auf dem Boden zu sehen. Die Höhe der Balken t sich den Frequenzen der Musik an, wobei in der Mitte die tiefen und nach außen hin die höheren Töne visualisiert werden. Der „Custom“-Wert kann nicht genutzt werden. Hurricane
Abbildung 2i: Hurricane-Visualisierung.
In dieser zweiten Visualisierung wurde ein Partikelsystem zur Hilfe genommen, um kleine Kugeln vom Boden aus in die Höhe zu „schießen“. Sie starten alle an der gleichen Position und zerstreuen sich je nach Frequenzausschlag kreisförmig nach außen. Es können keine Veränderungen über den „Custom“-Wert vorgenommen werden. Sphere
Abbildung 2j: Sphere-Visualisierung.
Bei „Sphere“ handelt es sich um eine relativ einfache Visualisierung. Sie besteht lediglich aus einem Ball, dessen Größe sich nach der mittleren Frequenz richtet. Über den „Custom“-Wert ist es möglich, die Genauigkeit der Rundung anzuen. Ist der Wert niedrig, so wird die Kugel eckiger und im Minimun ein Tetraeder. Je größer der Wert ist desto glatter wird der Ball.
14
BENUTZERHANDBUCH
Wave
Abbildung 2k: Wave-Visualisierung.
Wie der Name bereits verrät, ist bei „Wave“ eine Art Welle dargestellt. Diese kommt dem Benutzer quasi entgegen und besteht aus mehreren horizontalen Linien. Auf ihnen sind die aktuellen Frequenzen von links nach rechts in tief bis hoch abgebildet. Der „Custom“-Wert ist deaktiviert. 2.2.5 Fehlermeldungen Fehlermeldung
Bedeutung
Lösung
BASS_Init failed
Der Ton konnte nicht ordnungsgemäß BASS_Init übernimmt das Verbinden mit gestartet werden. der Soundkarte und konnte dies nicht durchführen. Eventuell ist die Soundkarte von einem anderen Programm belegt. Bitte überprüfen Sie dieses und beenden gegebenenfalls die andere Anwendung. Für nähere Informationen kann der mitgelieferte BASS-Fehler-Code herangezogen werden.
Connection to streaming server failed
Die Anwendung konnte keine VerbinBitte überprüfen Sie die IP in der INI-Datei. dung zum Streaming-Server herstellen. Möglicherweise liegt ein Schreibfehler vor. Unter Umständen ist auch ein ProxyServer notwendig, der ebenfalls in der INI-Datei eingestellt werden kann. Ansonsten kann für nähere Informationen der mitgelieferte BASS-Fehler-Code benutzt werden.
Could not create Mixer
Der Mixer-Kanal zur Erzeugung des 5.1-Sounds konnte nicht erstellt werden.
Möglicherweise liefert der Streaming-Server ungültige Audio-Daten oder das Format der Daten kann von der Anwendung nicht verarbeitet werden. Bitte versuchen Sie es mit einem anderen Streaming-Server.
No sound data available
Es ist kein Ton zum Abspielen vorhanden.
Die Sound-Kanäle wurden nicht ordnungsgemäß initialisiert. Bitte starten Sie die Anwendung neu.
Could not play sound
Der Ton kann nicht abgespielt werden.
Der Streaming-Server liefert Audio-Daten, die nicht von der Anwendung verarbeitet werden können.
2.2.6 Wiederanlaufbedingungen Nach einem Absturz der Anwendung kann sie ohne Probleme neugestartet werden. Die Einstellung, welche Visualisierung gerade aktiv war und die anderen Konfigurationswerte gehen allerdings verloren.
15
PROGRAMMIERHANDBUCH
3. Programmierhandbuch Das Programmierhandbuch enthält neben den Informationen zu der bei der Entwicklung eingesetzten Hardund Software vor allen Dingen eine Analyse der Problemstellung und die daraus resultierenden Ideen und Lösungen für die Umsetzung. 3.1 Entwicklungskonfiguration Die Computersysteme und Komponenten mit deren Hilfe die Software entwickelt wurde kann in vielerlei Hinsicht von Interesse sein und wird deswegen in diesem Kapitel aufgeführt. Die für die Entwicklung relevante Hardwareumgebungen waren zum Einen die Rechner des VR-Labors, auf denen die Hauptentwicklung der Software stattfand und zum Anderen die CoBench von Eyefactive. Im folgenden ist die Konfiguration der jeweiligen Systeme aufgeführt. VR-Rechner: Prozessor:
Intel® Core™ i5 750, 2.67GHz
Arbeitsspeicher:
2GB
Grafikkarte:
Nvidia GeForce GTX 275
Soundkarte:
HDA Intel (STAC92xx)
Betriebssystem:
Linux – Ubuntu 9.10
CoBench: Prozessor:
Intel® Core™ 6600, 2.4GHz
Arbeitsspeicher:
2GB
Grafikkarte:
Nvidia GeForce 8800 GTS
Soundkarten (extern):
Delock USB Sound Box 7.1, Speedlink USB 2.0 Mini-Soundkarte
Betriebssystem:
Linux – Ubuntu 9.10
3.2 Problemanalyse Einer der wichtigsten Aspekte bei der Umsetzung des gewählten Projekts ist die möglichst realitätsnahe Abbildung des DJ-Sets mitsamt Tanzfläche in die virtuelle Realität. Dieser Abschnitt befasst sich daher exemplarisch mit einigen der nachzubildenden Geräte bzw. Objekte sowie den daraus resultierenden Problemstellungen und diskutiert mögliche Ansätze hinsichtlich der Umsetzung. Bei der CoBench-Anwendung gilt es möglichst viele der bereits im Multitouch-SDK implementierten und getesteten Funktionalitäten zu nutzen und sie bei Bedarf um eigene zu erweitern. Unter diesem Gesichtspunkt wird an einigen Stellen bereits in der Analyse auf das SDK verwiesen. 3.2.1 Benutzeroberfläche Als wesentliche Vorlage für die Programm-Oberfläche dient ein Auflege-Set, bestehend aus zwei Plattenspielern und einem 2-Kanal-Mischpult für den Sound. Zusätzlich werden eine Art „virtueller Plattenkoffer“, über den sich die aufzulegenden Lieder wählen lassen, und eine Steuereinheit für die Lichtshow benötigt. Auch ein Konzept für die Menüführung zur Konfiguration einzelner Komponenten ist unerlässlich. Texturen Zunächst gilt es die Objekte, die auf der Oberfläche erscheinen sollen, grob anzuordnen und zu skizzieren. Darauf aufbauend entstehen immer feinere und genauere Abbildungen des tatsächlichen Interfaces. Im letzten Schritt müssen die Materialien der jeweiligen Elemente in einzelne Textur-Grafiken extrahiert werden. Damit die verschiedenen Bilddateien und verwendeten Schriftarten bei Korrekturen während der Umsetzung problemlos ausgetauscht werden können, sollte ihre Verwaltung gebündelt werden und zentral zugreifbar sein. 16
PROGRAMMIERHANDBUCH
Plattenspieler Ein realer Plattenspieler bietet neben dem einfachen Abspielen und Stoppen eines Musikstücks auch Möglichkeiten zur Anung der Geschwindigkeit und zum direkten Sprung an eine bestimmte Liedposition mit Hilfe des Tonarms. Aufbauend auf das Widget-Konzept des Frameworks scheint es sinnvoll, die einzelnen beweglichen Bauteile als eigenständige Widgets zu implementieren. Mit Hilfe eines Event-Listeners und selbst definierten Auslösern können somit zur Laufzeit verschiedene Funktionen angesteuert werden. Mit einem Tempo von etwa 45 U/min soll sich der Plattenteller nach Aktivierung durch einen Start/StopKnopf drehen. Der Musiktitel wird dann (bei aufgesetzter Nadel) in seiner Originalgeschwindigkeit abgespielt. Darüber hinaus gilt es das Beschleunigungs- und Abbremsverhalten mittels Touches zu simulieren. Da auf der CoBench zwar Berührungen erkannt werden jedoch nicht ihre Druck-Intensität, soll ein leichtes, konstantes Bremsen der Platte über das Auflegen von zwei Fingern möglich sein. Bei der Umsetzung des Pitch-Schiebereglers, der die stufenlose Anung der Abspielgeschwindigkeit in einem gewissen Bereich ermöglicht, spielt die Sensibilität des Multitouch-Systems eine wichtige Rolle. Weil die Pitch-Einstellungen unter Umständen bis auf zwei Nachkommastellen korrekt sein müssen, sind bei der Realisierung ggf. zusätzliche Vorkehrungen zur Feinjustierung zu treffen. Wie sein echtes Vorbild soll sich der virtuelle Tonarm per „Drag & Drop“ an beliebiger Lied-Position auf der Platte absetzen lassen. Der aktuelle Winkel beim Loslassen muss dann in die entsprechende Track-Zeit umgerechnet werden (Nadel innen entspricht 100%, Nadel außen 0% der Liedlänge). Demzufolge muss es der abgesetzten Tonkopf optisch, wie beim Original, mit zunehmender Spielzeit immer weiter zum Mittelpunkt der Schallplatte wandern. Zusätzlich ist ein LC-Display angedacht, auf dem aktuelle Liedinformationen des aufgelegten Titels, sowie ein Statusbalken für die Länge des Tracks erscheinen. Die notwendigen Daten müssen zur Laufzeit aus dem ID3-Tag extrahiert bzw. über die Soundbibliothek ausgelesen und mit dem Text-Objekt des Frameworks dargestellt werden. Mischpulte für Sound und Licht Die Mischpulte bestehen im Wesentlichen aus Dreh- bzw. Schiebereglern, unterschiedlichen Druck-Knöpfen, und Displays. Diese müssen im Hintergrund, über das Auslösen von Events (ähnlich wie beim Plattenspieler), die unterschiedlichen Funktionen der Sound- bzw. Lichtsteuerung aufrufen. Für die Druck-Knöpfe stehen im SDK bereits die notwendigen „PushButton“-Widgets zur Verfügung. Die übrigen Regler müssen mit Hilfe des SDK selbst entwickelt werden. Um Code-Dopplung zu vermeiden sollte bei der Umsetzung darauf geachtet werden, ähnliche Widgets zusammenzufassen und über Parameter konfigurierbar zu machen. Die Schieberegler beispielsweise unterscheiden sich lediglich in ihren Texturen und ihrer Neutralstellung. Daher könnten sowohl der Pitch-Slider auf dem Plattenspieler, als auch die Lautstärkeregler auf dem Mixer mit Hilfe desselben Widgets realisiert werden. Ähnlich verhält es sich mit den Drehknöpfen. Neben den Texturen müssten hier die Anschläge in Form von Min-/Max-Winkeln konfigurierbar sein. Menüführung Beim Start der Anwendung soll ein Konfigurationsmenü die Möglichkeit geben, die Ausgabe des Sounds auf verschiedene Soundkarten aufzuteilen bzw. den Ton in Form eines Audio-Streams an einen Server zu senden. Auch Einstellungen für das Ansteuern einer Lichtshow (IP-Adresse mit Portnummer) gilt es mit in das Formular aufzunehmen. Mit Hilfe eines Overlay, das sich über die gesamte sichtbare Fläche ausbreitet, sollen die Objekte im Hintergrund des Menüs gesperrt werden. Ähnlich wie beim bekannten „Lightbox“-Skript5 für Internetseiten wird somit einerseits das Menü in den Fokus des Betrachters gerückt und andererseits ein versehentliches Bedienen sich überlagernder Widgets verhindert. Für das Bestätigen bzw. Abbrechen des Dialogs sind zwei Buttons am Ende des Formulars vorgesehen. Nach 5 Lightbox (JavaScript) – Wikipedia, the free encyclopedia, vers. 13. August 2010, 20. Dezember 2010
.
17
PROGRAMMIERHANDBUCH
dem Absenden hat eine Validierung der eingegebenen Daten zu erfolgen, deren Ergebnis bei Bedarf in Form von Fehlermeldungen ausgegeben wird. Auf ähnliche Weise wie das Settings-Menü sollen auch die Slipmat- und Musikordner-Auswahl umgesetzt werden. Anstelle der Dialoggruppen ist jedoch ein „GTK+“-ähnlicher Dateibrowser vorgesehen, über den eine Datei bzw. ein Ordner selektiert werden kann. Das Wechseln zwischen den Ordnern und Auflisten ihrer Inhalte erfordert dabei spezielle Dateioperationen, die in einer Hilfsklasse zusammengefasst werden könnten. Alle notwendigen Eingabefelder, Buttons und Auswahllisten sind als Widgets bereits im eyefactive-SDK enthalten und bilden somit eine solide Grundlage für die Entwicklung komplexer Strukturen, wie den erwähnten Browser. Darüber hinaus dient ein gleichartiger Aufbau der Menüführung der Benutzerfreundlichkeit und bietet zusätzlich Raum für die quantitative Optimierung des Codes. Plattenkoffer Der Plattenkoffer dient der Auswahl und Anzeige von Musikstücken. Dabei soll sich das Design und die Haptik an die von Apple-Produkten bekannte Titelauswahl mit „Cover Flow“-Visualisierung orientieren. Jedes Lied soll durch ein endes Cover und die entsprechenden Track-Informationen in einem einzelnen Objekt (Record-Widget) dargestellt werden. Die Navigation durch die Musikauswahl wird dabei durch entsprechendes „Wischen“ über das Display erreicht. Der aktuelle Titel soll zusätzlich durch Animation hervorgehoben werden. Auf den ersten Blick bietet es sich für die Umsetzung dieser Anforderungen an, alle Record-Widgets dem im SDK integrierten Animations-Manager hinzuzufügen und mittels der Beschleunigung des relevanten Fingerblobs zu animieren. Dem Manager werden sowohl die neue Größe als auch die neue Position jedes RecordWidgets übergeben. Eine performantere Lösung wäre, lediglich ein einzelnes Record-Widget zu animieren und bei jedem Animationsschritt die übrigen Widgets relativ zum nächsten bzw. vorherigen Stück zu positionieren. Der Vorgang der Titelauswahl sollte mittels „Drag & Drop“ geschehen; so kann das gewünschte Lied auf den entsprechenden Plattenteller gezogen und abgespielt werden. Hierbei ist zu überlegen, wie man zwischen einem Blob für das Durchsuchen des Koffers und einem für die Auswahl eines Musikstücks unterscheiden kann. Hierbei sind drei Herangehensweisen in Erwägung zu ziehen: • Position des erkannten Blobs (z.B. auf oder neben einem Cover), • Dauer des erkannten Blobs (d.h. Verweildauer auf einer bestimmten Position), • Anzahl der erkannten Blobs (z.B. Navigation mit einem und „Drag & Drop“ mit zwei Fingern). Musikbibliothek Weiterhin ist es für die Realisierung des Plattenkoffers notwendig, Musikdateien auf einem Datenträger auszulesen, in einer Bibliothek zu speichern und anschließend zu verarbeiten. Die Anforderungen an die Musikbibliothek ergeben sich implizit aus den Anforderungen des Plattenkoffers. Diese erfordern, dass die ID3-Tags (Zusatzinformationen in Form von Metadaten) der MP3-Dateien ausgelesen werden müssen. So erhält man beispielsweise Informationen über den Interpreten oder den Titel, die zusammen mit dem Dateinamen in einer geeigneten Listenstruktur gespeichert werden können. Des Weiteren sollte es aus Performance-Gründen möglich sein den Inhalt der Bibliothek, d.h. die Daten der Liste, als Cache in einem XML-Dokument abzulegen. Dies hätte den Vorteil, dass nicht bei jedem Neustart des Programms eine neue Musiksammlung ausgelesen und erstellt werden müsste, sondern lediglich das erstellte XML-Dokument. Daraus ergibt sich, dass eine Klasse entwickelt werden muss, die das Parsen von XML-Dateien problembezogen übernimmt.
18
PROGRAMMIERHANDBUCH
3.2.2 Sound Plattenspieler Bei einem klassischen DJ-Set wird ein Plattenspieler (auch: Turntable) als Musikabspielgerät verwendet. Dieser wird später an einen Mixer angeschlossen, der den Sound zur Wiedergabe an einen Verstärker weiterleitet. Da beim Auflegen zwei Musikstücke ineinander übergeblendet werden, ist das wichtigste Merkmal eines DJtauglichen Plattenspielers die Möglichkeit, die Abspielgeschwindigkeit von Hand selbst einzustellen, damit diese Überblendung elegant und kaum hörbar vollzogen werden kann. Die Implementierung des Turntables der djBench sollte also in der Lage sein, ein derartiges Verhalten zu ermöglichen. Ebenso wichtig wie die Geschwindigkeitsänderung ist die Tatsache, dass der DJ im wahrsten Sinne des Wortes direkt in die Musik „eingreifen“ kann. Die laufende Platte kann jederzeit mit den Fingern angehalten oder wieder losgelassen werden und durch schnelles Vor- und Zurückbewegen wird das so genannte „Scratching“ ausgeführt. Mit djBench muss es daher möglich sein, die Abspielrichtung des Soundmaterials zu ändern oder es beispielsweise komplett durch die Bewegung mit der Hand manuell wiederzugeben. Ein denkbarer Ansatz wäre es, zwei identische Audioquellen, wobei eine von beiden rückwärts abgespielt wird, parallel laufen zu lassen, um bei Bedarf schnell zwischen ihnen umschalten zu können. Die Wiedergabe darf nicht nur ein einfaches Starten bzw. Stoppen ermöglichen, sondern muss zu jedem Zeitpunkt individuell steuerbar sein. Mischpult Den zweiten Teil des DJ-Sets bildet das Mischpult. Mit seiner Hilfe müssen Überblendungen zwischen verschiedenen Eingangskanälen möglich sein. Ein Weg die Lautstärkeregelung des Ausgangssignals vorzunehmen darf ebenso wenig fehlen, wie die Möglichkeit einzelne Kanäle separat vorzuhören. Auch Equalizer für jeden Kanal sind unabdingbar. Effekte gehören dagegen nicht zur Grundausstattung eines Mixers dazu, sind aber, wie auch bei der Entwicklung der djBench, oft vorhanden. Sind diese Voraussetzungen erfüllt, erhält man ein funktionsfähiges DJ-Set. Im Rahmen dieses Projektes soll ein einfaches Mischpult mit zwei Kanälen und einer kleinen Effekteinheit umgesetzt werden. Um dieses Vorhaben zu realisieren muss in erste Linie überlegt werden auf welche Weise das Routing der Eingangsquellen des Mixers intern stattfinden soll. So kann das Signal eines einzelnen Kanals über mehrere Wege vom Eingang bis zum Ausgang gelangen. Gleichzeitig muss beachtet werden, dass für das Vorhören ein separater Ausgang benötigt wird. Und auch die Effekte können nicht wahllos auf der Signalstrecke platziert werden, denn sie sind abhängig davon, ob sie für jeden Kanal einzeln oder nur für die Summe gelten sollen. Dadurch wird ihre Position beim Routing bestimmt. Zusätzlich muss die Lautstärke an vielen Stellen geregelt werden. Einerseits wirkt sie sich auf das gesamte Signal andererseits nur auf bestimmte Teile dessen aus. Generell gibt es sicherlich mehrere Möglichkeiten diese Anforderungen umzusetzen es scheint aber sinnvoll die Implementierung einem echten Mischpult nachzuempfinden. Streaming Neben der Klärung der Fragen zur internen Umsetzung der realitätsgetreuen Nachempfindung eines DJ-Sets müssen auch Überlegungen angestellt werden, auf welche Art und Weise die Soundwiedergabe von djBench letztendlich funktionieren soll. Um die bereits skizzierte Variante der Wiedergabe eines Masters und die gleichzeitige Möglichkeit des Vorhörens umzusetzen, werden mindestens zwei getrennte Audioausgänge benötigt. Diese Aufgabe ist entweder über den Einsatz einer entsprechenden Soundkarte mit zwei oder mehreren Ausgängen bzw. durch die Verwendung von zwei Soundkarten mit jeweils einem Ausgang zu lösen. Nachdem diese beiden Varianten einen Ansatz für die Benutzung nur eines Rechners darstellen bleibt zu klären, auf welchem Wege mehrere Abnehmer den Sound des Programms empfangen können. Die CAVEAnwendung benötigt beispielsweise eine solche externe Verbindung, denn ohne die Musik kann keine dynamische Visualisierung erfolgen. Es wäre denkbar die Audio-Rohdaten mittels UDP Broadcast zu verteilen, um sie dann auf Clientseite empfangen zu können. Dabei muss aber beachtet werden, dass hier die komplette Funktionalität eigenständig implementiert werden müsste. Abhilfe würde eine zweite Variante schaffen. Durch den Einsatz eines Audio Streaming-Protokolls in Verbindung mit einem Streaming-Server würden alle Rahmenbedingungen vorhanden sein und es müsste lediglich für eine Anbindung an den Server aus dem Programm heraus gesorgt werden. Da die BASS Audiobibliothek schon Methoden zur Verwendung der Streaming-Dienste bietet, scheint die zweite Option wohl die geeignetste. 19
PROGRAMMIERHANDBUCH
3.2.3 Lightshow Empfangen der Sound-Daten In der Lightshow-Anwendung werden die Sound-Daten benötigt, die von der CoBench Applikation erzeugt werden. Dafür ist eine Netzwerkkommunikation notwendig, da die CAVE nur so Daten empfangen kann und über keine andere Schnittstelle verfügt. Je nachdem welche Methode zum Verschicken der Audio-Daten gewählt wird, muss die Lightshow in der Lage sein, die Daten entsprechend zu empfangen. Bei einem UDP-Broadcast sind eigene Algorithmen notwendig, um die Pakete entgegen zu nehmen. Wird allergings ein Streaming-Protokoll verwendet, muss die Anwendung lediglich dafür ausgelegt sein, sich mit einem Streaming-Server zu verbinden und erhält darüber die Daten. Verarbeitung der Sound-Daten Für eine Visualisierung werden die Audio-Frequenzen benötigt, die über das Netzwerk empfangen werden. Diese liegen nicht unbedingt in einer Form vor, die sofort von der Anwendung benutzt werden kann. Deshalb müssen die Daten erst entsprechend dekodiert werden. Bei der Verwendung eines eigenen Protokolls ist die Programmierung einer Routine nötig, die mit den ankommenden Daten umgehen kann. Wird ein Streaming-Protokoll benutzt, dann gibt es oftmals zahlreiche Bibliotheken (wie z.B. BASS), die die Verarbeitung übernehmen und damit die Entwicklungszeit reduzieren. Es bleibt zu klären, in welchem Format die Sound-Daten vorliegen und wie sie anschließend von den Visualisierungen genutzt werden können. Die Audio-Frequenzen werden in diskreter Form benötigt, wobei die Anzahl der Unterteilungen möglichst variabel sein muss. Häufig sind die Musikdaten als FFT-Daten abgelegt, die erst umgerechnet werden müssten. Mittels der BASS-Bibliothek kann auf die FFT-Daten zugegriffen werden. Wiedergabe der Sound-Daten Die CAVE verfügt über eine 5.1 Soundanlage, wobei die Bodenplatte mit vier Subwoofern verbunden ist. Der Ton sollte aus allen Boxen zu hören sein, um die beste Wirkung zu erzielen. Wünschenswert wäre es zudem, wenn die Subwoofer-Spur genutzt wird, um die Bodenplatte in Schwingungen zu versetzen. Abhängig von der Verteilung der Musik vom djBench-Programm stehen nicht unbedingt 5.1-Daten zur Verfügung. Deshalb wird eventuell eine Umwandlung erforderlich sein. Das „Upmixing“ des Sounds von 2.0 auf 5.1, wie es zum Beispiel beim Streaming notwendig ist, kann über zwei Wege realisiert werden. Als ein möglicher Ansatz könnte die Hardware diese Aufgabe übernehmen, da sie meist standardmäßig über eine solche Funktionalität verfügt. Der Vorteil dabei läge darin, dass die Umformung schneller durchgeführt werden kann. Zu beachten ist hierbei, dass diese Konfiguration systemabhängig und deshalb nur für die CAVE gültig wäre. Einen anderen Ansatz würde die softwaretechnische Transformation der Daten darstellen, was unter Umständen einen höheren Aufwand zu Folge hätte. Da im 2.0-Audio keine Bass-Spur vorhanden ist, muss diese aus dem rechten und linken Kanal berechnet werden. Dabei sollten nur die tiefen Frequenzen übernommen werden, was mit einem Tief--Filter möglich ist. Die meiste Hardware bietet dieses auch an und mittels Software kann es ebenso umgesetzt werden. Visualisierung des Sounds in 3D Es ist geplant über ein Lightshow-Modul im djBench-Programm die Visualisierungen in der CAVE zu wechseln. Das heißt, es müssen mehrere Darstellungen vorhanden sein. Wünschenswert wäre eine einfache Erweiterungsmöglichkeit für weitere Visualisierungen, weshalb diese modular aufgebaut werden sollten. Um eine einheitliche Schnittstelle zu ermöglichen, könnte eine abstrakte Oberklasse entwickelt werden, von der alle Visualisierungen erben. Dies vereinfacht die Verwaltung der einzelnen 3D-Effekte. Außerdem würden Parameter wie Farbe, Wechselgeschwindigkeit etc. allgemein nutzbar sein. Für eine dreidimensionale Darstellung wird für jedes Auge ein eigenes Bild benötigt. Die daraus resultierenden zwei Bilder pro Zeitabschnitt müssen von den Projektoren abwechselt angezeigt werden. Dabei ist der Betrachterpunkt bei beiden unterschiedlich, wodurch der 3D-Effekt entsteht. Das Erzeugen der Bilder wird automatisch von dem CAVE-Framework der FH Wedel übernommen, weshalb keine weiteren Routinen nötig sind. 20
PROGRAMMIERHANDBUCH
Um die Effekte an die Musik anzuen, muss auf die Sound-Daten zugegriffen werden können. Dies könnte zum einen jede Visualisierung eigenständig übernehmen, was aber zu viel redundanten Code führen würde, oder eine Sound-Klasse bietet entsprechende Funktionalitäten an. Letzteres wäre softwaretechnisch der saubere Weg. Steuerung der Visualisierungen über das Netzwerk Mit Hilfe der CoBench-Anwendung soll zwischen den einzelnen Visualisierungen gewechselt sowie deren Parameter anget werden können. Dafür ist eine Kommunikation über das Netzwerk erforderlich, bei der Kommandos an die Lightshow übertragen werden. Diese Befehle müssen im djBench-Programm (Sender) und in der CAVE-Anwendung (Empfänger) bekannt sein. Hierfür eignet sich ein eigenes Protokoll, das von beiden Applikationen eingebunden und verwendet wird. Die Frage ist, wie die Übertragung erfolgen soll. Zur Auswahl stehen UDP und T. Da die Lightshow das djBenchProgramm zusätzlich über die zur Verfügung stehenden Visualisierungen informieren sollte, ist eine Kommunikation in beide Richtungen notwendig. Für den einfachen Verkehr der Befehle über das Netzwerk reicht die Funktionalität des UDP-Protokolls. Wenn eine Überprüfung gewünscht wird, ob die Übertragung unterbrochen wurde, wird allerdings eine verbindungsorientierte Kommunikation benötigt, wie sie mit dem T-Protokoll möglich ist. 3.3 Realisierung 3.3.1 Benutzeroberfläche Main-Widget Die durch das SDK vorgegebene Struktur des Ineinanderschachtelns verschiedener Widgets, erfordert das Anlegen eines sogenannten „Main-Widgets“ (djbMainWidget) beim Starten der Anwendung, der innerhalb der „yfApp“-Klasse beschrieben ist. Dieses erstreckt sich als Hauptfenster über die komplette Oberfläche und beinhaltet, je nach Programmzustand, die entsprechenden Bedienelemente und ihre Initialisierungs-Aufrufe. Da sich die Menüführung unmittelbar auf der Ebene des Hauptfensters bewegt, wurde auch ihre gesamte Logik, wie etwa die Erzeugung und Validierung der Menü-Formulare, in dieser Klasse implementiert. 01 void djbMainWidget::dlgClickedOk(const djbDialogEventArgs& args) 02 { 03
remErrorMsgsFromDlg(); //evtl vorhandene Fehlermeldungen löschen
04
vector <string> strErrorMsg; //Alle Fehlernachrichten
05
bool addLight = false;
06
switch(args.getDialogID())
07
{
08
[...] case eDlgChangeMusicFolder:
09 10
{
11
yfPropertyMap tmpMap;
12
mp_dlgwMenu->getFormValues(tmpMap); //map aus dialog holen
13
string path(tmpMap.get("path", "/")); //path holen
14
string selectedObject(tmpMap.get("selectedObject", "")); //selektiertes Objekt
15
if ((selectedObject != "") && (mp_rcRecordCaseWidget != 0))
16
mp_rcRecordCaseWidget->setMusicLibraryPath(path + selectedObject);
17
else
18
strErrorMsg.push_back("Please select a folder.");
19
}
20
break;
21
default:;
22
}
21
PROGRAMMIERHANDBUCH
23
if (strErrorMsg.size() == 0)
24
{
25
mp_dlgwMenu->close(); // Menü schließen
26
}
27
else
28
{
29 30
addErrorMsgsToDlg(strErrorMsg); }
31 } Ausschnitt aus der „djbMainWidget“-Klasse: Auswertung des Settings-Formulars mit Generierung von Fehlermeldungen
Somit ließen sich zusätzlich das Ändern des Musikordners und die Auswahl einer benutzerdefinierten Slipmat zur Laufzeit an dieser zentralen Stelle mit den dazugehörigen Widgets verbinden. Auch die übrigen, Widgetübergreifenden Ereignisse (Laden eines Tracks aus dem Plattenkoffer, ändern des Ausgabekanals zur Laufzeit usw.) werden hier an die jeweiligen, voneinander unabhängigen Teilnehmer verteilt. Texturen Der wichtigste Faktor bei der Gestaltung war die optimale Nutzung des zur Verfügung stehenden Platzes für die Oberfläche in Verbindung mit den geplanten Bedien-Elementen. Erste Tests fanden daher mit sehr einfach geformten Objekten aus dem SDK statt, um ein Gefühl für die Größen zu bekommen. Aus Gründen der Usability wurde hierbei auch eine Mindestgröße für die kleineren Bedienelemente ermittelt. Nicht zuletzt spielte bei der Anordnung und beim Design auch die mögliche Portierung der djBench auf ein anderes, kleineres Multitouch-Device eine Rolle. Auf der Basis von Screenshots wurde mit Hilfe von Adobe Photoshop schließlich ein optisch ansprechendes Design entwickelt, das sämtliche Bestandteile des DJ-Sets abbildet. Zur Verstärkung des VR-Eindrucks lag hier ein besonderes Augenmerk auf der möglichst realen Darstellung der Geräte. Durch entsprechende Aufteilung des Designs in verschiedene Ebenen ließen sich die einzelnen Texturen schließlich problemlos in ein für das SDK lesbares Grafikformat extrahieren (siehe Programmordner unter bin/djBench/data/media/images/textures). Neben dem Design mit Hilfe von Texturen wurden bei der Umsetzung auch häufig die SDK-internen Gestaltungsmöglichkeiten genutzt. Diese erlauben z.B. das Einfärben der jeweiligen Formen und ihrer Rahmen mit RGBA-Farben. Außerdem kann für die Darstellung von Text eine beliebige TrueType-Schriftart gewählt werden, was vor Allem für die dynamischen Textanzeigen im LC-Display der Plattenspieler und im Plattenkoffer sinnvoll ist. Die gesamten Farb-, Textur- und Schrift-Informationen wurden anschließend in der Klasse „djbTexConfig“ gesammelt und für den zentralen Zugriff auf Basis eines Singleton-Templates implementiert. Durch die zentrale Verwaltung des gesamten Erscheinungsbildes lassen sich nicht nur kleinere Korrekturen an selbigem vornehmen, sondern auch eine spätere Erweiterung der Software um ein Skin-System6 wäre möglich. Plattenspieler Bei der Umsetzung des Plattenspielers konnten nur bedingt SDK-eigene Elemente direkt genutzt werden. Durch ihre komplexen Funktionalitäten mussten der Plattenteller (djbPlatterWidget) mit seinem Tonarm (djbTonearmWidget) und auch der Pitch-Schieberegler (djbFadeSlider) als eigene Widget-Klassen implementiert werden. In der Plattenspieler-Klasse selbst (djbTurntableWidget) werden die verschiedenen Bestandteile zunächst initialisiert und dabei über String-Parameter mit ihren Texturen belegt. Einen weiteren Turntable-KunstruktorParameter stellt die Referenz auf das zu steuernde Sound-Objekt dar. Das heißt der Plattenspieler wurde so konzipiert, dass in ihm sämtliche Ereignisse zur Steuerung eines Musikstücks gesammelt und auf den Soundkanal angewendet werden. Als Beispiel wird hier das Ereignis erläutert, das beim Bremsen/Beschleunigen des Plattentellers ausgelöst wird: 6 Skin (Computer) – Wikipedia, vers. 16. September 2009, 14. Februar 2011
.
22
PROGRAMMIERHANDBUCH
In der updateInterval-Methode des Tellers, die zur Laufzeit in zeitlich nicht konstanten Abständen aufgerufen wird, werden die verschiedenen Bedien-Situationen (Starten/Stoppen durch Start-/Stop-Knopf des Plattenspielers, Abbremsen mittels zweier Finger, Scratchen) abgeprüft und schließlich bei jeder Geschwindigkeitsänderung ein Event ausgelöst und an das Turntable-Widget weitergegeben. 01 // Schauen ob sich Geschwindigkeit verändert hat und ggf Event aufrufen. 02 if (fabs(m_fValue - (getVelocityRotationDir() * getVelocityRotation())) >= 0.0001) 03 { 04
m_fValue = getVelocityRotationDir() * getVelocityRotation();
05
djbPlatterWidgetEventArgs pwa(m_iPlatterID,
06
,m_fValue
07
,static_cast
(m_fValue)
08 09
,valueToPercent(m_fValue)); yfNotifyEvent(g_evChanged, pwa, this);
10 } Auszug aus dem Quellcode der Methode „updateInterval“ der Klasse „djbPlatterWidget“
Als Status wird ein Objekt der Event-Klasse (djbPlatterWidgetEventArgs, Variable „pwa“) mit der GUI-ID sowie diskrete und prozentuale Geschwindigkeitswerte des Plattentellers übergeben. Der Plattenspieler als übergeordnetes Objekt fügt dem Teller beim Initialisieren einen Event-Listener hinzu und ruft bei Auftreten des Ereignisses die Methode „platterHasChanged“ auf: 01 void djbTurntableWidget::platterHasChanged(const djbPlatterWidgetEventArgs& args) 02 { 03
// wird aufgerufen, sobald sich Dreheschwindigkeit des Tellers ändert
04
if (mp_tawTonearm->getTonearmIsOn())
05
{
06 07
mp_sttSoundTurntable->setPitch(args.getPercent() / 100.0); }
08 } Quellcode der „platterHasChanged“-Methode innerhalb der „djbTurntableWidget“-Klasse
Hier wird schließlich die geänderte Geschwindigkeit des Plattentellers auf das Soundkanal-Objekt übertragen, sofern der Tonarm sich auf der Platte befindet. Auf ähnliche Weise werden auch die Ereignisse des Tonarms verarbeitet. Im Gegensatz zum Plattenteller sind die Auslöser der Ereignisse jedoch innerhalb der (von der yfWidget-Klasse) geerbten Blob-Methoden zu finden. Wird der Tonarm berührt, stoppt der auf dem Gerät abgespielte Track und beginnt erst dann wieder, wenn der Tonabnehmer auf der Platte abgesetzt wird. Da die Blob-Methoden nur aufgerufen werden, sobald sich Blobs auf dem Widget ändern, wirkt sich dies ressourcenschonend auf das System aus. Zusätzlich wird innerhalb der Plattenspieler-Klasse permanent die aktuelle Track-Position ausgelesen. Zum einen wird diese für die Anzeige im Display genutzt und zum anderen zur korrekten Berechnung des Winkels für die Nadelstellung des Tonarms. Das vielleicht wichtigste Element bei der Steuerung der djBench stellt jedoch das Schieberegler-Widget (djbFadeSlider) dar. Wichtig, weil es auf unterschiedliche Weise an vielen Stellen wiederverwendet werden kann. Beim Plattenspieler sind das zum einen der Pitch-Regler, zur Anung der Abspielgeschwindigkeit, und zum anderen der Statusbalken, der gleichzeitig zur alternativen Positions-Auswahl für das Lied dient. Er wurde daher so konzipiert, dass sein Aussehen über Konstruktor-Parameter variabel gestaltet werden kann. Zudem sind das Festsetzen und Unsichtbarmachen des Regler-Knopfes über entsprechende Funktionen („setLock“ bzw. „setSliderVisibility“) geregelt. Da der Regler-Knopf das einzige bewegliche Element des Reglers darstellt wurde er in eine separate Klasse ausgelagert (djbFadeSliderBtn). Events werden hier wiederum in den Blob-Methoden behandelt und an das übergeordnete Fade-Slider-Objekt weitergereicht. Dort wird er mit der aktuellen Position des Buttons verrechnet und abermals als Ereignis an das nächst-höhere Widget übergeben, wo es z.B. zur Steuerung der Geschwindigkeit genutzt werden kann. 23
PROGRAMMIERHANDBUCH
Als problematisch stellte sich während der Umsetzung vor Allem die nicht vorhandene Synchronität des abspielenden Sounds mit der Optischen Steuerung heraus. Der zeitliche Versatz zwischen den Aufrufen der jeweiligen Update-Funktionen führt daher zu einem leichten Delay, das heißt dass der Sound nicht direkt, sondern mit minimaler Verzögerung auf Änderungen der optischen Steuerung reagiert. Auch das Rechnen mit Float-Werten und damit verbundene Ungenauigkeiten spielen hierbei eine Rolle. Wegen der im Vergleich zur Größe verhältnismäßig geringen Auflösung, mussten zudem die bereits in der Problemanalyse angesprochenen Maßnahmen zur Feinjustierung des Geschwindigkeitsreglers in Form von „+/-“-Buttons eingebaut werden. Mischpulte Ähnlich wie beim Plattenspieler, laufen auch in den Mischpult-Klassen die Ereignisse der eingesetzten Steuer-Elemente in Form von prozentualen Werten zusammen. Beim Sound-Mischpult (djbMixerWidget) lassen sich diese unmittelbar auf den jeweiligen Ausgabekanal bzw. auf den Master-Ausgabekanal anwenden und beim Lichtmischpult (djbLightMixerWidget) auf ein Visualisierungs-Objekt. Wie schon beim Turntable-Widget wird das auch hier durch die Übergabe einer Referenz auf die zu steuernden Objekte (djbSoundMixer bzw. djbVisualizationControl) im Kontruktor der Mixer-Klassen realisiert. Diese Art der Kopplung sorgt neben einer ordentlichen Trennung von Steuerung und Oberfläche zudem für eine einfache Erweiterbarkeit des Systems. Als optisches für den Nutzer wurden für die Druckknöpfe mehrere Status-Texturen angefertigt. Wie beim Original geben sie Aufschluss darüber, welche Funktion derzeit aktiviert ist oder ob die Software einen Blob erkannt und somit das Drücken des gewünschten Buttons angenommen hat. Dafür werden die Buttons, ggf. zusammen mit ihrem aktuellen Status (ein- oder ausgeschaltet), in einem klassenglobalen VectorContainer mit Bezug auf ihre GUI-ID gespeichert. Sobald ein Ereignis registriert wird, wird die dazugehörige Methode aufgerufen („btnDown“ bzw. „btnUp“): 01 void djbMixerWidget::btnDown(const yfPushButtonEventArgs& args) 02 { 03
string strTex(""); // Pfad zur Textur
04
switch (args.getButtonID())
05
{
06
case eCh01Cue:
07
// Icon umsetzen (eingedrückter Knopf)
08
strTex = m_pbArrPushButtons[eCh01Cue].bIsOn
09
? djbTexConfig::instance().getTex(djbTexConfig::eMiwCueBigOnDown)
10
: djbTexConfig::instance().getTex(djbTexConfig::eMiwCueBigOffDown);
11
break;
12 13
[...]
14 15
default:;
16
}
17
// Icon setzen, wenn Pfad rauskommt
18
if (strTex != "")
19 20
m_pbArrPushButtons[args.getButtonID()].p_btn->setIcon(strTex); // Status togglen
21 m_pbArrPushButtons[args.getButtonID()].bIsOn = ! m_pbArrPushButtons[args.getButtonID()¬ ].bIsOn; 22 } Ausschnitt aus dem Quelltext der „btnDown“-Methode in der „djbMixerWidget“-Klasse
Im Codeschnipsel ist zu erkennen, wie über einen Case-Verteiler und nach Auswertung der Statusvariablen schließlich die korrekte Textur gesetzt wird. Für den Sound-Mixer wurde außerdem noch ein Widget in Form eines Drehknopfs entwickelt. Wichtig war hier die in der Planung angesprochene Konfigurierbarkeit, sodass der Knopf entweder als Lautstärkeregler 24
PROGRAMMIERHANDBUCH
mit festen Anschlagpunkten oder als Endlosdrehknopf ohne Begrenzung genutzt werden kann. Erreicht wird dies durch entsprechende Parameter im Konstruktor, die bei Bedarf eine Grenzwert-Prüfung innerhalb der „adjustRotation“-Methode hinzuschalten. Außerdem kam bei beiden Mischpulten das bereits für die Plattentellergeschwindigkeit bzw. den Track-Statusbalken verwendete Schieberegler-Widget zum Einsatz. Über die bereits erwähnte Möglichkeit des Feststellens lassen sich bei bestimmten Visualisierungen im Lichtmischpult optionale Regler sperren bzw. aktivieren. Auch die geplante beliebig einstellbare Neutralstellung wurde implementiert und beispielsweise beim Crossfader genutzt. Durch die später geschaffene Möglichkeit des Wechselns der Ausgabegeräte bzw. des optionalen Zuschaltens einer Lichtshow über ein Konfigurationsmenü, ergaben sich bei den Mischpulten ein paar kleinere Probleme. Die Soundmixer- bzw. Visualisierungs-Objekte mussten dabei nämlich jeweils neu initialisiert werden. Da die GUI-Elemente sich jedoch nicht gleichzeitig mit-initialisierten, war z.B. der Effekt-Button optisch noch eingeschaltet, aber im Soundmixer-Objekt durch den Reset abgeschaltet war. Über eine zusätzliche Initialisierungs-Methode in jedem Mixer, die jeweils mit dem Reset des jeweiligen zu steuernden Objekts einhergeht wurde das Problem letztlich gelöst. Menüführung Strukturell ist die Menüführung relativ stark an html-Formular angelegt. Die Oberste Ebene und somit das Menüfenster, bildet das Dialog-Widget (djbDialogWidget). In ihm sind die optischen Effekte wie z.B. das Einund Ausfahren des Menüs implementiert. Über Konstruktor-Parameter lässt es sich mit einem Menü-Titel und -Icon versehen und beliebig in der Größe verändern. Standardmäßig befinden sich zudem am unteren Ende des Fensters zwei Buttons zum Bestätigen („OK“) bzw. Abbrechen („CANCEL“) des Dialogs. Das Dialog-Widget kann mehrere Dialog-Gruppen (djbDialogGroupWidget) beinhalten. Diese enthalten schließlich die tatsächlichen Dialog-Eingabefelder des SDK. Da die Dialog-Gruppen wiederum über Parameter mit beliebigen Unterüberschriften und Icons konfiguriert werden können, bieten sie eine sehr gute Möglichkeit zur optischen Strukturierung der Menüeinträge. Im Main-Widget lässt sich somit flexibel das gewünschte Formular zusammenstellen. Innerhalb des Dialog-Widget werden alle Formulardaten in einer Map (yfPropertyMap) verwaltet. Beim Absenden des Formulars wird diese Map schließlich aus dem Main-Widget heraus über eine Referenz ausgewertet und bei Bedarf werden entsprechende Fehlerausgaben generiert. Auch für den „GTK+“-ähnlichen Dateibrowser zur Auswahl der Slipmat bzw. des Musikordners bildet das Dialog-Widget die Grundlage. Anstelle der Dialog-Gruppen wird dem Menü jedoch ein speziell entwickeltes Dateibrowser-Widget (djbFileBrowserWidget) hinzugefügt, wobei die selektierbaren Dateien über einen Konstruktor-Parameter gewählt werden können. Genau wie sein Gnome-Vorbild besteht der Dateibrowser aus einem Bereich, in dem der Pfad ordnerweise (bis zu drei Ebenen tief) nachgebildet ist (djbFilePathWidget), sowie je einem scrollbaren Auswahl-Fenster zum Navigieren auf Ordnerebene bzw. zum Auswählen der Datei innerhalb des gewählten Ordners (djbFileListWidget). Über entsprechende Dateioperationen, die in der Klasse „djbFileOperations“ zusammengefasst sind, lässt sich somit das gesamte Dateisystem durchsuchen. Auf der Main-Widget-Ebene findet wiederum die Analyse der Eingabe statt, wobei dann entsprechende Methoden, z.B. das Initialisieren der Platten im Plattenkoffer nach Auswahl eines neuen Musikordners, angesteuert werden. Probleme traten hauptsächlich bei der Entwicklung des Konfigurationsmenüs auf. Beispielsweise findet die Erkennung der zur Verfügung stehenden Sound-Devices lediglich bei Programmstart statt, sodass nachträglich per USB angeschlossene Soundkarten nicht in der Auswahl erscheinen und selektiert werden können. Außerdem brachte die Verbindung der CAVE-Lichtshow mit der djBench einige Schwierigkeiten mit sich, sodass anfänglich falsche Fehlermeldungen produziert wurden. Dieses Problem ließ sich jedoch durch die Implementierung einer regelmäßigen Abfrage des Verbindungsstatus‘ zur Laufzeit beheben. Plattenkoffer Die Hauptaufgabe bei der Realisierung dieser Anzeige-Komponente lag in der animierten Navigation. Dabei 25
PROGRAMMIERHANDBUCH
führte die dynamische Größenanung der Record-Widgets (djbRecordWidget), in Abhängigkeit der Lage, zu Schwierigkeiten bei der Positionierung. Grund dafür waren die erst zur Animationszeit auftretenden Skalierungen, die bei der Berechnung der Verschiebung, genauer der neuen X-Position, berücksichtigt werden mussten. Die Probleme traten bereits bei der ersten Realisierung des Plattenkoffers auf und resultierten in mehreren Lösungsansätzen und -umsetzungen. Dabei stellte sich heraus, dass alle Möglichkeiten ähnliche Probleme bezüglich der Animation hervorriefen. Navigation Der Plattenkoffer für die Darstellung aller Lieder der Bibliothek ist durch das RecordCase-Widget (djbRecordCaseWidget) implementiert. Dieses besteht aus einem RecordFrame (djbRecordFrameWidget), das wiederum alle Record-Widgets enthält. Das RecordCase dient als Wrapper, dem die anzuzeigende Musikbibliothek bei Erzeugung übergeben wird. Für die eigentliche Anzeige und Navigation durch diese Sammlung ist das RecordFrame-Widget verantwortlich. Zur Navigation wird innerhalb der RecordFrame-Klasse stets das erste Record-Widget der Track-Liste dem SDK-eigenen Animations-Manager hinzugefügt und mit Hilfe der erkannten Blob-Translationen im Plattenkofferbereich animiert („animateRecordWidget“-Methode mit den Parametern „fTrans“ (float), „iXTransBlob“ (int) und „add“ (int)). In jedem Animationsschritt wird anschließend über die restliche Liste iteriert, wobei die resultierende Position der übrigen Record-Widgets gesetzt wird. Dabei stehen die Methodenparameter „fTrans“ für die vorberechnete neue Position der rechten Kante des Record-Widgets und „iXTransBlob“ für den faktorisierten Wert, um den die Einträge des Koffers nach links oder rechts verschoben werden. Das bedeutet, die eigentliche Translation des Blobs wird in einen Integerwert umgerechnet. Dieser besagt, um wie viele Stellen in der Sammlung weitergesprungen wird. Der „add“-Parameter in der „animateRecordWidget“-Methode ist der mit der Navigationsrichtung verechnete Parameter „iXTransBlob“. Die Funktion berechnet sowohl die endgültige neue Position des animierten Record-Widgets als auch seine tatsächliche neue Größe. Die Animation wird mittels Manager wie folgt ausgeführt: 01 p_waAnimation->setAnimationType(yfAnimation::eEaseOut); 02 p_waAnimation->animateSizeTo(yfSize2f(size ,size), 03
yfWidget::eRight,
04
10.0f);
05 p_waAnimation->animatePositionTo(yfPoint2f(fXTranslation 06
,m_RecordWidgetPtrList.front()->getPosition(eBottom).y),
07
yfWidget::eBottomRight,
08
20.0f);
09 m_amManager.addAnimation(p_waAnimation);
Die anderen Widgets in der Bibliothek werden in der „updateInterval“-Methode anhand des animierten Record-Widgets positioniert und skaliert. Für diese Komponenten muss eine Randbehandlung bezüglich der Skalierung erfolgen.
26
PROGRAMMIERHANDBUCH
Das Anzeigefenster der Bibliothek ist über ein Raster in unterschiedliche Abschnitte unterteilt:
Abbildung 3a: Plattenkoffer-Widget mit angedeutetem Raster.
Die Randbereiche rechts und links sind als Standartgröße zu verstehen. Sobald dann ein Record-Widget in einen anderen Bereich gelangt, wird seine Größe neu animiert. Die Überprüfung hierzu wird bei jedem Update der Anzeige vorgenommen. Es folgt ein exemplarischer Pseudeo C-Code, wie diese in der „update“-Funktion umgesetzt wurde: 01 if (RasterMitte->isInside(VorgängerPosition(eRight).x + m_fCoverPadding) - RasterMitteP¬ osition(eLeft).x 02 03 04
, VorgängerPosition (eTopRight).y - RasterMittePosition(eTopLeft).y))){ if (CurrRecordWidgetWidth != CenterCoverSize) resizeRecordWidget(p_rcRecordWidget, m_iCenterCoverSize);
05 }
Auswahl Die Selektion eines Musikstücks zum Abspielen findet wie unter 3.2.1 beschrieben mittels „Drag & Drop“ statt. Zur Unterscheidung des Durchsuchens der Bibliothek von der Auswahl eines Titels wird die Anzahl der Blobs ausgewertet: Mindestens zwei Finger dienen der Auswahl eines Musikstücks, wobei die Anzahl über die „getBlobCount“Methode ermittelt und innerhalb der „blobsDown“-Methode des RecordFrame-Widgets ausgewertet wird. Um eine konsistente Animation der Widgets sicherzustellen, wird zunächst eine Track-Selektion zur Animationszeit ausgeschlossen. Außerdem ist es nicht möglich mehr als einen Titel zu einem bestimmten Zeitpunkt auszuwählen und zu bewegen, was durch die boolesche Variable „m_bIsDrag“ erreicht wird: 01 if (!m_bIsDrag && getBlobCount() >= 2 && !m_amManager.findAnimation(m_WidgetAnimationPtrL¬ ist.back()->getID()))
Anschließend wird per Iteration über die Record-Widget-Liste das ggf. gewählte Widget identifiziert: 01 if ((abs(mapGlobalToLocal(itBlobPtr->second->getCentroid()).x - p_rcRecordWidget->getPos¬ ition().x) <= p_rcRecordWidget->getSize().width *0.5f) 02 && (abs(mapGlobalToLocal(itBlobPtr->second->getCentroid()).y - p_rcRecordWidget->getPos¬ ition().y) <= p_rcRecordWidget->getSize().height*0.5f))
Wurde eine Auswahl erkannt, wird die „makeDrag“-Methode aufgerufen, die eine Kopie des selektierten Tracks erzeugt. Innerhalb der „blobsUpdate“-Methode wird dann anhand aller erkannter Blobs die Position des gezogegenen Objekts gesetzt. Beim Loslassen testet eine Kollisionserkennung zunächst, ob das Widget auf einem Plattenspieler abgelegt wurde. Die Erkennung des korrekten Widget-Typen erfolgt über über die „yfPropertyMap“. Alle Kind-Widgets innerhalb des Main-Widgets werden auf den „isCollisionable“-Schlüssel getestet, der jedoch lediglich beim Plattenspieler (djbPlatterWidget) gesetzt ist: 27
PROGRAMMIERHANDBUCH
01
map< int, yfWidgetPtr > widgetPtr = *(getParent()->getParent()->getChildren());
02
map< int, yfWidgetPtr >::iterator it;
03
yfPropertyMap pMap;
04
for (it = widgetPtr.begin(); it != widgetPtr.end(); ++it){
05
pMap.clear();
06
it->second->getProperties(pMap);
07
if (pMap.hasKey("isCollisonable")){
Daraufhin folgt die eigentliche Kollisions-Erkennung, die bei einer Berührung ein Event mit den entsprechenden Informationen des ausgewählten Tracks auslöst und das Laden der Datei auf initiiert. 01 if ((it->second->getShape()->isInside(yfPoint2i(mapParentToGlobal(p_wWidget->getPosition¬ (yfWidget::eTopLeft) ).x - it->second->getPosition(yfWidget::eLeft).x, mapParentToGlobal(¬ p_wWidget->getPosition(yfWidget::eTopLeft) ).y - it->second->getPosition(yfWidget::eTopLe¬ ft).y))) 02 || (it->second->getShape()->isInside(yfPoint2i(mapParentToGlobal(p_wWidget->getPo¬ sition(yfWidget::eBottomLeft) ).x - it->second->getPosition(yfWidget::eLeft).x, mapParentTo¬ Global(p_wWidget->getPosition(yfWidget::eBottomLeft) ).y - it->second->getPosition(yfWidget¬ ::eTopLeft).y))) 03 || (it->second->getShape()->isInside(yfPoint2i(mapParentToGlobal(p_wWidget->getPo¬ sition(yfWidget::eTopRight) ).x - it->second->getPosition(yfWidget::eLeft).x, mapParentTo¬ Global(p_wWidget->getPosition(yfWidget::eTopRight) ).y - it->second->getPosition(yfWidget¬ ::eTopLeft).y))) 04 || (it->second->getShape()->isInside(yfPoint2i(mapParentToGlobal(p_wWidget->getPo¬ sition(yfWidget::eBottomRight)).x - it->second->getPosition(yfWidget::eLeft).x, mapParentTo¬ Global(p_wWidget->getPosition(yfWidget::eBottomRight)).y – it->second->getPosition(yfWidget¬ ::eTopLeft).y)))) { 05
djbRecordFrameWidgetEventArgs recfwa(mp_rcRecordWidget->getRecordID()
06
,it->first
07 cRecordWidget->getTrackInfo().name
,mp_rcRecordWidget->getTrackInfo().path+mp_r¬
08
,mp_rcRecordWidget->getTrackInfo().image
09
,mp_rcRecordWidget->getTrackInfo().title
10
,mp_rcRecordWidget->getTrackInfo().artist
11
,mp_rcRecordWidget->getTrackInfo().album
12 13
,getMusicLibraryPath()); yfNotifyEvent(g_evRecCollision, recfwa, this);
14 }
Musikbibliothek Die Grundlage für einen virtuellen Plattenkoffer bildet eine, für die Verarbeitung vorbereitete, Menge an Musikdateien. Zu diesem Zweck wurde die Klasse „djbMusicLibrary“ erstellt, welche zum Auslesen und der anschließenden Verwaltung von Musikdateien dient. Bei der Erzeugung eines Objektes dieser Klasse wird ein Pfad angegeben, der zur Laufzeit geändert werden kann. Anhand dieses Pfades werden vorhandene Musikdateien ausgelesen und die Bibliothek dynamisch aufgebaut. Dabei werden die ID3-Tags der MP3-Dateien mit Hilfe der C++-Bibliothek „id3lib“7 verarbeitet, die alle für das Auslesen und Verarbeiten der Metainformation benötigten Funktionen bereitstellt. Über einen Aufruf der Methode „getID3Tag“ der „djbMusicLibrary“-Klasse ist es somit möglich, alle relevanten Metadaten einer beliebigen Musikdatei auszulesen und in einem übergebenen Datencontainer (Aufbau siehe Punkt 3.4.1) zu speichern. Dabei wird auch ein temporärer Ordner für die Albumcover erstellt, in den dem alle gefundenen Titelbilder abgelegt werden. Damit nicht bei jedem Verzeichniswechsel stets alle Ordner und Unterordner nach MP3s gescannt werden müssen, wird die Bibliothek in einer XML-Datei gecached: Mit Hilfe des externen Parsers „TinyXML++“8 wird nach jedem erfolgreichem Auslesevorgang ein XML7 id3lib - The ID3v1/ID3v2 Tagging Library, 26. Februar 2011
. 8 tip - Project Hosting on Google Code, 26. Februar 2011
.
28
PROGRAMMIERHANDBUCH
Dokument mit allen Liedern und ihren Metadaten erzeugt und im Wurzelverzeichnis abgelegt. Diese dient bei erneutem Zugriff auf den Ordner als Grundlage für den Aufbau der Bibliothek. Treten beim Laden der XML-Datei Konsistenzfehler auf (z.B. enthaltene Datei ist nicht mehr vorhanden), werden der aktuelle Pfad neu gescannt und eine Cache-Datei angelegt. Sollte hingegen ein Coverbild nicht gefunden werden, so hat dies keinen neuen Auslesevorgang zur Folge, sondern es wird ein Default-Bild verwendet. 3.3.2 Sound Plattenspieler Die gewünschte Funktionalität des Plattenspielers kann allein durch das simple öffnen und abspielen einer Audiodatei nicht zu erreichen. Es muss ein Weg gefunden werden, der es ermöglicht die Wiedergabe eines Tracks vollkommen manuell zu gestalten. Um das zu erreichen ist folgendermaßen vorgegangen worden: Mit Hilfe des verwendeten Soundframeworks können intern beliebig viele so genannte Streams angelegt werden. Um die Turntables für djBench zu implementieren wurden drei dieser Audio-Streams benutzt. Der erste Stream kann als File Handle angesehen werden. Er ist lediglich dazu da, eine Audiodatei zu öffnen, zu dekodieren und für weitere Schritte bereit zu stellen. Mit dem zweiten Stream, der lesend auf die dekodierten Daten des Ersten zugreift, wird die Vorwärts- und Rückwärtswiedergabe realisiert. Über ein Flag im Funktionsaufruf kann die Abspielrichtung bestimmt werden. Die Daten dieses Streams sind als Quelle mit dem Dritten verknüpft. Der letzte Stream ermöglicht die Anung der Abspielgeschwindigkeit. Anhand dieser Aufteilung können auf jeden geöffneten Track die gewünschten Änderungen separat angewendet werden. Um das realistische „Scratch“-Verhalten zu simulieren wird die Abspielgeschwindigkeit an die Rotation der Platte gekoppelt und kann dadurch intuitiv beeinflusst werden. Sobald die Geschwindigkeit einen negativen Wert erreicht, wir die Wiedergaberichtung umgekehrt.
Mischpult Die eben beschriebene Methodik der Nutzung verschiedener Streams eignet sich auch gut für die Realisierung der gewünschten Funktionalität des Mischpults. Neben der Verkettung dieser Streams ist es hier allerdings zusätzlich erforderlich beispielsweise mehrere Streams zu einem zusammenzufassen oder einen in mehrere gleiche aufzuspalten, quasi zu kopieren. Das Mischpult besteht aus zwei Hauptkanälen, den beiden angeschlossenen Plattenspielern. Diese haben den Aufbau, der bei der Beschreibung der Umsetzung der Turntables bereits erläutert wurde. Beide Kanäle werden durch einen so genannten Mixer-Stream zusammengefasst, welcher später als Ausgangskanal genutzt wird. Um das Vorhören und Mixen unabhängig vom eigentlichen Masterausgang zu ermöglichen, gibt es für jeden Kanal eine Kopie, die sich genau wie der ursprüngliche Stream verhält. Diese Kopien laufen in einem zweiten 29
PROGRAMMIERHANDBUCH
Mixer-Stream zusammen und bilden dadurch einen unabhängigen zweiten Mixer. Die für jeden Kanal verfügbaren Equalizereinstellungen werden bereits vor dem Klonen auf das Audiomaterial angewendet und sind dadurch für Master und Cue gleichzeitig hörbar. Den mehr oder weniger dritten Hauptkanal am Mischpult bildet die Effekteinheit. Allerdings ordnet sie sich nicht neben den beiden anderen Eingängen ein, sondern wird erst auf die Summe vor dem Ausgang angewendet. Dadurch ist es nicht möglich verschiedene Effekte gleichzeitig auf einzelnen Kanälen zu haben, was aber laut Spezifikation auch nicht angedacht ist. Das Signal, welches aus der Zusammenfassung der beiden Eingänge, den möglichweise angewendeten Equalizern und der Effekteinheit besteht, wird nun ein weiteres Mal auf gesplittet. Dadurch ist es möglich beispielsweise zwei verschiedene Soundkarten oder eine Soundkarte und den Streaming-Server als getrennte Ausgänge anzusprechen. Bei der Nutzung des Streamings ist im ganzen Ablauf darauf zu achten, dass Modifikationen des Audiosignals auch direkt auf den Rohdaten der Eingänge ausgeführt werden muss. Manche Funktionen der Audiobibliothek machen Modifikationen zwar lokal hörbar, verändern die Daten des Audiosignals allerdings nicht. Effekte und Equalizer wären für entfernte Zuhörer am Ende der Streams nicht zu hören. Für die Kanäle zum Vorhören muss auf diesen Umstand nicht geachtet werden, da sie nur zur lokalen Nutzung vorgesehen sind.
Streaming Wie in den Vorüberlegungen beschrieben, soll für djBench keine eigener Streamingdienst realisiert, sondern ein verfügbarer Dienst verwendet und entsprechend in das Programm eingebunden werden. Die verwendete Audiobibliothek BASS bietet dafür geeignete Methoden als Schnittstellen an und es ist lediglich dafür zu sorgen einen geeigneten Audio Encoder und einen Streaming-Server bereitzustellen. Für die Kodierung der Audiodaten wurde LAME MP3 Encoder ausgewählt. Er ist weit verbreitet und bietet eine gute Qualität. Durch eine entsprechende Methode wird der Encoder von der Audiobibliothek aufgerufen und wandelt die Daten der Kopie des Master-Streams um, damit sie für den Streaming-Einsatz geeignet sind. Im nächsten Schritt werden diese Daten durch den Aufruf einer weiteren Bibliotheksfunktion an den Streaming-Server weitergereicht. Der Server sorgt dann dafür, dass potentielle Zuhörer das Audiomaterial ver30
PROGRAMMIERHANDBUCH
wenden können. Aus Performance-Gründen ist es ratsam den Streaming-Server auf einem dedizierten System laufen zu lassen. Da die Bibliothek und die beiden externen Programme sehr eigenständig für die Erledigung ihrer Aufgaben sorgen, ist an dieser Stelle kein weiterer großer Implementierungsaufwand nötig. 3.3.3 Lightshow Empfangen der Sound-Daten Nach dem Starten der Anwendung wird eine Verbindung zu einem Streaming-Server aufgebaut, der den Sound des CoBench empfängt. Es kann sich dabei um Shoutcast oder Icecast handeln und die IP kann wie im Benutzerhandbuch beschrieben über eine INI-Datei gesetzt werden. Die Funktionalität übernimmt zu großen Teilen die BASS-Bibliothek, die über eine Schnittstelle zum Verbinden und Abspielen verfügt. Falls die Verbindung aus irgendeinem Grund getrennt wird, versucht sich die Anwendung im Abstand von fünf Sekunden neu zu verbinden. Dies geschieht über einen Thread, der im Hintergrund läuft und stets die Verbindung überprüft. Alle Sound-Operationen, wie auch die folgenden, sind in einer Sound-Klasse gekapselt. Verarbeitung der Sound-Daten Da für das Verteilen des Sounds ein Streaming-Server verwendet wurde und damit ein Großteil der Arbeit durch die BASS-Bibliothek abgenommen wird, müssen lediglich die Daten von der FFT-Darstellung in einen nutzbaren Frequenz-Bereich umgerechnet werden. Dafür wurde eine Routine in der Sound-Klasse entwickelt, die die Transformation übernimmt. Die Anzahl der Unterteilungen des Spektrums kann dabei beliebig gewählt werden, je nachdem wie es für eine Visualisierung gewünscht ist. Bei der Towers-Visualisierung wird beispielweise in vier Frequenz-Bereiche aufgeteilt. Auf die damit erhaltenen Sound-Daten kann von einer Visualisierung direkt zugegreifen werden und anschließend weiterverarbeitet werden. Wiedergabe der Sound-Daten Mit BASS ist es möglich eine Tabelle aufzustellen, in der angegeben wird, welcher Kanal (links bzw. rechts) vom Stereo-Sound auf welcher Box abgespielt werden soll. Es findet hier also ein Upmixing in folgender weise statt: Upmix-Tabelle (Linke Spalte = linker Kanal, rechte Spalte = rechter Kanal): 01 Const float matrix[12] = { 02
1.0f, 0.0f, // Links vorne
03
0.0f, 1.0f, // Rechts vorne
04
1.0f, 0.0f, // Links hinten
05
0.0f, 1.0f, // Rechts hinten
06
1.0f, 1.0f, // Center Box
07
0.1f, 0.1f
// Subwoofer
08 }
Das Ansteuern der Bodenplatte der CAVE beispielsweise wird auf diese Weise realisiert. Zudem bietet BASS einen Tief--Filter an, der hier angewendet wird. Dieser leitet nur die Frequenzen weiter, die unter 50 Hertz liegen. Das Upmixing und der Filter konnten nur mittels eines zusätzlichen virtuellen Mixerkanals umgesetzt werden. Dieser empfängt die Daten aus dem Streaming-Kanal und verändert die Daten entsprechend, bevor sie abgespielt werden. Visualisierung des Sounds in 3D Es wurde ein Singleton-Objekt entwickelt, das alle verfügbaren Visualisierungen verwaltet. Zudem übernimmt es den Farbverlauf und das Wechseln von Visualisierungen sowie weitere Konfigurationen. Um eine klare Schnittstelle zu definieren, wurde eine abstrakte Klasse entwickelt, von der alle Visualisierungen erben müssen. 31
PROGRAMMIERHANDBUCH
Eine vererbte Klasse kann auf Werte wie die aktuelle Farbe zugreifen und diese benutzen. Außerdem gibt es einen custom-Wert, der beliebig verwendet werden darf. Dazu muss er im Konstruktor aktiviert werden. Dort wird auch der Name für die Visualisierung gesetzt. Dies sieht dann folgendermaßen aus: 01 M_bCustomizable = true; 02 M_strTitle = "Name der Visualisierung"
Alles was in der doRender-Methode steht, wird später aufgerufen. Es kann normaler OpenGL-Code benutzt werden, um Grafik-Effekte zu erzeugen. Die Sound-Daten befinden sich in der Member-Variablen m_ vSoundData. Wenn das Holen der Audio-Daten verändert werden soll, kann die Methode retrieveSoundData überschrieben werden, ansonsten findet standardmäßig eine Vier-Teilung des Spektrum statt. Steuerung der Visualisierungen über das Netzwerk Um die Effekte der Lightshow über das Netzwerk steuern zu können, agiert die Lightshow-Anwendung als T-Server. Dadurch kann sich ein beliebiges Programm verbinden und Befehle senden. Die Netzwerkkommunikation wurde mit der boost::asio-Bibliothek realisiert. Sobald sich eine Anwendung mit dem Server verbindet, werden dieser die Namen der verfügbaren Visualisierungen geschickt. Außerdem wird übermittelt, ob der custom-Wert genutzt wird. Anschließend können Kommandos ausgeführt werden, die in der Protokoll-Datei visualization_control_protocol.h aufgeführt sind. Der Port für den Server lautet 3334. Für die CoBench-Anwendung wurde dieses Protokoll genutzt, um das Lightshow-Modul zu realisieren. Dafür ist die Klasse djbVisualizationControl erstellt worden, die sich mit dem Server verbindet und das Senden der Befehle übernimmt. Diese wird nur dann instanziiert, wenn in den Einstellungen angegeben wurde, dass die Lightshow genutzt werden soll. Bei einem Verbindungsverlust wird automatisch ein Neuaufbau versucht. Wegen dieser Überprüfung wurde T als Netzwerkprotokoll verwendet. 3.4. Beschreibung grundlegender Datenstrukturen Im Folgenden Abschnitt sind einige der zentralen Datenstrukturen von der djBench-Anwendung aufgelistet und beschrieben. 3.4.1 CoBench-App Speicherung aller relevanten Daten eines Musikstücks Für das Laden und Abspielen eines Tracks sind sowohl die Speicherung des Dateinamens als auch der absolute Pfad zum Speicherort wichtig. Zusätzlich wird das ende Albumcover für die Darstellung eines Tracks innerhalb einer Musikbibliothek benötigt, das (falls vorhanden) aus dem ID3-Tag extrahiert und auf der Festplatte abgelegt werden kann. Auch den Pfad zum Speicherort gilt es dabei festzuhalten. Gleiches gilt für die Meta-Informationen „Künstlername“ sowie „Lied-“ und „Albumtitel“. Die relevanten Daten für jeweils einen Track sind durch die Datenstruktur „track“ wie folgt dargestellt: 01 Typedef struct { 02
string name;
03
string artist;
04
string title;
05
string album;
06
string image;
07
string path;
08 } track;
Alle eingelesenen Lied-Informationen bilden eine Liste (aus der C++ „Standard Template“-Bibliothek) mit Elementen diesen Typs. Lied-Informationen in einem XML-Dokument In der XML-Datei zum cachen der Musikbibliothek werden sämtliche Informationen der Track-Liste gespeichert. 32
PROGRAMMIERHANDBUCH
Die zugrunde liegende XML-Struktur sieht dabei wie folgt aus: 01
02
Der Inhalt des Dokumentes wird von dem root-Element
umschlossen, was eine Musikbibliothek kennzeichnet. Innerhalb des root-Elements wird jeder Track mit dem Schlüsselwort
eingeleitet. Ein track-Element beinhaltet schließlich die jeweiligen Lied-Informationen. Somit lässt sich eine beliebig große Musikbibliothek abbilden. 3.4.2 CAVE-App Partikel Für die „Hurricane”-Visualisierung wurde ein einfaches Partikelsystem entwickelt. Jedes einzelne Partikel ist ein Objekt mit folgenden Eigenschaften: 01 boost::array
m_vPosition; // Aktuelle Position 02 boost::array
m_vDirection; // Flug-Richtung 03 float m_fSize; // Größe 04 int m_iBirthday; // Geburtszeitpunkt 05 int m_iLifetime; // Lebensdauer 06 bool m_bLife; // Flag, ob das Partikel lebendig ist 07 bool m_bIsDying; // Flag, ob das Partikel gerade stirbt 08 bool m_bBorn; // Flag, ob das Partikel geboren wurde 09 float m_fFadeSpeed; // Geschwindigkeit für das Verschwinden 10 float m_fFadeInSpeed; // Geschwindigkeit für das Erscheinen 11 float m_fOpacity; // Aktuelle Transparenz 12 float m_fSpeed; // Flug-Geschwindigkeit
Über eine Fabrikmethode kann ein neues Partikel erzeugt werden. T Kommunikation zur Steuerung der Visualisierungen Bei der Umsetzung der Steuerungsbefehle über das Netzwerk mittels T wurde die „asio“-Bibliothek aus dem „boost“-Paket verwendet. Dabei ist es notwendig eine eigene Klasse für den Server und eine für die Verbindung zu einem Client zu entwickeln. Der Server akzeptiert Anfragen oder lehnt sie ab und übernimmt somit die Verwaltung der Clients. Sobald eine Verbindung hergestellt wurde, wird sie abgespeichert und fortlaufend auf ihre Gültigkeit überprüft. Über eine „Connection“, die einen Socket enthält, werden Befehle des Clients empfangen und beim Verbindungsaufbau werden einmalig die verfügbaren Visualisierungen übermittelt. Farbe Für das Überblenden der Farben von den Visualisierungen wurde eine Farb-Klasse erstellt. Diese enthält die drei Farbanteile Rot, Grün und Blau und einen Alpha-Wert. Die Klasse verfügt über eine Fabrikmethode zum Erzeugen von Farb-Objekten. Es können folgende vorgefertigte Farben erzeugt werden, die in einem Enumeration-Typ abgelegt sind:
33
PROGRAMMIERHANDBUCH
01 enum Color::ColorPreset { 02
Blue, Red, Yellow, Green, ColorCount
03 };
ColorCount dient dabei nur zur Bestimmung der Anzahl der vordefinierten Farben. 3.5 Programmorganisationsplan yf*-Klassen Alle Klassen mit dem Präfix „yf” wurden durch die eyefactive GmbH zur Verfügung gestellt und bilden das Framework, das zur Entwicklung einer Multitouch-Anwendung auf der CoBench verwendet werden kann. Die Klasse „yfApp“ steht als einzige in direkter Verbindung mit den für die djBench erstellten djb*-Klassen und kann als „Hauptprogramm“ angesehen werden.
djb*-Klassen Das Präfix „djb“ kennzeichnet alle Klassen, die für die djBench angelegt wurden. Sie bilden den Kern des Programms. Der Großteil der Klassen sind Widgets, die die Widgetklassen des Frameworks verwenden bzw. erweitern und für die Gestaltung der Programmoberfläche benötigt werden. Die restlichen Klassen enthalten die Programmlogik und Dateioperationen.
34
PROGRAMMIERHANDBUCH
Lightshow Klassen Für die Lichtshow in der CAVE wurde ein, von der FH Wedel zur Verfügung gestelltes, Framework zur 3D-Darstellung und Tracking verwendet. Es dient dabei als Grundgerüst und wurde um entsprechende Funktionalitäten erweitert. Die OpenAL-Bibliothek wurde dabei durch die BASS-Bibliothek ersetzt, um die Möglichkeit zu erhalten mit den Streaming-Servern kommunizieren und Audio-Daten auszulesen zu können. In der io.p-Datei des VR-Frameworks wird das Sound-Objekt, der T-Server zum Empfangen von Kommandos und das Manager-Objekt für die Visualisierungen initialisiert und aktualisiert.übernehmen alle weiteren Funktionalitäten. Dadurch ist die Lightshow-Anwendung relativ lose gekoppelt an das Framework gekoppelt.
Icecast und Lame Die Streaming Funktionalität von djBench wurde nicht selbst implementiert. Sie baut zum einen auf die Unterstützung des verwendeten Audio-Frameworks BASS, sowie auf die Verwendung zweier externer Programme auf. Die Daten werden dabei über entsprechende Methoden des Frameworks in den Encoder (Lame) und anschließend an den Streaming-Server Icecast geleitet. 3.6 Programmtests Damit die Qualität einer Software sichergestellt werden kann muss sie intensiv getestet werden. Das Testen kann und muss dabei auf verschiedenen Programmebenen durchgeführt werden. Im Idealfall sind die Testfälle aus der zugrunde liegenden Spezifikation abzuleiten und bereits vor der eigentlichen Implementierung fertigzustellen. Funktionale Tests können natürlich erst nach der Fertigstellung erfolgen. Da bei der Entwicklung von djBench keine neuartigen Datenstrukturen implementiert wurden und die Software selbst keine komplexen Berechnungen durchführt, sondern eine bestimmte Funktionalität erfüllen soll, wurde auf Tests auf niedrigster Ebene in Form von Unit-Tests verzichtet. Die funktionalen Tests, die während bzw. nach Fertigstellung der einzelnen Teile durchgeführt wurden lassen sich gedanklich in drei Abschnitte aufteilen. 35
PROGRAMMIERHANDBUCH
Oberfläche Das Testen der Programmoberfläche von djBench wurde während der gesamten Entwicklungsphase kontinuierlich durchgeführt. Die Oberfläche besteht aus vielen einzelnen, simplen Widgets, die zu größeren Objekten zusammengesetzt wurden. Durch die Verwendung von Grafiken als „Skins“ bzw. Texturen erhält die Anwendung erst ein realistisches Äußeres. Auf dessen Basis wurden die funktionalen Tests der Programmoberfläche durchgeführt. Dabei galten verschiedene Bedienungsschritte aus realen Abläufen als Vorlage. Maßgabe für das erfolgreiche Bestehen der Tests war die intuitive Umsetzung der Handlungsschritte mit dem Programm. Schwerwiegende Konstruktionsfehler der Bedienelemente konnten dabei meist nicht festgestellt werden. Vielmehr wurden durch diese Tests logische Fehler, wie die Rückgabe falscher Positionswerte der Potentiometer und Fader, aufgedeckt und korrigiert. Sound Eine gemäß den gewünschten Anforderungen funktionierende Soundwiedergabe bildet das Akzeptanzkriterium für den erfolgreichen Projektabschluss. Aus diesem Grund wurde in diesem Bereich der meiste Testaufwand betrieben. Zunächst wurden, soweit möglich, die Schalter, Drehknöpfe und Schieberegler des Mixers für sich allein auf ihre korrekte Funktionalität überprüft. Eine Bedienung über die Programmoberfläche musste die entsprechende Veränderung in der Soundwiedergabe bewirken. Auftretende Fehler, welche meistens nur aus einer falschen Umrechnung der Parameter bestanden, konnten dadurch direkt behoben und eine Verkettung von Fehlern bei komplexeren Benutzeraktionen vermieden werden. Im Anschluss wurde das Mischpult als ganzes, durch Nachempfindung einer Überblendung von zwei Tracks, in seiner Funktionsweise getestet. Da bei diesem Ablauf jeder Regler des Mixers bedient wird, war, nach Korrektur der festgestellten Fehler, die einwandfreie Funktion des Mischpults sichergestellt. Große Probleme sind dabei nicht aufgetreten. Die Nachbesserungen beschränkten sich auf geringe Parameteranungen bei der Effekteinheit und die Behebung der falschen Beeinflussung der Lautstärkeregler untereinander. Während die Überprüfung der korrekten Lautstärkewerte im Zweifelsfall auch durch die Ausgabe der Zahlenwerte hätte überprüft werden können, gestaltete sich der Test der Equalizer und Effekte hingegen etwas schwieriger. Referenzen bildeten hierbei andere Musikprogramme und ein echtes Mischpult mit Effekteinheit. Durch anwenden gleicher Soundveränderungen einerseits in djBench und andererseits im Referenzprogramm bzw. am Mischpult wurde das akustische Ergebnis verglichen. Neben der Funktionalität der Soundmodifizierung des Mischpults ist es auch seine Aufgabe das Audiosignal zur direkten Ausgabe weiterzuleiten. Hierfür müssen zwei Kriterien erfüllt sein. Einerseits die lokale Wiedergabe des Vorhör-Kanals und die Ausgabe des Masterkanals, sowie andererseits die Übertragung zur entfernten Wiedergabe an den Streaming-Server. Das Umschalten der lokalen Wiedergabemöglichkeiten und wählen von verschiedenen Soundkarten konnte einfach überprüft und sichergestellt werden. Beim Test der Wiedergabe des Icecast-Streams mussten allerdings Latenzzeiten festgestellt werden. Diese waren zwar deutlich niedriger, als die Werte des Shoutcast-Streams, von Echtzeit-Playback konnte allerdings nicht gesprochen werden. Da dieser Umstand aber bereits bekannt und kalkuliert war, wurde lediglich auf eine „nicht zu große“ Verzögerung geachtet. Den wichtigsten Teil der Soundtests stellte die Umsetzung des Plattenspielers bzw. des „Scratchens“ dar. Hier musste zum einen die Funktionsweise der Geschwindigkeitsänderung geprüft werden und zum anderen die Bedienung des Plattenspielers „von Hand“, also das Scratchen, um die, laut Spezifikation geforderte, Qualität zu erreichen. Der Pitch-Regler (für Geschwindigkeitsänderungen) funktionierte auf Anhieb und ohne Probleme. Das Scratchverhalten hingegen bereitete einige Probleme. Die manuelle Wiedergabe bei sehr langsamer Geschwindigkeit klang sehr ruckelig und stockte, die Wiedergabe bei sehr hoher Geschwindigkeit klang unnatürlich und Artefakte waren hörbar. Dadurch waren an dieser Stelle häufige Nachbesserungen nötig. Letztendlich wurde aber ein zufriedenstellendes Ergebnis erreicht und die akustische Empfindung des Scratchens auf der djBench kommt der Realität sehr nahe.
36
PROGRAMMIERHANDBUCH
Lichtshow Die Lichtshow konnte unabhängig von den restlichen Programmteilen getestet werden. Dazu wurde eine beliebige Audioquelle benötigt, um die Frequenzen, die die Bewegung des Lichtes beeinflussen, auszulesen. Da es sehr schwierig und abstrakt ist, sich einen gewünschten Lichteffekt allein anhand von Zahlenwerten im Kopf vorzustellen wurde hier während der Implementierung bereits sehr viel getestet. Dabei dienten die Visualisierungen von diversen Medienplayern als Referenzen. Getestet wurde das Reaktionsverhalten der Animation auf Synchronität zur Musikwiedergabe, die konkrete Umsetzung der verschiedenen Darstellungen, sowie das Wechseln zwischen ihnen.
37