diff --git a/app/src/main/java/org/toop/Main.java b/app/src/main/java/org/toop/Main.java index 1f91081..858ab1a 100644 --- a/app/src/main/java/org/toop/Main.java +++ b/app/src/main/java/org/toop/Main.java @@ -14,14 +14,17 @@ import java.io.IOException; import java.nio.file.NotDirectoryException; public class Main { - static void main(String[] args) throws IOException, UnsupportedAudioFileException, LineUnavailableException { + static void main(String[] args) throws IOException, UnsupportedAudioFileException, LineUnavailableException, InterruptedException { var a = new AssetManager(new File("app/src/main/resources/assets")); var b = new NetworkingClientManager(); var c = new SoundManager(a); -// IO.println(a.getAssets()); - IO.println(c.getClips()); - + new EventFlow().addPostEvent(new AudioEvents.PlayAudio("mainmenu.wav", true)).asyncPostEvent(); + new EventFlow().addPostEvent(new AudioEvents.PlayAudio("sadtrombone.wav", true)).asyncPostEvent(); + Thread.sleep(200); + new EventFlow().addPostEvent(new AudioEvents.PlayAudio("mainmenu.wav", true)).asyncPostEvent(); + new EventFlow().addPostEvent(new AudioEvents.PlayAudio("sadtrombone.wav", true)).asyncPostEvent(); + Thread.sleep(200); new EventFlow().addPostEvent(new AudioEvents.PlayAudio("mainmenu.wav", true)).asyncPostEvent(); new EventFlow().addPostEvent(new AudioEvents.PlayAudio("sadtrombone.wav", true)).asyncPostEvent(); diff --git a/framework/src/main/java/org/toop/framework/assets/resources/AudioResource.java b/framework/src/main/java/org/toop/framework/assets/resources/AudioResource.java index fd841a9..3f8408e 100644 --- a/framework/src/main/java/org/toop/framework/assets/resources/AudioResource.java +++ b/framework/src/main/java/org/toop/framework/assets/resources/AudioResource.java @@ -4,32 +4,24 @@ import javax.sound.sampled.*; import java.io.*; public class AudioResource extends Resource { - private AudioInputStream audioInputStream = null; - private Clip clip = null; + + // Constructor public AudioResource(File audioFile) { super(audioFile); } - public AudioInputStream getAudioStream(){ - return this.audioInputStream; + // Gets a new clip to play + public Clip getNewClip() throws LineUnavailableException, UnsupportedAudioFileException, IOException { + // Get a new clip from audio system + Clip clip = AudioSystem.getClip(); + + // Insert a new audio stream into the clip + clip.open(this.getAudioStream()); + return clip; } - public Clip getClip() { - return this.clip; - } - - @Override - public Resource load() { - try { - this.audioInputStream = AudioSystem.getAudioInputStream(this.getStream()); - Clip clip = AudioSystem.getClip(); - clip.open(this.audioInputStream); - this.clip = clip; - } catch (UnsupportedAudioFileException | LineUnavailableException e) { - throw new RuntimeException(e); - } catch (IOException e) { // TODO: Error handling - throw new RuntimeException(e); - } - return this; + // Generates a new audio stream from byte array + private AudioInputStream getAudioStream() throws UnsupportedAudioFileException, IOException { + return AudioSystem.getAudioInputStream(this.getStream()); } } diff --git a/framework/src/main/java/org/toop/framework/audio/SoundManager.java b/framework/src/main/java/org/toop/framework/audio/SoundManager.java index 59d0656..faa8770 100644 --- a/framework/src/main/java/org/toop/framework/audio/SoundManager.java +++ b/framework/src/main/java/org/toop/framework/audio/SoundManager.java @@ -1,9 +1,9 @@ package org.toop.framework.audio; +import org.toop.framework.SnowflakeGenerator; import org.toop.framework.assets.Asset; import org.toop.framework.assets.AssetManager; import org.toop.framework.assets.resources.AudioResource; -import org.toop.framework.assets.resources.Resource; import org.toop.framework.audio.events.AudioEvents; import org.toop.framework.eventbus.EventFlow; @@ -12,16 +12,15 @@ import java.util.*; import javax.sound.sampled.*; public class SoundManager { - private final Map activeClips = new HashMap<>(); - private final HashMap clips = new HashMap<>(); - private final AssetManager assetManager; + private final Map activeClips = new HashMap<>(); + private final HashMap audioResources = new HashMap<>(); + private final SnowflakeGenerator idGenerator = new SnowflakeGenerator(); // TODO: Don't create a new generator public SoundManager(AssetManager asm) { - this.assetManager = asm; // Get all Audio Resources and add them to a list. for (Asset resource : asm.getAllResourceOfType(AudioResource.class).values()) { try { - addClip(resource); + this.addAudioResource(resource); } catch (IOException | LineUnavailableException | UnsupportedAudioFileException e) { throw new RuntimeException(e); } @@ -36,53 +35,59 @@ public class SoundManager { } private void handleStopSound(AudioEvents.StopAudio event) { - this.stopSound(event.fileNameNoExtensionAndNoDirectory()); + this.stopSound(event.clipId()); } - private void addClip(Asset audioAsset) + private void addAudioResource(Asset audioAsset) throws IOException, UnsupportedAudioFileException, LineUnavailableException { AudioResource audioResource = audioAsset.getResource(); - this.clips.put(audioAsset.getName(), audioResource.getClip()); + this.audioResources.put(audioAsset.getName(), audioResource); } - private void playSound(String audioFileName, boolean loop) { - // Get clip - Clip clip = clips.get(audioFileName); + private long playSound(String audioFileName, boolean loop) { + try { + AudioResource resource = audioResources.get(audioFileName); - if (clip == null) { - return; - } - - // Reset clip - clip.setFramePosition(0); - - // If loop make it loop, else just start it once - if (loop){ - clip.loop(Clip.LOOP_CONTINUOUSLY); - } - else { - clip.start(); - } - - // store it so we can stop it later - activeClips.put(audioFileName, clip); // TODO: Do on snowflake for specific sound to stop - - // remove when finished (only for non-looping sounds) - clip.addLineListener(event -> { - if (event.getType() == LineEvent.Type.STOP && !clip.isRunning()) { - activeClips.remove(audioFileName); - clip.close(); + // Return -1 which indicates resource wasn't available + if (resource == null){ + return -1; } - }); + + // Get a new clip from resource + Clip clip = resource.getNewClip(); + + // If supposed to loop make it loop, else just start it once + if (loop){ + clip.loop(Clip.LOOP_CONTINUOUSLY); + } + else { + clip.start(); + } + + // Generate id for clip + long clipId = idGenerator.nextId(); + + // store it so we can stop it later + activeClips.put(clipId, clip); // TODO: Do on snowflake for specific sound to stop + + // remove when finished (only for non-looping sounds) + clip.addLineListener(event -> { + if (event.getType() == LineEvent.Type.STOP && !clip.isRunning()) { + activeClips.remove(clipId); + clip.close(); + } + }); + + // Return id so it can be stopped + return clipId; + } catch (LineUnavailableException | IOException | UnsupportedAudioFileException e) { + throw new RuntimeException(e); + } } - public HashMap getClips() { - return this.clips; - } - - public void stopSound(String audioFileName) { - Clip clip = activeClips.get(audioFileName); + public void stopSound(long clipId) { + Clip clip = activeClips.get(clipId); if (clip == null) { return; @@ -90,7 +95,7 @@ public class SoundManager { clip.stop(); clip.close(); - activeClips.remove(audioFileName); + activeClips.remove(clipId); } public void stopAllSounds() { diff --git a/framework/src/main/java/org/toop/framework/audio/events/AudioEvents.java b/framework/src/main/java/org/toop/framework/audio/events/AudioEvents.java index 56aaf64..74bc41a 100644 --- a/framework/src/main/java/org/toop/framework/audio/events/AudioEvents.java +++ b/framework/src/main/java/org/toop/framework/audio/events/AudioEvents.java @@ -8,5 +8,5 @@ public class AudioEvents extends EventsBase { public record PlayAudio(String fileNameNoExtensionAndNoDirectory, boolean loop) implements EventWithoutSnowflake {} - public record StopAudio(String fileNameNoExtensionAndNoDirectory) implements EventWithoutSnowflake {} + public record StopAudio(long clipId) implements EventWithoutSnowflake {} }