Java-AG

Werbung
Java - AG
Audio - Ausgabe mit Java
3. Juli 2001
Frank Münster
Arten von Sound
„Sampled“
MIDI
Sampled:
MIDI:
Audiodaten liegen in
einer Sounddatei vor
Audiodaten liegen in Form
bestimmter abrufbarer
Klänge innerhalb der
Hardware vor.
( MIDI - Musical Instrument
Digital Interface )
Packages des Java-Sound API
javax.sound.sampled
javax.sound.midi
javax.sound.sampled.spi
javax.sound.midi.spi
Wir beschäftigen uns mit dem „sampled“-Package.
Die „ spi “-Packages („Service Provider Interface“)
dienen der „Erweiterung“ von Java, z.B. zusätzliche
Unterstützung von .mp3 Dateien, etc.
FileFormat / AudioFileFormat
Der Unterschied zwischen FileFormat und AudioFileFormat:
AudioFormat: Datenformat, Art des Sample, Art der
Codierung
AudioFileFormat: Dateiformat, die Art, wie die Daten in
Dateiform gespeichert werden.
 Unterstützte FileFormats:  Unterstützte
AudioFileFormats:
 .wav
 PCM
 .au
 mu-law ( m-law )
 .aiff
 a-law
 .rmf
Das „Sampled“-Package
Wichtige Klassen:
Wichtige Interfaces:
AudioSystem
AudioInputStream
AudioFormat
DataLine.Info
Line
Clip
SourceDataLine
Mixer
LineListener
Audio-Wiedergabe
Interface Clip
Interface SourceDataLine
Geben wir Sound-Dateien als Clip wieder, so wird die
komplette Datei vor dem Abspielen in den Speicher
geladen. Wir haben die Möglichkeit des „loopens“,
entweder den kompletten Sound oder Ausschnitte.
void loop(int count); void setLoopPoints(int start, int end)
Unter Verwendung einer SourceDataLine werden jeweils nur
Stücke der Datei in einen Buffer geladen, diese werden dann
abgespielt, währenddessen wird der Buffer erneut mit den
darauf folgenden Daten beschrieben. Somit eignet sich die
SouceDataLine besonders für große Dateien.
Interface Line
Die zuvor beschriebenen Interfaces Clip und
SourceDataLine sind vom Interface Line abgeleitet.
Abspielen einer Datei - Vorgehensweise
 1. „File“-Objekt mit der gewünschten Dataei anlegen
 2. „AudioInputStream“ anfordern
 3. „AudioFormat“ des Sample überprüfen
 4. Zum AudioFormat „passende“ Line anfordern
 5. ggf. „LineListener“ hinzufügen
 6. Line öffnen
 7. Wiedergabe starten
 8. ggf. Wiedergabe stoppen
 9. Line schließen
File-Objekt anlegen
import java.io.File;
import java.io.IOException;
...
File audiodatei = new File(„e:\\beispiele\\beisp.wav“);
// Verzeichnisse werden mit doppeltem
// Backslash angegeben
AudioInputStream anfordern
AudioInputStream audioinput = null;
try
{
audioinput =
AudioSystem.getAudioInputStream(Audiofile);
}
catch (Exception e)
{
...
}
AudioFormat des Sample überprüfen
...
AudioFormat format = audioinput.getFormat();
System.out.println(format.toString() );
DataLine.Info info = new DataLine.Info(Clip.class,
format); // DataLine.Info Objekt wird später zum
// anfordern einer „passenden“ Line (hier vom
// Typ „Clip“) benötigt.
„Passende“ Line anfordern
...
Clip line;
try
{
line = (Clip) AudioSystem.getLine(info);
// „info“ ist das zuvor angelegte DataLine.Info
// Objekt. Java kann über dieses Objekt eine Line
// mit den für das Sample benötigten Spezi// fikationen anfordern)
catch (Exception e)
{...}
„LineListener“ hinzufügen
try
{
line = (Clip) AudioSystem.getLine(info);
line.addLineListener(this);
}
catch ...
...
public void update(final javax.sound.sampled.LineEvent p1)
{
if (p1.getType().equals(LineEvent.Type.STOP))
...}
{...}
Öffnen, starten etc. der Line
try
{
line = (Clip) AudioSystem.getLine(info);
line.open(audioinput);
line.start(); // oder line.loop(n);
...
// evtl. line.stop();
}
catch ...
Line schließen
...
public void update(final javax.sound.sampled.LineEvent p1)
{
if (p1.getType().equals(LineEvent.Type.STOP))
{ line.close(); }
...
}
// Line muß unbedingt geschlossen werden!!!
// Wird das Programm vor dem Schließen beendet, ist ein
//Schließen der Line nicht mehr möglich, sie bleibt bis
//zum Neustart des Rechners „reserviert“.
// Mögl. Resultat: „Audio Device unavailable“
Line schließen (2)
Von Line abgeleitete Objekte ( SourceDataLine, Clip, Mixer, Port, etc.)
repräsentieren physische Einheiten innerhalb der Hardware (z.B. auf der
Soundkarte).
Daher ist die Erzeugung dieser Objekte hardwarebedingt, d.h. es können
nicht beliebig viele dieser Objekte gleichzeitig existent sein. Schließen
wir die Lines nach der Verwendung nicht, so kann diese Line für nichts
Anderes mehr verwendet werden, da sie nicht „freigegeben“ wurde. Die
nächste Anforderung muß also auf eine andere Line zurückgreifen.
Gibt es keine andere Line mehr, wirft Java eine
LineUnavailableException aus. Auch andere Anwendungen können in
diesem Fall keine Sounds mehr abspielen und liefern Meldungen wie
z.B: „Audio Device unavailable“.
Besonderheiten SourceDataLine
Daten werden Stück für Stück in einem
Buffer gelesen und verarbeitet
Buffer wird in einer Schleife jeweils mit
neuen Daten gefüllt
Schleife wird bei EndOfFile (Rückgabewert
-1) unterbrochen (oder bei Benutzer-Stop)
Line wird geschlossen
SourceDataLine
try
{ line = (SourceDataLine) AudioSystem.getLine(info);
line open(format, int b); // b ist die Größe des Buffers in
// Bytes, den die Line besitzen
// soll. b kann auch weggelassen
// werden, Java legt dann die Buffergröße
// fest.
int BUFFER_SIZE = line.getBufferSize();
int read = 0;
byte[] data = new byte[BUFFER_SIZE]);
int written;
SourceDataLine (2)
while (read != -1)
//read wird -1, wenn Dateiende erreicht
{
read = audioinput.read(data, 0, BUFFER_SIZE);
// 0 (int offset) bedeutet, daß die
// Datei beginnend bei Position 0
// (Dateianfang) gelesen werden
// soll.
if(read >= 0)
{ written = line.write(data, 0, read); }
else break;
}
line.drain();
} // Ende von try{}
catch...
finally{line.close();}
Methoden
AudioSystem.getAudioInputStream(file);
// Liefert einen AudioInputStream, mit welchem die Daten aus
der Sounddatei gelesen werden können.
Audioinputstream.getFormat();
// Liefert ein AudioFormat - Objekt, welches Informationen
über Das Format der in der Datei enthaltenen Audiodaten
enthält.
new DataLine.Info(Clip.class, audioformat);
// Erzeugt ein DataLine.Info - Objekt anhand der AudioFormatInformationen. Unter der Angabe der gewünschten Line (hier
Clip) enthält das erzeugte Objekt speziellere Informationen
als AudioFormat, welche zur Anforderung einer passenden
„Line“ benötigt werden.
Methoden (2)
DataLine.Info info.toString();
// Wandelt die im DataLine.Info Objekt enthaltenen Info‘s in
einen String um, der dann angezeigt werden kann.
Clip line =(Clip) AudioSystem.getLine(info);
// Liefert eine den Spezifikationen des DataLine.Info
Objektes entsprechende Line (hier vom Typ Clip). Der Aufruf
dieser Methode muß innerhab von „try“ stehen, da
möglicherweise keine entsprechende Line vorhanden ist;
andernfalls wird es gar nicht erst von Java compiliert.
line.open(); line.start(); line.loop(n); line.stop();
line.close();
// Verwendung selbsterklärend, loop(n) kann nur bei Lines vom
Typ Clip verwendet werden, n ist die Anzahl der
Wiederholungen
Methoden (3)
line.addLineListener(this);
// „heftet“ den LineListener (this, da er in diese Klasse
implementiert ist, und Objekte dieser Klasse somit auch
LineListener-Objekte sind) an die Line. In der „update“Methode kann der LineListener dann auf „LineEvents“ reagieren
(z.B. STOP-Event, CLOSE-Event, etc.)
int read = audioinputstream.read(byte[] data, int offset, int
Buffersize);
// Das Array repräsentiert den Buffer, Offset die
Startposition, Buffersize die Größe des Buffers, also die
Größe des Arrays. Beginnend bei Offset werden Daten aus
audioinputstream in den buffer gelesen, wobei die Methode
jeweils die Anzahl der gelesenen Bytes zurückliefert
(int read).
Methoden (4)
int written = line.write(byte[] data, int Offset, int read);
// Umgekehrt werden hier die zuvor in den Buffer gelesenen
Daten in die Line „geschrieben“, damit eine Wiedergabe
erfolgen kann.
line.drain();
// Befinden sich noch Daten im Buffer, werden diese noch
gelesen und verarbeitet (abgespielt), bis der Buffer leer
ist.
line.flush();
// Die restliche Daten werden „weggespült“, ohne daß sie
weiter verarbeitet werden.
Literatur
Leider läßt sich zur Zeit noch nicht allzuviel Literatur zu
diesem Thema finden, möglicherweise auch weil das Java
Sound-API erst seit Version 1.3 im JDK enthalten ist. Zuvor
war Sound in Java nur bedingt möglich, und ohne größere
Probleme nur in Applets.
Zu empfehlen ist der Java Sound-API Programmer‘s Guide
von Sun, welchen man sich unter
http://ftp.java.sun.com/docs/j2se1.3/javasound.pdf
als pdf (Adobe Acrobat) - Datei heruterladen kann.
Diese Anleitung ist allerdings in HTML-Form auch in die APIDocs, welche im GIS-Labor zugänglich sind, integriert.
Herunterladen