Die Seite http://mozart.qvwx.de/ implementiert das musikalische Würfelspiel, das unter Mozarts Namen 1787 erschienen ist.
Wie funktioniert das?
Die Anwendung ist freiwillig komplexer gebaut als nötig. Sie ist als Spielprojekt konzipiert und besteht deswegen absichtlich aus
zu vielen Teilen und kombiniert willkürlich Sprachen und Technologien.
Architektur-Übersicht
Webserver
Der Webserver ist bis auf eine einzige Ausnahme nur damit befasst statische Inhalte auszuliefern. Das kann wirklich jeder. Die Ausnahme ist mozart.php
und wird weiter unten beschrieben.
Browser-Seite
Im Browser wird index.html
aufgerufen und lädt verschiedene Resourcen wie Bilder, Stylesheets und Javascript-Code nach. Die Seite verwendet jQuery und Bootstrap für Stil und „Belebung“ der Seite.
Das wesentliche Stück Code in mozart.js
ist ein asynchroner AJAX-Aufruf von mozart.php
. Dieses serverseitige Script ist dafür verantwortlich die „Komposition“ anzustoßen und gibt als Ergebnis einen Schlüssel zurück, der den Aufruf identifiziert. Der Schlüssel bezeichnet ein Verzeichnis auf dem Server, aus ihm und bekannten Dateinamen bildet der clientseitige
Javascript-Code HTML zur Anzeige und Download der Ergebnisse und hängt es in den DOM-Baum ein so daß der Benutzer es sehen kann.
mozart.php
mozart.php
ist ein triviales Script, das vom Webserver als CGI aufgerufen wird und an mozart.py
delegiert. Es erhält
den vom Benutzer gewählten Text bzw. die vorgefertigte Signatur als Query-Parameter und reicht diese an mozart.py
weiter. Es gibt die von mozart.py
erstellte Request-ID als einfachen Text an den Browser zurück. Es ist möglich dieses Skript einzeln aufzurufen. Zum Beispiel als mozart.php?arg=Beispiel. Der zurückgegebene Text muss dann in eine passende URL eingebaut werden um die Ergebnisdateien herunterzuladen.
mozart.py
Ist ein in Python verfasstes Stück Code, das den übergebenen Text liest und daraus eine Mozart-Signatur bestimmt. Im ersten Schritt wird dazu ein MD5-Hash über den gesamten Text berechnet. Die 16 Byte des Hashes passen gut zu den 16 Würfen mit zwei Würfeln, die Mozart für sein Spiel verlangt hat. Allerdings hat ein Byte 256 verschiedene Werte, während man mit zwei Würfen 2..12, also 11 verschiedene Werte werfen kann. mozart.py
verteilt die 256 Werte durch eine einfache Modulo-Rechnung auf 11 und benachteiligt dabei die Würfelwerte 10, 11 und 12 geringfügig. In Anbetracht der Tatsache, daß Mozart nicht explizit berücksichtigt, daß beim Wurf mit zwei Würfeln nicht alle Ergebnisse gleich wahrscheinlich sind, erlaube ich mir diese Ungenauigkeit.
Außerdem bestimmt mozart.py
eine UID als Request-ID.
Diese Request-ID und die aus dem Text berechnete Mozart-Signatur wird jetzt an initialize.ck
übergeben. Danach ruft es noch lilypond auf, um Notensatz und MIDI-Generierung zu erledigen.
initialize.ck
Mit initialize.ck
wird eine Reihe von ChuCK-Programmen gestartet, mit denen die Regeln von Mozart umgesetzt werden. Diese Programme implementieren in einer milde objektorientierten Weise die Takte des Originalwerks, treffen die vorgeschriebene Auswahl und „spielen“ sie mit zwei virtuellen Händen auf virtuellen Instrumenten.
Als Ausgabe produzieren sie einerseits eine WAV-Datei der Musik und als Seiteeffekt je eine Datei mit Notation für lilypond für die linke und die rechte Hand.
lilypond
lilypond wird als letztes in der Verarbeitungskette aufgerufen, setzt die Noten als PNG und PDF-Datei und schreibt eine MIDI-Datei die anstelle der umfangreichen und klanglich nicht besonders berauschenden WAV-Version zum Abspielen verwendet werden kann.