mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-04-14 14:43:33 +02:00
API angepasst und Javadoc verbessert
This commit is contained in:
@@ -18,8 +18,8 @@ public interface Audio {
|
|||||||
* {@code isLooping() == true}, dann muss auch immer
|
* {@code isLooping() == true}, dann muss auch immer
|
||||||
* {@code isPlaying() == true} gelten.
|
* {@code isPlaying() == true} gelten.
|
||||||
*
|
*
|
||||||
* @return {@code true}, wenn das Medium in einer Schleife
|
* @return {@code true}, wenn das Medium in einer Schleife abgespielt wird,
|
||||||
* abgespielt wird, {@code false} sonst.
|
* {@code false} sonst.
|
||||||
*/
|
*/
|
||||||
boolean isLooping();
|
boolean isLooping();
|
||||||
|
|
||||||
@@ -36,17 +36,28 @@ public interface Audio {
|
|||||||
*/
|
*/
|
||||||
void setVolume( double volume );
|
void setVolume( double volume );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gibt die aktuelle Lautstärkeeinstellung dieses Mediums zurück.
|
||||||
|
* <p>
|
||||||
|
* Die Lautstärke wird auf einer linearen Skale angegeben, wobei 0 kein Ton
|
||||||
|
* und 1 volle Lautstärke bedeutet. Werte über 1 verstärken den Ton des
|
||||||
|
* Mediums.
|
||||||
|
*
|
||||||
|
* @return Die Lautstärke als linear skalierter Wert.
|
||||||
|
*/
|
||||||
|
double getVolume();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Startet die Wiedergabe des Mediums und beendet die Methode. Das
|
* Startet die Wiedergabe des Mediums und beendet die Methode. Das
|
||||||
* Audio-Medium wird einmal abgespielt und stoppt dann.
|
* Audio-Medium wird einmal abgespielt und stoppt dann.
|
||||||
*/
|
*/
|
||||||
void playOnce();
|
void play();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Startet die Wiedergabe des Mediums und blockiert das Programm, bis die
|
* Startet die Wiedergabe des Mediums und blockiert das Programm, bis die
|
||||||
* Wiedergabe beendet ist.
|
* Wiedergabe beendet ist.
|
||||||
*/
|
*/
|
||||||
void playOnceAndWait();
|
void playAndWait();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spielt das Medium in einer kontinuierlichen Schleife ab. Die Methode
|
* Spielt das Medium in einer kontinuierlichen Schleife ab. Die Methode
|
||||||
|
|||||||
@@ -50,30 +50,53 @@ public class Mixer implements Audio {
|
|||||||
pAudio.setVolume(pVolumeFactor * volume);
|
pAudio.setVolume(pVolumeFactor * volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlaying() {
|
public boolean isPlaying() {
|
||||||
return audios.stream().anyMatch(aw -> aw.audio.isPlaying());
|
return audios.stream().anyMatch(aw -> aw.audio.isPlaying());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isLooping() {
|
public boolean isLooping() {
|
||||||
return audios.stream().anyMatch(aw -> aw.audio.isLooping());
|
return audios.stream().anyMatch(aw -> aw.audio.isLooping());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setVolume( double pVolume ) {
|
public void setVolume( double pVolume ) {
|
||||||
volume = (float) pVolume;
|
volume = (float) pVolume;
|
||||||
audios.stream().forEach(aw -> aw.audio.setVolume(aw.volumeFactor * pVolume));
|
audios.stream().forEach(aw -> aw.audio.setVolume(aw.volumeFactor * pVolume));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void playOnce() {
|
public double getVolume() {
|
||||||
audios.stream().forEach(aw -> aw.audio.playOnce());
|
return volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void playOnceAndWait() {
|
public void play() {
|
||||||
audios.stream().forEach(aw -> aw.audio.playOnce());
|
audios.stream().forEach(aw -> aw.audio.play());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void playAndWait() {
|
||||||
|
audios.stream().forEach(aw -> aw.audio.play());
|
||||||
while( audios.stream().anyMatch(aw -> aw.audio.isPlaying()) ) {
|
while( audios.stream().anyMatch(aw -> aw.audio.isPlaying()) ) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(10);
|
Thread.sleep(10);
|
||||||
@@ -83,16 +106,25 @@ public class Mixer implements Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void loop() {
|
public void loop() {
|
||||||
audios.stream().forEach(aw -> aw.audio.loop());
|
audios.stream().forEach(aw -> aw.audio.loop());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
audios.stream().forEach(aw -> aw.audio.stop());
|
audios.stream().forEach(aw -> aw.audio.stop());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
if( isPlaying() ) {
|
if( isPlaying() ) {
|
||||||
@@ -101,6 +133,18 @@ public class Mixer implements Audio {
|
|||||||
audios.stream().forEach(aw -> aw.audio.dispose());
|
audios.stream().forEach(aw -> aw.audio.dispose());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ändert die Lautstärke aller hinzugefügten Audiomedien in der angegebenen
|
||||||
|
* Zeit schrittweise, bis die angegebene Lautstärke erreicht ist.
|
||||||
|
* <p>
|
||||||
|
* Zu beachten ist, dass die Lautstärke des Mixers angepasst wird. Das
|
||||||
|
* bedeutet, dass die Lautstärke der hinzugefügten Medien mit ihrem
|
||||||
|
* Lautstärkefaktor multipliziert werden. Die Medien haben am Ende also
|
||||||
|
* nicht unbedingt die Lautstärke {@code to}.
|
||||||
|
*
|
||||||
|
* @param to Der Zielwert für die Lautstärke.
|
||||||
|
* @param time Die Zeit, nach der die Änderung abgeschlossen sein soll.
|
||||||
|
*/
|
||||||
public void fade( final double to, final int time ) {
|
public void fade( final double to, final int time ) {
|
||||||
TaskRunner.run(new Runnable() {
|
TaskRunner.run(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -108,9 +152,6 @@ public class Mixer implements Audio {
|
|||||||
final long start = System.currentTimeMillis();
|
final long start = System.currentTimeMillis();
|
||||||
double t = 0.0;
|
double t = 0.0;
|
||||||
double from = volume;
|
double from = volume;
|
||||||
if( !isPlaying() ) {
|
|
||||||
playOnce();
|
|
||||||
}
|
|
||||||
do {
|
do {
|
||||||
setVolume(Constants.interpolate(from, to, t));
|
setVolume(Constants.interpolate(from, to, t));
|
||||||
t = (double) (System.currentTimeMillis() - start) / (double) time;
|
t = (double) (System.currentTimeMillis() - start) / (double) time;
|
||||||
|
|||||||
@@ -1,43 +1,82 @@
|
|||||||
package schule.ngb.zm.media;
|
package schule.ngb.zm.media;
|
||||||
|
|
||||||
import schule.ngb.zm.tasks.TaskRunner;
|
import schule.ngb.zm.tasks.TaskRunner;
|
||||||
|
import schule.ngb.zm.util.Log;
|
||||||
import schule.ngb.zm.util.ResourceStreamProvider;
|
import schule.ngb.zm.util.ResourceStreamProvider;
|
||||||
|
import schule.ngb.zm.util.Validator;
|
||||||
|
|
||||||
import javax.sound.sampled.*;
|
import javax.sound.sampled.*;
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ein Musikstück, dass im Projekt abgespielt werden soll.
|
||||||
|
* <p>
|
||||||
|
* Im gegensatz zu einem {@link Sound} sind Musikstücke längere Audiodateien,
|
||||||
|
* die zum Beispiel als Hintergrundmusik ablaufen sollen. Die Musik wird daher
|
||||||
|
* nicht komplett in den Speicher geladen, sondern direkt aus der Audioquelle
|
||||||
|
* gestreamt und wiedergegeben.
|
||||||
|
*/
|
||||||
public class Music implements Audio {
|
public class Music implements Audio {
|
||||||
|
|
||||||
// size of the byte buffer used to read/write the audio stream
|
// size of the byte buffer used to read/write the audio stream
|
||||||
private static final int BUFFER_SIZE = 4096;
|
private static final int BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ob der Sound gerade abgespielt wird.
|
||||||
|
*/
|
||||||
private boolean playing = false;
|
private boolean playing = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ob der Sound gerade in einer Schleife abgespielt wird.
|
||||||
|
*/
|
||||||
private boolean looping = false;
|
private boolean looping = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Quelle des Musikstücks.
|
||||||
|
*/
|
||||||
private String audioSource;
|
private String audioSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Der AudioStream, um die AUdiosdaten zulsen, falls dieser schon geöffnet
|
||||||
|
* wurde. Sonst {@code null}.
|
||||||
|
*/
|
||||||
private AudioInputStream audioStream;
|
private AudioInputStream audioStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Line für die Ausgabe, falls diese schon geöffnet wurde. Sonst
|
||||||
|
* {@code null}.
|
||||||
|
*/
|
||||||
private SourceDataLine audioLine;
|
private SourceDataLine audioLine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Lautstärke der Musik.
|
||||||
|
*/
|
||||||
private float volume = 0.8f;
|
private float volume = 0.8f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt eine Musik aus der angegebenen Datei oder Webadresse.
|
||||||
|
*
|
||||||
|
* @param source Ein Dateipfad oder eine Webadresse.
|
||||||
|
* @throws NullPointerException Falls die Quelle {@code null} ist.
|
||||||
|
*/
|
||||||
public Music( String source ) {
|
public Music( String source ) {
|
||||||
|
Validator.requireNotNull(source);
|
||||||
this.audioSource = source;
|
this.audioSource = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlaying() {
|
public boolean isPlaying() {
|
||||||
return playing;
|
return playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isLooping() {
|
public boolean isLooping() {
|
||||||
if( !playing ) {
|
if( !playing ) {
|
||||||
@@ -46,6 +85,9 @@ public class Music implements Audio {
|
|||||||
return looping;
|
return looping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setVolume( double volume ) {
|
public void setVolume( double volume ) {
|
||||||
this.volume = (float) volume;
|
this.volume = (float) volume;
|
||||||
@@ -54,6 +96,18 @@ public class Music implements Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public double getVolume() {
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interne Methode, um die gesetzte Lautstärke vor dem Abspielen
|
||||||
|
* anzuwenden.
|
||||||
|
*/
|
||||||
private void applyVolume() {
|
private void applyVolume() {
|
||||||
FloatControl gainControl =
|
FloatControl gainControl =
|
||||||
(FloatControl) audioLine.getControl(FloatControl.Type.MASTER_GAIN);
|
(FloatControl) audioLine.getControl(FloatControl.Type.MASTER_GAIN);
|
||||||
@@ -63,8 +117,11 @@ public class Music implements Audio {
|
|||||||
gainControl.setValue(vol);
|
gainControl.setValue(vol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void playOnce() {
|
public void play() {
|
||||||
if( openLine() ) {
|
if( openLine() ) {
|
||||||
TaskRunner.run(new Runnable() {
|
TaskRunner.run(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -75,19 +132,28 @@ public class Music implements Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void playOnceAndWait() {
|
public void playAndWait() {
|
||||||
if( openLine() ) {
|
if( openLine() ) {
|
||||||
stream();
|
stream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void loop() {
|
public void loop() {
|
||||||
looping = true;
|
looping = true;
|
||||||
playOnce();
|
play();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
playing = false;
|
playing = false;
|
||||||
@@ -95,6 +161,9 @@ public class Music implements Audio {
|
|||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
if( audioLine != null ) {
|
if( audioLine != null ) {
|
||||||
@@ -112,7 +181,8 @@ public class Music implements Audio {
|
|||||||
if( audioStream != null ) {
|
if( audioStream != null ) {
|
||||||
audioStream.close();
|
audioStream.close();
|
||||||
}
|
}
|
||||||
} catch( IOException ex ) {}
|
} catch( IOException ex ) {
|
||||||
|
}
|
||||||
|
|
||||||
audioLine = null;
|
audioLine = null;
|
||||||
audioStream = null;
|
audioStream = null;
|
||||||
@@ -126,15 +196,14 @@ public class Music implements Audio {
|
|||||||
int bytesRead = -1;
|
int bytesRead = -1;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (playing && (bytesRead = audioStream.read(bytesBuffer)) != -1) {
|
while( playing && (bytesRead = audioStream.read(bytesBuffer)) != -1 ) {
|
||||||
audioLine.write(bytesBuffer, 0, bytesRead);
|
audioLine.write(bytesBuffer, 0, bytesRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
audioLine.drain();
|
audioLine.drain();
|
||||||
audioLine.stop();
|
audioLine.stop();
|
||||||
} catch( IOException ex ) {
|
} catch( IOException ex ) {
|
||||||
LOGGER.warning("Error while playing Music source <" + audioSource + ">");
|
LOG.warn(ex, "Error while playing Music source <%s>", audioSource);
|
||||||
LOGGER.throwing("Music", "stream", ex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the remaining audio to play
|
// Wait for the remaining audio to play
|
||||||
@@ -163,7 +232,7 @@ public class Music implements Audio {
|
|||||||
|
|
||||||
final int ch = format.getChannels();
|
final int ch = format.getChannels();
|
||||||
final float rate = format.getSampleRate();
|
final float rate = format.getSampleRate();
|
||||||
AudioFormat outFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, rate, 16, ch, ch*2, rate, false);
|
AudioFormat outFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, rate, 16, ch, ch * 2, rate, false);
|
||||||
|
|
||||||
DataLine.Info info = new DataLine.Info(SourceDataLine.class, outFormat);
|
DataLine.Info info = new DataLine.Info(SourceDataLine.class, outFormat);
|
||||||
|
|
||||||
@@ -174,14 +243,14 @@ public class Music implements Audio {
|
|||||||
audioStream = AudioSystem.getAudioInputStream(outFormat, inStream);
|
audioStream = AudioSystem.getAudioInputStream(outFormat, inStream);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
LOGGER.warning("Sound source <" + audioSource + "> could not be played: No audio source found.");
|
LOG.warn("Sound source <%s> could not be played: No audio source found.", audioSource);
|
||||||
}
|
}
|
||||||
} catch( UnsupportedAudioFileException ex ) {
|
} catch( UnsupportedAudioFileException ex ) {
|
||||||
LOGGER.log(Level.WARNING, "Sound source <" + audioSource + "> could not be played: The specified audio file is not supported.", ex);
|
LOG.warn(ex, "Sound source <%s> could not be played: The specified audio file is not supported.", audioSource);
|
||||||
} catch( LineUnavailableException ex ) {
|
} catch( LineUnavailableException ex ) {
|
||||||
LOGGER.log(Level.WARNING, "Sound source <" + audioSource + "> could not be played: Audio line for playing back is unavailable.", ex);
|
LOG.warn(ex, "Sound source <%s> could not be played: Audio line for playing back is unavailable.", audioSource);
|
||||||
} catch( IOException ex ) {
|
} catch( IOException ex ) {
|
||||||
LOGGER.log(Level.WARNING, "Sound source <" + audioSource + "> could not be played: Error playing the audio file.", ex);
|
LOG.warn(ex, "Sound source <%s> could not be played: Error playing the audio file.", audioSource);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -201,7 +270,6 @@ public class Music implements Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//private static final Logger LOGGER = Logger.getLogger("schule.ngb.zm.media.Music");
|
private static final Log LOG = Log.getLogger(Music.class);
|
||||||
private static final Logger LOGGER = Logger.getLogger(Music.class.getName());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,84 @@
|
|||||||
package schule.ngb.zm.media;
|
package schule.ngb.zm.media;
|
||||||
|
|
||||||
|
import schule.ngb.zm.util.Log;
|
||||||
import schule.ngb.zm.util.ResourceStreamProvider;
|
import schule.ngb.zm.util.ResourceStreamProvider;
|
||||||
|
import schule.ngb.zm.util.Validator;
|
||||||
|
|
||||||
import javax.sound.sampled.*;
|
import javax.sound.sampled.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wiedergabe kurzer Soundclips, die mehrmals wiederverwendet werden.
|
||||||
|
* <p>
|
||||||
|
* In Spielen und anderen Projekten gibt es oftmals eine Reihe kurzer Sounds,
|
||||||
|
* die zusammen mit bestimmten Aktionen wiedergegeben werden (zum Beispiel, wenn
|
||||||
|
* die Spielfigur springt, wenn zwei Objekte kollidieren, usw.). Sounds werden
|
||||||
|
* komplett in den Speicher geladen und können dadurch immer wieder, als
|
||||||
|
* Schleife oder auch nur Abschnittsweise abgespielt werden.
|
||||||
|
* <p>
|
||||||
|
* Für längre Musikstücke (beispielsweise Hintergrundmusik) bietet sich eher die
|
||||||
|
* KLasse {@link Music} an.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings( "unused" )
|
||||||
public class Sound implements Audio {
|
public class Sound implements Audio {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ob der Sound gerade abgespielt wird.
|
||||||
|
*/
|
||||||
private boolean playing = false;
|
private boolean playing = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ob der Sound gerade in einer Schleife abgespielt wird.
|
||||||
|
*/
|
||||||
private boolean looping = false;
|
private boolean looping = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Quelle des Musikstücks.
|
||||||
|
*/
|
||||||
private String audioSource;
|
private String audioSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Der Clip, falls er schon geladen wurde, sonst {@code null}.
|
||||||
|
*/
|
||||||
private Clip audioClip;
|
private Clip audioClip;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ob die Resourcen des Clips im Speicher nach dem nächsten Abspielen
|
||||||
|
* freigegeben werden sollen.
|
||||||
|
*/
|
||||||
private boolean disposeAfterPlay = false;
|
private boolean disposeAfterPlay = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Lautstärke des Clips.
|
||||||
|
*/
|
||||||
private float volume = 0.8f;
|
private float volume = 0.8f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt einen Sound aus der angegebene Quelle.
|
||||||
|
*
|
||||||
|
* @param source Ein Dateipfad oder eine Webadresse.
|
||||||
|
* @throws NullPointerException Falls die Quelle {@code null} ist.
|
||||||
|
*/
|
||||||
public Sound( String source ) {
|
public Sound( String source ) {
|
||||||
|
Validator.requireNotNull(source);
|
||||||
this.audioSource = source;
|
this.audioSource = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
public boolean isPlaying() {
|
public boolean isPlaying() {
|
||||||
// return audioClip != null && audioClip.isRunning();
|
// return audioClip != null && audioClip.isRunning();
|
||||||
return playing;
|
return playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
public boolean isLooping() {
|
public boolean isLooping() {
|
||||||
if( !playing ) {
|
if( !playing ) {
|
||||||
looping = false;
|
looping = false;
|
||||||
@@ -37,6 +86,10 @@ public class Sound implements Audio {
|
|||||||
return looping;
|
return looping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
public void setVolume( double volume ) {
|
public void setVolume( double volume ) {
|
||||||
this.volume = (float) volume;
|
this.volume = (float) volume;
|
||||||
if( audioClip != null ) {
|
if( audioClip != null ) {
|
||||||
@@ -44,6 +97,18 @@ public class Sound implements Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public double getVolume() {
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interne Methode, um die gesetzte Lautstärke vor dem Abspielen
|
||||||
|
* anzuwenden.
|
||||||
|
*/
|
||||||
private void applyVolume() {
|
private void applyVolume() {
|
||||||
FloatControl gainControl =
|
FloatControl gainControl =
|
||||||
(FloatControl) audioClip.getControl(FloatControl.Type.MASTER_GAIN);
|
(FloatControl) audioClip.getControl(FloatControl.Type.MASTER_GAIN);
|
||||||
@@ -53,6 +118,10 @@ public class Sound implements Audio {
|
|||||||
gainControl.setValue(vol);
|
gainControl.setValue(vol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
looping = false;
|
looping = false;
|
||||||
if( audioClip.isRunning() ) {
|
if( audioClip.isRunning() ) {
|
||||||
@@ -61,6 +130,10 @@ public class Sound implements Audio {
|
|||||||
playing = false;
|
playing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
public void play() {
|
public void play() {
|
||||||
if( this.openClip() ) {
|
if( this.openClip() ) {
|
||||||
audioClip.start();
|
audioClip.start();
|
||||||
@@ -68,16 +141,10 @@ public class Sound implements Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playOnce() {
|
/**
|
||||||
disposeAfterPlay = true;
|
* {@inheritDoc}
|
||||||
play();
|
*/
|
||||||
}
|
@Override
|
||||||
|
|
||||||
public void playOnceAndWait() {
|
|
||||||
disposeAfterPlay = true;
|
|
||||||
playAndWait();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void playAndWait() {
|
public void playAndWait() {
|
||||||
this.play();
|
this.play();
|
||||||
|
|
||||||
@@ -94,26 +161,73 @@ public class Sound implements Audio {
|
|||||||
audioClip.close();
|
audioClip.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spielt den Sound genau einmal ab und gibt danach alle Resourcen des Clips
|
||||||
|
* frei.
|
||||||
|
* <p>
|
||||||
|
* Der Aufruf ist effektiv gleich zu
|
||||||
|
* <pre><code>
|
||||||
|
* clip.playAndWait();
|
||||||
|
* clip.dispose();
|
||||||
|
* </code></pre>
|
||||||
|
* allerdings wird der aufrufende Thread nicht blockiert und
|
||||||
|
* {@link #dispose()} automatisch am Ende aufgerufen.
|
||||||
|
*/
|
||||||
|
public void playOnce() {
|
||||||
|
disposeAfterPlay = true;
|
||||||
|
play();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spielt den Sound genau einmal ab und gibt danach alle Resourcen des Clips
|
||||||
|
* frei.
|
||||||
|
* <p>
|
||||||
|
* Der Aufruf entspricht
|
||||||
|
* <pre><code>
|
||||||
|
* clip.playAndWait();
|
||||||
|
* clip.dispose();
|
||||||
|
* </code></pre>
|
||||||
|
*/
|
||||||
|
public void playOnceAndWait() {
|
||||||
|
disposeAfterPlay = true;
|
||||||
|
playAndWait();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
public void loop() {
|
public void loop() {
|
||||||
loop(Clip.LOOP_CONTINUOUSLY);
|
loop(Clip.LOOP_CONTINUOUSLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wiederholt den Sound die angegebene Anzahl an Wiederholungen ab und stoppt
|
||||||
|
* die Wiedergabe dann.
|
||||||
|
* @param count Anzahl der Wiederholungen.
|
||||||
|
*/
|
||||||
public void loop( int count ) {
|
public void loop( int count ) {
|
||||||
int loopCount = count;
|
if( count > 0 ) {
|
||||||
if( loopCount != Clip.LOOP_CONTINUOUSLY ) {
|
int loopCount = count;
|
||||||
if( loopCount <= 0 ) {
|
if( loopCount != Clip.LOOP_CONTINUOUSLY ) {
|
||||||
return;
|
if( loopCount <= 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Adjust Number of loops
|
||||||
|
loopCount -= 1;
|
||||||
|
}
|
||||||
|
if( openClip() ) {
|
||||||
|
looping = true;
|
||||||
|
audioClip.loop(loopCount);
|
||||||
|
playing = true;
|
||||||
}
|
}
|
||||||
// Adjust Number of loops
|
|
||||||
loopCount -= 1;
|
|
||||||
}
|
|
||||||
if( openClip() ) {
|
|
||||||
looping = true;
|
|
||||||
audioClip.loop(loopCount);
|
|
||||||
playing = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
if( audioClip != null ) {
|
if( audioClip != null ) {
|
||||||
if( audioClip.isRunning() ) {
|
if( audioClip.isRunning() ) {
|
||||||
@@ -150,17 +264,14 @@ public class Sound implements Audio {
|
|||||||
applyVolume();
|
applyVolume();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
LOGGER.warning("Sound source " + audioSource + " could not be played: No audio source found.");
|
LOG.warn("Sound source <%s> could not be played: No audio source found.", audioSource);
|
||||||
}
|
}
|
||||||
} catch( UnsupportedAudioFileException ex ) {
|
} catch( UnsupportedAudioFileException ex ) {
|
||||||
LOGGER.warning("Sound source " + audioSource + " could not be played: The specified audio file is not supported.");
|
LOG.warn(ex, "Sound source <%s> could not be played: The specified audio file is not supported.", audioSource);
|
||||||
LOGGER.throwing("Sound", "openClip", ex);
|
|
||||||
} catch( LineUnavailableException ex ) {
|
} catch( LineUnavailableException ex ) {
|
||||||
LOGGER.warning("Sound source " + audioSource + " could not be played: Audio line for playing back is unavailable.");
|
LOG.warn(ex, "Sound source <%s> could not be played: Audio line for playing back is unavailable.", audioSource);
|
||||||
LOGGER.throwing("Sound", "openClip", ex);
|
|
||||||
} catch( IOException ex ) {
|
} catch( IOException ex ) {
|
||||||
LOGGER.warning("Sound source " + audioSource + " could not be played: Error playing the audio file.");
|
LOG.warn(ex, "Sound source <%s> could not be played: Error playing the audio file.", audioSource);
|
||||||
LOGGER.throwing("Sound", "openClip", ex);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -180,6 +291,11 @@ public class Sound implements Audio {
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interne Methode, die aufgerufen wird, wenn die Wiedergabe gestoppt wird.
|
||||||
|
* Entweder durch einen Aufruf von {@link #stop()} oder, weil die Wiedergabe
|
||||||
|
* nach {@link #playOnce()} beendet wurde.
|
||||||
|
*/
|
||||||
private void playbackStopped() {
|
private void playbackStopped() {
|
||||||
playing = false;
|
playing = false;
|
||||||
if( disposeAfterPlay ) {
|
if( disposeAfterPlay ) {
|
||||||
@@ -188,17 +304,6 @@ public class Sound implements Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
private static final Log LOG = Log.getLogger(Sound.class);
|
||||||
public void addLineListener( LineListener listener ) {
|
|
||||||
if( audioClip == null ) {
|
|
||||||
openClip();
|
|
||||||
}
|
|
||||||
if( audioClip != null ) {
|
|
||||||
audioClip.addLineListener(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(Sound.class.getName());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user