mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-04-14 06:33:34 +02:00
Audio Interface ud Mixer Klasse
This commit is contained in:
70
src/schule/ngb/zm/media/Audio.java
Normal file
70
src/schule/ngb/zm/media/Audio.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package schule.ngb.zm.media;
|
||||
|
||||
/**
|
||||
* Interface für Audio-Medien.
|
||||
*/
|
||||
public interface Audio {
|
||||
|
||||
/**
|
||||
* Prüft, ob das Medium gerade abgespielt wird.
|
||||
*
|
||||
* @return {@code true}, wenn das Medium abgespielt wird, {@code false}
|
||||
* sonst.
|
||||
*/
|
||||
boolean isPlaying();
|
||||
|
||||
/**
|
||||
* Prüft, ob das Medium gerade in einer Schleife abgespielt wird. Wenn
|
||||
* {@code isLooping() == true}, dann muss auch immer
|
||||
* {@code isPlaying() == true} gelten.
|
||||
*
|
||||
* @return @return {@code true}, wenn das Medium in einer Schleife
|
||||
* abgespielt wird, {@code false} sonst.
|
||||
*/
|
||||
boolean isLooping();
|
||||
|
||||
/**
|
||||
* Legt die Lautstärke des Mediums beim Abspielen fest.
|
||||
* <p>
|
||||
* Die Lautstärke wird auf einer linearen Skale festgelegt, wobei 0 kein Ton
|
||||
* und 1 volle Lautstärke bedeutet. Werte über 1 verstärken den Ton des
|
||||
* Mediums.
|
||||
*
|
||||
* @param volume Die neue Lautstärke zwischen 0 und 1.
|
||||
* @see <a
|
||||
* href="https://stackoverflow.com/a/40698149">https://stackoverflow.com/a/40698149</a>
|
||||
*/
|
||||
void setVolume( double volume );
|
||||
|
||||
/**
|
||||
* Startet die Wiedergabe des Mediums und beendet die Methode. Das
|
||||
* Audio-Medium wird einmal abgespielt und stoppt dann.
|
||||
*/
|
||||
void playOnce();
|
||||
|
||||
/**
|
||||
* Startet die Wiedergabe des Mediums und blockiert das Programm, bis die
|
||||
* Wiedergabe beendet ist.
|
||||
*/
|
||||
void playOnceAndWait();
|
||||
|
||||
/**
|
||||
* Spielt das Medium in einer kontinuierlichen Schleife ab. Die Methode
|
||||
* startet die Wiedergabe und beendet dann direkt die Methode. Um die
|
||||
* Wiedergabe zu stoppen muss {@link #stop()} aufgerufen werden.
|
||||
*/
|
||||
void loop();
|
||||
|
||||
/**
|
||||
* Stoppt die Wiedergabe. Wird das Medium gerade nicht abgespielt
|
||||
* {@code isPlaying() == false}, dann passiert nichts.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Stoppt die Wiedergabe und gibt alle Resourcen, die für das Medium
|
||||
* verwendet werden, frei.
|
||||
*/
|
||||
void dispose();
|
||||
|
||||
}
|
||||
129
src/schule/ngb/zm/media/Mixer.java
Normal file
129
src/schule/ngb/zm/media/Mixer.java
Normal file
@@ -0,0 +1,129 @@
|
||||
package schule.ngb.zm.media;
|
||||
|
||||
import schule.ngb.zm.Constants;
|
||||
import schule.ngb.zm.tasks.TaskRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Ein Mixer ist eine Sammlung mehrerer {@link Audio Audio-Medien}, die
|
||||
* gemeinsam kontrolliert werden können.
|
||||
* <p>
|
||||
* Im einfachsten Fall kann die Audio-Gruppe gemeinsam gestartet und gestoppt
|
||||
* werden. Ein Mixer kann die Lautstärke der Medien in Relation zueinander
|
||||
* setzen. Dazu wird jedem Medium ein Faktor mitgegeben. Ein Medium mit dem
|
||||
* Faktor 0.5 ist dann halb so laut wie eines, mit dem Faktor 1.0.
|
||||
* <p>
|
||||
* Darüber hinaus kann ein Mixer Effekte wie einen
|
||||
* {@link #fade(double, int) fadeIn} auf die Medien anwenden.
|
||||
*/
|
||||
public class Mixer implements Audio {
|
||||
|
||||
private List<AudioWrapper> audios;
|
||||
|
||||
private float volume = 0.8f;
|
||||
|
||||
class AudioWrapper {
|
||||
|
||||
Audio audio;
|
||||
|
||||
float volumeFactor;
|
||||
|
||||
public AudioWrapper( Audio audio, float volumeFactor ) {
|
||||
this.audio = audio;
|
||||
this.volumeFactor = volumeFactor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Mixer() {
|
||||
this.audios = new ArrayList<>(4);
|
||||
}
|
||||
|
||||
public void add( Audio pAudio ) {
|
||||
add(pAudio, 1f);
|
||||
}
|
||||
|
||||
public void add( Audio pAudio, double pVolumeFactor ) {
|
||||
audios.add(new AudioWrapper(pAudio, (float) pVolumeFactor));
|
||||
pAudio.setVolume(pVolumeFactor * volume);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlaying() {
|
||||
return audios.stream().anyMatch(aw -> aw.audio.isPlaying());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLooping() {
|
||||
return audios.stream().anyMatch(aw -> aw.audio.isLooping());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVolume( double pVolume ) {
|
||||
volume = (float) pVolume;
|
||||
audios.stream().forEach(aw -> aw.audio.setVolume(aw.volumeFactor * pVolume));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playOnce() {
|
||||
audios.stream().forEach(aw -> aw.audio.playOnce());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playOnceAndWait() {
|
||||
audios.stream().forEach(aw -> aw.audio.playOnce());
|
||||
while( audios.stream().anyMatch(aw -> aw.audio.isPlaying()) ) {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch( InterruptedException e ) {
|
||||
// Just keep waiting
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loop() {
|
||||
audios.stream().forEach(aw -> aw.audio.loop());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
audios.stream().forEach(aw -> aw.audio.stop());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if( isPlaying() ) {
|
||||
stop();
|
||||
}
|
||||
audios.stream().forEach(aw -> aw.audio.dispose());
|
||||
}
|
||||
|
||||
public void fade( final double to, final int time ) {
|
||||
TaskRunner.run(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final long start = System.currentTimeMillis();
|
||||
double t = 0.0;
|
||||
double from = volume;
|
||||
if( !isPlaying() ) {
|
||||
playOnce();
|
||||
}
|
||||
do {
|
||||
setVolume(Constants.interpolate(from, to, t));
|
||||
t = (double) (System.currentTimeMillis() - start) / (double) time;
|
||||
|
||||
try {
|
||||
Thread.sleep(1000 / Constants.framesPerSecond);
|
||||
} catch( InterruptedException e ) {
|
||||
// Keep waiting
|
||||
}
|
||||
} while( t < 1.0 );
|
||||
setVolume(to);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import java.io.InputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Music {
|
||||
public class Music implements Audio {
|
||||
|
||||
// size of the byte buffer used to read/write the audio stream
|
||||
private static final int BUFFER_SIZE = 4096;
|
||||
@@ -25,16 +25,18 @@ public class Music {
|
||||
|
||||
private SourceDataLine audioLine;
|
||||
|
||||
private float volume = 1.0f;
|
||||
private float volume = 0.8f;
|
||||
|
||||
public Music( String source ) {
|
||||
this.audioSource = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlaying() {
|
||||
return playing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLooping() {
|
||||
if( !playing ) {
|
||||
looping = false;
|
||||
@@ -42,6 +44,7 @@ public class Music {
|
||||
return looping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVolume( double volume ) {
|
||||
this.volume = (float) volume;
|
||||
if( audioLine != null ) {
|
||||
@@ -58,6 +61,7 @@ public class Music {
|
||||
gainControl.setValue(vol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playOnce() {
|
||||
if( openLine() ) {
|
||||
TaskRunner.run(new Runnable() {
|
||||
@@ -69,23 +73,27 @@ public class Music {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playOnceAndWait() {
|
||||
if( openLine() ) {
|
||||
stream();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loop() {
|
||||
looping = true;
|
||||
playOnce();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
playing = false;
|
||||
looping = false;
|
||||
dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if( audioLine != null ) {
|
||||
if( audioLine.isRunning() ) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Sound {
|
||||
public class Sound implements Audio {
|
||||
|
||||
private boolean playing = false;
|
||||
|
||||
@@ -19,7 +19,7 @@ public class Sound {
|
||||
|
||||
private boolean disposeAfterPlay = false;
|
||||
|
||||
private float volume = 1.0f;
|
||||
private float volume = 0.8f;
|
||||
|
||||
public Sound( String source ) {
|
||||
this.audioSource = source;
|
||||
|
||||
Reference in New Issue
Block a user