From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001 From: Sven Eisenhauer Date: Fri, 10 Nov 2023 15:11:48 +0100 Subject: add new repo --- .../hjp5/html/k100309.html | 604 +++++++++++++++++++++ 1 file changed, 604 insertions(+) create mode 100644 Master/Reference Architectures and Patterns/hjp5/html/k100309.html (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100309.html') diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100309.html b/Master/Reference Architectures and Patterns/hjp5/html/k100309.html new file mode 100644 index 0000000..496db4b --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100309.html @@ -0,0 +1,604 @@ + + + +Handbuch der Java-Programmierung, 5. Auflage + + + + + + + + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage +
 <<  +  <   +  >   + >>  + API  +Kapitel 49 - Sound +
+
+ + + + +

49.2 Gesampelter Sound

+
+ +
+ + + + +

49.2.1 Was ist Sampling?

+ +

+Das Sound-API macht eine sehr grundlegende Unterscheidung zwischen +gesampeltem Sound und Midi-Sound. Beim Sampling, das +wir in diesem Abschnitt behandeln wollen, wird ein Audio-Signal in +viele kleine Stücke zerlegt, deren Amplitude in sehr kurzen Abständen +mit Hilfe eines Analog-Digital-Konverters gemessen wird: +

+ + +

+ +

+Abbildung 49.1: Samplen eines Audio-Signals

+ +

+Die Frequenz, mit der die Abtastung geschieht, bezeichnet man als +Sampling Rate, und sie sollte mindestens doppelt so hoch sein +wie die größte aufzuzeichnende Frequenz. Bei Audio-CDs +beträgt sie 44100 Hz, und die Auflösung des A/D-Konverters +beträgt 16 Bit. Speichert man die so entstehenden Amplitudenwerte +fortlaufend ab, so kann man bei Kenntnis der Sampling-Rate daraus +später das Originalsignal näherungsweise rekonstruieren. +Sind Sampling-Rate und Auflösung hoch genug, kann das menschliche +Ohr keinen Unterschied zwischen gesampeltem und Originalsignal feststellen: +

+ + +

+ +

+Abbildung 49.2: Ein gesampeltes Audio-Signal

+ + + + +

49.2.2 Das Sampling-API

+ +

+Das Sound-API macht keine Annahmen über vorhandene Hardware oder +angeschlossene Geräte. Statt dessen stellt es Methoden zur Verfügung, +mit denen die vorhandene Hardware zur Laufzeit ermittelt und Objekte +zum Zugriff darauf beschafft werden können. Im Falle von gesampeltem +Sound dient dazu die Klasse AudioSystem +aus dem Paket javax.sound.sampled. +Sie besitzt eine Reihe von statischen Methoden, mit denen die grundlegenden +Hilfsmittel für den Umgang mit gesampeltem Sound beschafft werden +können: +

+ + + + +

Zugriff auf Audio-Dateien

+ +

+Die Klasse AudioSystem +stellt einige Methoden zum Zugriff auf Dateien mit gesampeltem Sound +zur Verfügung: +

+ + + + + +
+ +
+public static AudioFileFormat getAudioFileFormat(File file)
+  throws UnsupportedAudioFileException, IOException
+
+public static AudioFileFormat getAudioFileFormat(InputStream stream)
+  throws UnsupportedAudioFileException, IOException
+
+public static AudioFileFormat getAudioFileFormat(URL url)
+  throws UnsupportedAudioFileException, IOException
+
+
+public static AudioInputStream getAudioInputStream(File file)
+  throws UnsupportedAudioFileException, IOException
+
+public static AudioInputStream getAudioInputStream(InputStream stream)
+  throws UnsupportedAudioFileException, IOException
+
+public static AudioInputStream getAudioInputStream(URL url)
+  throws UnsupportedAudioFileException, IOException
+
+
+public static boolean isConversionSupported(
+  AudioFormat targetFormat,
+  AudioFormat sourceFormat
+)
+
+public static AudioInputStream getAudioInputStream(
+  AudioFormat targetFormat,
+  AudioInputStream sourceStream
+)
+
+
+
+javax.sound.sampled.AudioSystem
+ +

+Mit getAudioFileFormat +kann das AudioFileFormat +einer Sound-Datei ermittelt werden. Die Eingabedatei kann entweder +als File, +InputStream +oder URL +übergeben werden. Mit getAudioInputStream +kann ein AudioInputStream +beschafft werden, mit dem der Inhalt der Sound-Datei gelesen werden +kann. Auch hier darf der Parameter wahlweise vom Typ File, +InputStream +oder URL +sein. + +

+Die Klasse AudioSystem +unterstützt sogar Konvertierungen zwischen verschiedenen Formaten. +Ob eine bestimmte Konvertierung verfügbar ist, kann mit isConversionSupported +abgefragt werden. Wird getAudioInputStream +mit einem Zielformat und einem anderen AudioInputStream +als Parameter aufgerufen, führt die Methode die Konvertierung +durch und liefert einen AudioInputStream, +der das gewünschte Zielformat hat. + + + + +

Audio-Geräte beschaffen

+ +

+Die Klasse AudioSystem +stellt auch Methoden zum Zugriff auf Audio-Geräte zur Verfügung: +

+ + + + + +
+ +
+public static Mixer.Info[] getMixerInfo()
+
+public static Mixer getMixer(Mixer.Info info)
+
+public static Line getLine(Line.Info info)
+  throws LineUnavailableException
+
+
+
+javax.sound.sampled.AudioSystem
+ +

+Um herauszufinden, welche Mixer +verfügbar sind, muss zunächst getMixerInfo +aufgerufen werden. Der Rückgabewert ist ein Array mit Mixer.Info-Objekten, +das je vorhandenem Mixer +ein Element enthält. Durch Übergabe eines Mixer.Info-Objekts +an getMixer +kann der zugehörige Mixer +beschafft werden. Man kann allerdings auch ohne explizite Verwendung +eines Mixers gesampelten Sound ausgegeben, wenn mit getLine +direkt ein geeignetes Audio-Gerät beschafft wird. Dazu muss ein +Line.Info-Objekt +übergeben werden, das dessen Eigenschaften beschreibt. Wir werden +in Listing 49.1 zeigen, +wie das Line.Info-Objekt +konstruiert werden muss, um einen Clip +zu erzeugen. + + + + +

Die Steuerelemente eines Audio-Geräts

+ +

+Wir hatten eingangs erwähnt, dass eine Line +eine Reihe von Steuerlementen zur Verfügung stellt, mit denen +Parameter wie Lautstärke, Stereo-Panorama oder Hall eingestellt +werden können. Auf diese kann mit folgenden Methoden zugegriffen +werden: +

+ + + + + +
+ +
+public Control[] getControls()
+
+public boolean isControlSupported(Control.Type control)
+
+public Control getControl(Control.Type control)
+
+
+
+javax.sound.sampled.Line
+ +

+getControls +liefert ein Array aller verfügbaren Steuerelemente, die durch +Instanzen der Klasse Control +repräsentiert werden. Mit isControlSupported +kann durch Übergabe eines Control.Type-Objekts +festgestellt werden, ob ein bestimmter Typ vorhanden ist. Mit getControl +kann dieser schließlich beschafft werden. + +

+Control +ist die Basisklasse einer ganzen Gruppe von Kontrollelementen, die +sich durch den Datentyp des zu verändernden Parameters unterscheiden. +Es gibt die Unterklassen BooleanControl, +EnumControl, +FloatControl +und CompoundControl. +Ein FloatControl +beispielsweise dient zur Veränderung eines Fließkommawerts +(wie etwa der Lautstärke), während ein BooleanControl +einen An-/Aus-Wert verändern kann (beispielsweise die Stummschaltung +eines Elements). Die wichtigsten Methoden der Klasse FloatControl +sind: +

+ + + + + +
+ +
+public float getMaximum()
+public float getMinimum()
+
+public float getValue()
+public void setValue(float newValue)
+
+
+
+javax.sound.sampled.FloatControl
+ +

+Mit getMinimum +und getMaximum +können der kleinste und größte einstellbare Wert abgefragt +werden, mit getValue +der aktuelle. Mit setValue +kann der Wert des Controls verändert werden. + +

+Die Type-Klassen der einzelnen +Steuerelemente besitzen jeweils eine Reihe von vordefinierten Konstanten, +die an getControl +übergeben werden können. Für FloatControl.TYPE +sind das beispielsweise MASTER_GAIN +zur Einstellung der Lautstärke oder PAN +zur Veränderung des Stereo-Panoramas. + +

+Ein Steuerelement des Typs MASTER_GAIN +bestimmt die Gesamtverstärkung, die das Audio-Element dem Ursprungssignal +hinzufügt. Ihr Wert wird in Dezibel +(dB) angegeben, wobei positive Werte +eine Verstärkung und negative eine Abschwächung des Eingangssignals +anzeigen. Das Dezibel ist eine logarithmische Maßeinheit, die +den Verstärkungsfaktor durch die Formel 10dB/20 ausdrückt. +20 dB entsprechen also einer 10-fachen Verstärkung, -40 dB einer +100-fachen Abschwächung. 0 dB bedeutet, dass die Stärke +des Ausgangs- im Verhältnis zum Eingangssignal unverändert +bleibt. + +

+Ein Steuerelement des Typs PAN +bestimmt die Lage des Audio-Signals im Stereo-Panorama. Es kann Werte +von -1.0 (ganz links) bis +1.0 (ganz rechts) annehmen. Ein Wert von +0 legt das Signal in die Mitte. + + + + +

Der Clip

+ +

+Ein Clip +ist eine besondere Form einer DataLine, +der alle Audiodaten komplett im Hauptspeicher hält. Wie jede +Line +muss er vor der Verwendung durch Aufruf von open +geöffnet werden und nach Gebrauch mit close +geschlossen werden. Zum Abspielen stellt er folgende Methoden zur +Verfügung: +

+ + + + + +
+ +
+public void start()
+public void stop()
+
+public boolean isRunning()
+
+
+
+javax.sound.sampled.Clip
+ +

+Ein Aufruf von start +startet das Abspielen des Clips, mit stop +wird es angehalten. Mit isRunning +kann überprüft werden, ob die Wiedergabe noch läuft +oder bereits beendet wurde. +

+ + + + + + + + + +
+ +

+Die Methode start +ist nicht modal, d.h. sie wartet beim Aufruf nicht, bis der +Clip vollständig abgespielt ist. Sie initiiert lediglich den +Abspielvorgang und kehrt dann sofort zum Aufrufer zurück. Falls +dieser auf das Ende warten will, muss er entweder durch wiederholten +Aufruf von isRunning +den Status des Clips abfragen oder sich bei diesem als Listener registrieren +und auf das STOP-Signal warten.

+ + + + +
 Hinweis 
+
+ + + + +

49.2.3 Abspielen einer Sample-Datei

+ +

+Nach den Erklärungen der vorangegangenen Abschnitte wollen wir +nun das Beispielprogramm zum Abspielen einer Sample-Datei vorstellen: + + +

+ + + + + +
+ +
+001 /* Listing4901.java */
+002 
+003 import java.io.*;
+004 import javax.sound.sampled.*;
+005 
+006 public class Listing4901
+007 {
+008   private static void playSampleFile(String name, float pan, float gain)
+009   throws Exception
+010   {
+011     //AudioInputStream öffnen
+012     AudioInputStream ais = AudioSystem.getAudioInputStream(
+013       new File(name)
+014     );
+015     AudioFormat format = ais.getFormat();
+016     //ALAW/ULAW samples in PCM konvertieren
+017     if ((format.getEncoding() == AudioFormat.Encoding.ULAW) ||
+018         (format.getEncoding() == AudioFormat.Encoding.ALAW))
+019     {
+020       AudioFormat tmp = new AudioFormat(
+021         AudioFormat.Encoding.PCM_SIGNED,
+022         format.getSampleRate(),
+023         format.getSampleSizeInBits() * 2,
+024         format.getChannels(),
+025         format.getFrameSize() * 2,
+026         format.getFrameRate(),
+027         true
+028       );
+029       ais = AudioSystem.getAudioInputStream(tmp, ais);
+030       format = tmp;
+031     }
+032     //Clip erzeugen und öffnen
+033     DataLine.Info info = new DataLine.Info(
+034       Clip.class,
+035       format,
+036       ((int) ais.getFrameLength() * format.getFrameSize())
+037     );
+038     Clip clip = (Clip)AudioSystem.getLine(info); 
+039     clip.open(ais);
+040     //PAN einstellen
+041     FloatControl panControl = (FloatControl)clip.getControl(
+042       FloatControl.Type.PAN
+043     );
+044     panControl.setValue(pan);
+045     //MASTER_GAIN einstellen
+046     FloatControl gainControl = (FloatControl)clip.getControl(
+047       FloatControl.Type.MASTER_GAIN
+048     );
+049     gainControl.setValue(gain);
+050     //Clip abspielen
+051     clip.start(); 
+052     while (true) {
+053       try {
+054         Thread.sleep(100);
+055       } catch (Exception e) {
+056         //nothing
+057       }
+058       if (!clip.isRunning()) {
+059         break;
+060       }
+061     }
+062     clip.stop();
+063     clip.close();
+064   }
+065 
+066   public static void main(String[] args)
+067   {
+068     try {
+069       playSampleFile(
+070         args[0],
+071         Float.parseFloat(args[1]),
+072         Float.parseFloat(args[2])
+073       );
+074     } catch (Exception e) {
+075       e.printStackTrace();
+076       System.exit(1);
+077     }
+078     System.exit(0);
+079   }
+080 }
+
+
+Listing4901.java
+ +Listing 49.1: Abspielen einer Sample-Datei

+ +

+Die Methode playSampleFile öffnet +zunächst einen AudioInputStream +und bestimmt dessen AudioFormat. +Ist dessen Kodierung ULAW +oder ALAW, +konvertiert es den Stream in das PCM-Format, +denn die anderen beiden Formate werden standardmäßig nicht +unterstützt. Anschließend wird ein DataLine.Info-Objekt +instanziert und in Zeile 038 +ein Clip +damit erzeugt. Dieser wird geöffnet und MASTER_GAIN +und PAN +werden auf die als Methodenparameter übergebenen Werte eingestellt. +In Zeile 051 wird der +Clip +gestartet und anschließend gewartet, bis er vollständig +abgespielt ist. + +

+Das Programm wird mit dem Namen der Datei und den Werten für +PAN +und MASTER_GAIN +als Kommandozeilenparameter aufgerufen. Es kann zum Abspielen von +wav-, aiff- und au-Dateien verwendet werden. +


+ + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 +
 <<  +  <   +  >   + >>  + API  +© 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de +
+ + + -- cgit v1.2.3