Merge remote-tracking branch 'refs/remotes/origin/46-audio-epic' into assetManager

# Conflicts:
#	framework/src/main/java/org/toop/framework/assets/resources/AudioAsset.java
#	framework/src/main/java/org/toop/framework/assets/resources/BaseResource.java
#	framework/src/main/java/org/toop/framework/assets/resources/ImageResource.java
This commit is contained in:
lieght
2025-09-30 22:54:54 +02:00
5 changed files with 96 additions and 50 deletions

View File

@@ -14,14 +14,17 @@ import java.io.IOException;
import java.nio.file.NotDirectoryException; import java.nio.file.NotDirectoryException;
public class Main { 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 a = new AssetManager(new File("app/src/main/resources/assets"));
var b = new NetworkingClientManager(); var b = new NetworkingClientManager();
var c = new SoundManager(a); var c = new SoundManager(a);
// IO.println(a.getAssets()); new EventFlow().addPostEvent(new AudioEvents.PlayAudio("mainmenu.wav", true)).asyncPostEvent();
IO.println(c.getClips()); 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("mainmenu.wav", true)).asyncPostEvent();
new EventFlow().addPostEvent(new AudioEvents.PlayAudio("sadtrombone.wav", true)).asyncPostEvent(); new EventFlow().addPostEvent(new AudioEvents.PlayAudio("sadtrombone.wav", true)).asyncPostEvent();

View File

@@ -1,23 +1,34 @@
package org.toop.framework.assets.resources; package org.toop.framework.assets.resources;
import java.io.*; import java.io.*;
import java.nio.file.Files;
public abstract class BaseResource { public abstract class BaseResource {
final InputStream stream; final InputStream stream;
final File file; final File file;
public abstract class Resource {
final private byte[] rawData;
final private File file;
BaseResource(final File file) { BaseResource(final File file) {
Resource(final File file) throws RuntimeException {
this.file = file; this.file = file;
try { try {
this.stream = new BufferedInputStream(new FileInputStream(file)); this.rawData = Files.readAllBytes(file.toPath());
} catch (FileNotFoundException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
public InputStream getInputStream() { public InputStream getInputStream() {
return this.stream; return this.stream;
public Resource load() {
return this;
}
public InputStream getStream() {
return new BufferedInputStream(new ByteArrayInputStream(this.rawData));
} }
public File getFile() { public File getFile() {

View File

@@ -0,0 +1,27 @@
package org.toop.framework.assets.resources;
import javafx.scene.image.Image;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class ImageResource extends Resource {
private Image image = null;
public ImageResource(File imageFile) {
super(imageFile);
}
public Image getImage() {
return this.image;
}
@Override
public Resource load() {
this.image = new Image(this.getStream());
return this;
}
}

View File

@@ -1,9 +1,9 @@
package org.toop.framework.audio; package org.toop.framework.audio;
import org.toop.framework.SnowflakeGenerator;
import org.toop.framework.assets.Asset; import org.toop.framework.assets.Asset;
import org.toop.framework.assets.AssetManager; import org.toop.framework.assets.AssetManager;
import org.toop.framework.assets.resources.AudioResource; 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.audio.events.AudioEvents;
import org.toop.framework.eventbus.EventFlow; import org.toop.framework.eventbus.EventFlow;
@@ -12,16 +12,15 @@ import java.util.*;
import javax.sound.sampled.*; import javax.sound.sampled.*;
public class SoundManager { public class SoundManager {
private final Map<String, Clip> activeClips = new HashMap<>(); private final Map<Long, Clip> activeClips = new HashMap<>();
private final HashMap<String, Clip> clips = new HashMap<>(); private final HashMap<String, AudioResource> audioResources = new HashMap<>();
private final AssetManager assetManager; private final SnowflakeGenerator idGenerator = new SnowflakeGenerator(); // TODO: Don't create a new generator
public SoundManager(AssetManager asm) { public SoundManager(AssetManager asm) {
this.assetManager = asm;
// Get all Audio Resources and add them to a list. // Get all Audio Resources and add them to a list.
for (Asset<AudioResource> resource : asm.getAllResourceOfType(AudioResource.class).values()) { for (Asset<AudioResource> resource : asm.getAllResourceOfType(AudioResource.class).values()) {
try { try {
addClip(resource); this.addAudioResource(resource);
} catch (IOException | LineUnavailableException | UnsupportedAudioFileException e) { } catch (IOException | LineUnavailableException | UnsupportedAudioFileException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -36,28 +35,29 @@ public class SoundManager {
} }
private void handleStopSound(AudioEvents.StopAudio event) { private void handleStopSound(AudioEvents.StopAudio event) {
this.stopSound(event.fileNameNoExtensionAndNoDirectory()); this.stopSound(event.clipId());
} }
private void addClip(Asset<AudioResource> audioAsset) private void addAudioResource(Asset<AudioResource> audioAsset)
throws IOException, UnsupportedAudioFileException, LineUnavailableException { throws IOException, UnsupportedAudioFileException, LineUnavailableException {
AudioResource audioResource = audioAsset.getResource(); AudioResource audioResource = audioAsset.getResource();
this.clips.put(audioAsset.getName(), audioResource.getClip()); this.audioResources.put(audioAsset.getName(), audioResource);
} }
private void playSound(String audioFileName, boolean loop) { private long playSound(String audioFileName, boolean loop) {
// Get clip try {
Clip clip = clips.get(audioFileName); AudioResource resource = audioResources.get(audioFileName);
if (clip == null) { // Return -1 which indicates resource wasn't available
return; if (resource == null){
return -1;
} }
// Reset clip // Get a new clip from resource
clip.setFramePosition(0); Clip clip = resource.getNewClip();
// If loop make it loop, else just start it once // If supposed to loop make it loop, else just start it once
if (loop){ if (loop){
clip.loop(Clip.LOOP_CONTINUOUSLY); clip.loop(Clip.LOOP_CONTINUOUSLY);
} }
@@ -65,24 +65,29 @@ public class SoundManager {
clip.start(); clip.start();
} }
// Generate id for clip
long clipId = idGenerator.nextId();
// store it so we can stop it later // store it so we can stop it later
activeClips.put(audioFileName, clip); // TODO: Do on snowflake for specific sound to stop activeClips.put(clipId, clip); // TODO: Do on snowflake for specific sound to stop
// remove when finished (only for non-looping sounds) // remove when finished (only for non-looping sounds)
clip.addLineListener(event -> { clip.addLineListener(event -> {
if (event.getType() == LineEvent.Type.STOP && !clip.isRunning()) { if (event.getType() == LineEvent.Type.STOP && !clip.isRunning()) {
activeClips.remove(audioFileName); activeClips.remove(clipId);
clip.close(); clip.close();
} }
}); });
// Return id so it can be stopped
return clipId;
} catch (LineUnavailableException | IOException | UnsupportedAudioFileException e) {
throw new RuntimeException(e);
}
} }
public HashMap<String, Clip> getClips() { public void stopSound(long clipId) {
return this.clips; Clip clip = activeClips.get(clipId);
}
public void stopSound(String audioFileName) {
Clip clip = activeClips.get(audioFileName);
if (clip == null) { if (clip == null) {
return; return;
@@ -90,7 +95,7 @@ public class SoundManager {
clip.stop(); clip.stop();
clip.close(); clip.close();
activeClips.remove(audioFileName); activeClips.remove(clipId);
} }
public void stopAllSounds() { public void stopAllSounds() {

View File

@@ -8,5 +8,5 @@ public class AudioEvents extends EventsBase {
public record PlayAudio(String fileNameNoExtensionAndNoDirectory, boolean loop) public record PlayAudio(String fileNameNoExtensionAndNoDirectory, boolean loop)
implements EventWithoutSnowflake {} implements EventWithoutSnowflake {}
public record StopAudio(String fileNameNoExtensionAndNoDirectory) implements EventWithoutSnowflake {} public record StopAudio(long clipId) implements EventWithoutSnowflake {}
} }