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.Level;
|
||||||
import java.util.logging.Logger;
|
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
|
// 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;
|
||||||
@@ -25,16 +25,18 @@ public class Music {
|
|||||||
|
|
||||||
private SourceDataLine audioLine;
|
private SourceDataLine audioLine;
|
||||||
|
|
||||||
private float volume = 1.0f;
|
private float volume = 0.8f;
|
||||||
|
|
||||||
public Music( String source ) {
|
public Music( String source ) {
|
||||||
this.audioSource = source;
|
this.audioSource = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isPlaying() {
|
public boolean isPlaying() {
|
||||||
return playing;
|
return playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isLooping() {
|
public boolean isLooping() {
|
||||||
if( !playing ) {
|
if( !playing ) {
|
||||||
looping = false;
|
looping = false;
|
||||||
@@ -42,6 +44,7 @@ public class Music {
|
|||||||
return looping;
|
return looping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setVolume( double volume ) {
|
public void setVolume( double volume ) {
|
||||||
this.volume = (float) volume;
|
this.volume = (float) volume;
|
||||||
if( audioLine != null ) {
|
if( audioLine != null ) {
|
||||||
@@ -58,6 +61,7 @@ public class Music {
|
|||||||
gainControl.setValue(vol);
|
gainControl.setValue(vol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void playOnce() {
|
public void playOnce() {
|
||||||
if( openLine() ) {
|
if( openLine() ) {
|
||||||
TaskRunner.run(new Runnable() {
|
TaskRunner.run(new Runnable() {
|
||||||
@@ -69,23 +73,27 @@ public class Music {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void playOnceAndWait() {
|
public void playOnceAndWait() {
|
||||||
if( openLine() ) {
|
if( openLine() ) {
|
||||||
stream();
|
stream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void loop() {
|
public void loop() {
|
||||||
looping = true;
|
looping = true;
|
||||||
playOnce();
|
playOnce();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
playing = false;
|
playing = false;
|
||||||
looping = false;
|
looping = false;
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
if( audioLine != null ) {
|
if( audioLine != null ) {
|
||||||
if( audioLine.isRunning() ) {
|
if( audioLine.isRunning() ) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class Sound {
|
public class Sound implements Audio {
|
||||||
|
|
||||||
private boolean playing = false;
|
private boolean playing = false;
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ public class Sound {
|
|||||||
|
|
||||||
private boolean disposeAfterPlay = false;
|
private boolean disposeAfterPlay = false;
|
||||||
|
|
||||||
private float volume = 1.0f;
|
private float volume = 0.8f;
|
||||||
|
|
||||||
public Sound( String source ) {
|
public Sound( String source ) {
|
||||||
this.audioSource = source;
|
this.audioSource = source;
|
||||||
|
|||||||
Reference in New Issue
Block a user