Schlagwort-Archive: Performance

„Wie bitte? Sound in Java? Wer würde denn so etwas wollen? Und dann wahrscheinlich auch noch 100% plattformunabhängig, ja? Wer Sound in Java haben will, soll wenigstens furchtbar leiden müssen. Also gut, wir machen es! Aber wir machen es so schlecht wie möglich, damit es niemand benutzen will!“

So oder so ähnlich muss das wohl bei Sun geklungen haben, als man sich irgendwann notgedrungen entschloss eine Java Sound API zu entwickeln. Ich kann mir jedenfalls nicht anders erklären, wieso es im Jahr 2012 immer noch nicht möglich ist, anständig mit JavaSound zu arbeiten, wenn es um so simple Dinge wie Ausgabe von z.B. WAVE-Audio geht. Es funktioniert – keine Frage – aber es macht keinen Spaß und es ist eine performancetechnische Katastrophe.

Gestraft ist man vor allen Dingen dann, wenn man sich aus Gründen des Minimalismus und im Sinne der größtmöglichen Platzersparnis entschließt, weitestgehend unabhängig von den bekannten teilweise mehrere Megabyte großen Java-Soundbibliotheken irgendwelcher Fremdanbieter bleiben zu wollen, die vereinzelt scheinbar sogar 3D-Audio in Java realisieren können. Aber sowas wollte ich gar nicht. Ich wollte einfach nur Audiodateien ausgeben ohne zusätzlichen Ballast von irgendwelchen Multimediabibliotheken und Java-Spiele-Komplett-Engines einbinden zu müssen. Ich bräuchte sowieso nur Start, Stopp und einstellbare Loops, mehr nicht. Zum Glück kann das JavaSound alles. Theoretisch.

Man hat die Wahl der Qual zwischen Pest und Cholera. Es gibt java.applet.AudioClip, welches den Vorteil hat, wirklich extrem einfach zu bedienen zu sein. Man kann da gar nichts falsch machen. Leider funktioniert das mit vielen WAVE-Dateien nicht, wenn sie z.B. eine etwas exotischere Samplingfrequenz haben. Auch gibt es Probleme mit sehr kurzen oder sehr langen Audiodateien. Und das Loopen und Abspielen ist mir dann eigentlich doch zu spartanisch. Looppoints wären schon nötig gewesen.

Für so etwas gibt es JavaSound mit javax.sound.sampled.Clip. Funktioniert ähnlich einfach, und bringt gleich die nötigsten Methoden mit, man kann sogar „Vor- und Zurückspulen“ und die Anzahl der Loops setzen. Clip leidet allerdings unter einer unglaublich miesen Performance. Das macht sich beim Abspielen eines einzelnen Samples gar nicht bemerkbar, außer man hält den Speicher- und CPU-Verbrauch seiner JVM sehr genau im Auge. Nein, das ganze Ausmaß des Grauens entdeckt man erst, wenn man – wie das z.B. in Spielesoftware recht üblich ist – den selben Clip in sehr kurzen Abständen mehrfach hintereinander abspielt (z.B. Sprung- oder Schieß-Geräusche). Die ganze Anwendung beginnt zu ruckeln, die Sounds werden teilweise verschluckt, manchmal überhaupt nicht abgespielt. Das ist so natürlich nicht akzeptabel. Ich vermute es liegt einfach am nicht unerheblichen Overhead für das Starten und Stoppen der Threads jedes einzelnen Sounds.

Es gab da noch eine weitere Kleinigkeit, die mir die Haare zu Berge stehen ließ. Bei Clip lassen sich zwar bequem die Looppunkte setzen, beim ersten Abspielen mittels loop() scheint es diese aber komplett zu ignorieren. Erst beim zweiten und bei jedem weiteren Mal geht es dann plötzlich wie gewünscht. Ich habe alle erdenklichen Kombinationen versucht, den Audiopuffer geleert, und alle Methoden getestet, die diese Klasse mit sich bringt. Da war nichts zu machen. Ich musste mir schließlich mit einem billigen Workaround behelfen, das Sample zuvor „heimlich“ einmal für eine Millisekunde anzuspielen und sofort mit anschließendem Rewind zurücksetzen, damit es dann gleich beim ersten Mal richtig loopt.

JavaSound hat noch soviele Kinderkrankheiten, dass es beinahe schon absurd ist, wenn man bedenkt, wie lange es Java schon gibt. Sogar die deutlich jüngere Dalvik VM unter Android bietet mehr und leistet mehr, ist vor allem sehr viel spielefreundlicher in dieser Hinsicht. Multimedia in Java ist wohl leider noch etwas, das äußerst stiefmütterlich von Sun bzw. Oracle behandelt wird. Okay, dafür gibt es ja wenigstens JavaFX 2.0. Vielleicht taugt das ja für solch verrückte und völlig abwegige Experimente wie Soundausgabe in einer Java-Anwendung.