Skip to content

Commit

Permalink
(fastjengine#165) potential fix for audio events not being sent
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasstarsz committed May 12, 2022
1 parent 748f64a commit 20f0ccb
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 8 deletions.
19 changes: 18 additions & 1 deletion src/main/java/tech/fastj/systems/audio/AudioManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,24 @@ static SourceDataLine newSourceDataLine(AudioFormat audioFormat) {
}

try {
return (SourceDataLine) AudioSystem.getLine(lineInfo);
SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(lineInfo);
sourceDataLine.addLineListener(event -> {
switch (event.getType().toString()) {
case "Open": {

}
case "Close": {

}
case "Stop": {

}
case "": {

}
}
});
return sourceDataLine;
} catch (LineUnavailableException exception) {
throw new IllegalStateException("No audio lines were available to load the data line with format " + audioFormat + ".", exception);
}
Expand Down
54 changes: 52 additions & 2 deletions src/main/java/tech/fastj/systems/audio/MemoryAudio.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
package tech.fastj.systems.audio;

import tech.fastj.engine.FastJEngine;

import tech.fastj.systems.audio.state.PlaybackState;

import java.net.URL;
import java.nio.file.Path;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;

/**
* An audio object used for sound playback.
Expand Down Expand Up @@ -55,14 +62,48 @@ public class MemoryAudio extends Audio {
public static final int LoopAtEnd = -1;

private final AudioEventListener audioEventListener;
private final Clip clip;
private Clip clip;
private final AudioInputStream audioInputStream;

private float loopStart;
private float loopEnd;
private int loopCount;
private boolean shouldLoop;

private boolean forcedStart;
private boolean forcedStop;

private final LineListener eventHelper = event -> {
switch (event.getType().toString()) {
case "START": {
if (forcedStart) {
return;
}

LineEvent startLineEvent = new LineEvent(clip, LineEvent.Type.START, clip.getLongFramePosition());
AudioEvent startAudioEvent = new AudioEvent(startLineEvent, this);
FastJEngine.getGameLoop().fireEvent(startAudioEvent);
break;
}
case "STOP": {
if (forcedStop) {
return;
}

LineEvent stopLineEvent = new LineEvent(clip, LineEvent.Type.STOP, clip.getLongFramePosition());
AudioEvent stopAudioEvent = new AudioEvent(stopLineEvent, this);
FastJEngine.getGameLoop().fireEvent(stopAudioEvent);
}
}
};

private static ScheduledExecutorService forcedTimeout = Executors.newScheduledThreadPool(2);

public static void reset() {
forcedTimeout.shutdownNow();
forcedTimeout = Executors.newScheduledThreadPool(2);
}

/**
* Constructs the {@code MemoryAudio} object with the given path.
*
Expand All @@ -74,6 +115,7 @@ public class MemoryAudio extends Audio {
loopStart = LoopFromStart;
loopEnd = LoopAtEnd;
clip = Objects.requireNonNull(AudioManager.newClip());
clip.addLineListener(eventHelper);
audioInputStream = Objects.requireNonNull(AudioManager.newAudioStream(audioPath));
audioEventListener = new AudioEventListener(this);
currentPlaybackState = PlaybackState.Stopped;
Expand All @@ -91,6 +133,7 @@ public class MemoryAudio extends Audio {
loopStart = LoopFromStart;
loopEnd = LoopAtEnd;
clip = Objects.requireNonNull(AudioManager.newClip());
clip.addLineListener(eventHelper);

String urlPath = audioPath.getPath();
String urlProtocol = audioPath.getProtocol();
Expand Down Expand Up @@ -294,7 +337,9 @@ public void rewindToBeginning() {
*/
@Override
public void play() {
forcedStart = true;
MemoryAudioPlayer.playAudio(this);
forcedTimeout.schedule(() -> forcedStart = false, 20, TimeUnit.MILLISECONDS);
}

/**
Expand All @@ -307,7 +352,9 @@ public void play() {
*/
@Override
public void pause() {
forcedStop = true;
MemoryAudioPlayer.pauseAudio(this);
forcedTimeout.schedule(() -> forcedStop = false, 20, TimeUnit.MILLISECONDS);
}

/**
Expand All @@ -321,7 +368,9 @@ public void pause() {
*/
@Override
public void resume() {
forcedStart = true;
MemoryAudioPlayer.resumeAudio(this);
forcedTimeout.schedule(() -> forcedStart = false, 20, TimeUnit.MILLISECONDS);
}

/**
Expand All @@ -336,9 +385,10 @@ public void resume() {
*/
@Override
public void stop() {
forcedStop = true;
MemoryAudioPlayer.stopAudio(this);
forcedTimeout.schedule(() -> forcedStop = false, 20, TimeUnit.MILLISECONDS);
}

@Override
public String toString() {
return "MemoryAudio{" +
Expand Down
59 changes: 54 additions & 5 deletions src/main/java/tech/fastj/systems/audio/StreamedAudio.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package tech.fastj.systems.audio;

import tech.fastj.systems.audio.state.PlaybackState;
import tech.fastj.engine.FastJEngine;

import java.net.URL;
import java.nio.file.Path;
import java.util.Objects;
import java.util.UUID;
import tech.fastj.systems.audio.state.PlaybackState;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.BooleanControl;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import java.net.URL;
import java.nio.file.Path;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
* An audio object used for sound playback.
Expand Down Expand Up @@ -43,6 +49,40 @@ public class StreamedAudio extends Audio {

private AudioEventListener audioEventListener;

private boolean forcedStart;
private boolean forcedStop;

private final LineListener eventHelper = event -> {
switch (event.getType().toString()) {
case "START": {
if (forcedStart) {
return;
}

LineEvent startLineEvent = new LineEvent(sourceDataLine, LineEvent.Type.START, sourceDataLine.getLongFramePosition());
AudioEvent startAudioEvent = new AudioEvent(startLineEvent, this);
FastJEngine.getGameLoop().fireEvent(startAudioEvent);
break;
}
case "STOP": {
if (forcedStop) {
return;
}

LineEvent stopLineEvent = new LineEvent(sourceDataLine, LineEvent.Type.STOP, sourceDataLine.getLongFramePosition());
AudioEvent stopAudioEvent = new AudioEvent(stopLineEvent, this);
FastJEngine.getGameLoop().fireEvent(stopAudioEvent);
}
}
};

private static ScheduledExecutorService forcedTimeout = Executors.newScheduledThreadPool(2);

public static void reset() {
forcedTimeout.shutdownNow();
forcedTimeout = Executors.newScheduledThreadPool(2);
}

/**
* Constructs the {@code StreamedAudio} object with the given path.
*
Expand Down Expand Up @@ -79,6 +119,7 @@ public class StreamedAudio extends Audio {
/** Initializes a {@code StreamedAudio}'s data line, controls, and event listeners. */
private void initializeStreamData() {
sourceDataLine = Objects.requireNonNull(AudioManager.newSourceDataLine(audioInputStream.getFormat()));
sourceDataLine.addLineListener(eventHelper);

try {
sourceDataLine.open(audioInputStream.getFormat());
Expand Down Expand Up @@ -180,22 +221,30 @@ public SourceDataLine getAudioSource() {

@Override
public void play() {
forcedStart = true;
StreamedAudioPlayer.playAudio(this);
forcedTimeout.schedule(() -> forcedStart = false, 20, TimeUnit.MILLISECONDS);
}

@Override
public void pause() {
forcedStop = true;
StreamedAudioPlayer.pauseAudio(this);
forcedTimeout.schedule(() -> forcedStop = false, 20, TimeUnit.MILLISECONDS);
}

@Override
public void resume() {
forcedStart = true;
StreamedAudioPlayer.resumeAudio(this);
forcedTimeout.schedule(() -> forcedStart = false, 20, TimeUnit.MILLISECONDS);
}

@Override
public void stop() {
forcedStop = true;
StreamedAudioPlayer.stopAudio(this);
forcedTimeout.schedule(() -> forcedStop = false, 20, TimeUnit.MILLISECONDS);
}

@Override
Expand Down

0 comments on commit 20f0ccb

Please sign in to comment.