From 0d0c0ca08ca816bce82140394c37baad74718bd9 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Mon, 8 Jan 2024 12:29:09 +0900 Subject: [PATCH] Add support for ogg-vorbis audio files --- .../client/BattleMusic.java | 133 +++++++++++++++++- 1 file changed, 131 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/burnedkirby/TurnBasedMinecraft/client/BattleMusic.java b/src/main/java/com/burnedkirby/TurnBasedMinecraft/client/BattleMusic.java index a48ccb5..bccb282 100644 --- a/src/main/java/com/burnedkirby/TurnBasedMinecraft/client/BattleMusic.java +++ b/src/main/java/com/burnedkirby/TurnBasedMinecraft/client/BattleMusic.java @@ -1,6 +1,7 @@ package com.burnedkirby.TurnBasedMinecraft.client; import com.burnedkirby.TurnBasedMinecraft.common.TurnBasedMinecraftMod; +import de.jarnbjo.vorbis.VorbisAudioFileReader; import fr.delthas.javamp3.Sound; import net.minecraft.client.Minecraft; import org.apache.logging.log4j.Logger; @@ -28,7 +29,9 @@ public class BattleMusic private boolean playingIsSilly; private boolean isPlaying; private Thread mp3StreamThread; + private Thread oggVorbisStreamThread; private MP3Streamer mp3StreamRunnable; + private OGGVorbisStreamer oggVorbisStreamRunnable; public BattleMusic(Logger logger) { @@ -81,7 +84,7 @@ public class BattleMusic } String ext = name.substring(extIndex + 1).toLowerCase(); // return ext.equals("mid") || ext.equals("wav") || ext.equals("mp3"); - return ext.equals("wav") || ext.equals("mp3"); // midi disabled + return ext.equals("wav") || ext.equals("mp3") || ext.equals("ogg"); // midi disabled } }); for(File f : battleFiles) @@ -101,7 +104,7 @@ public class BattleMusic } String ext = name.substring(extIndex + 1).toLowerCase(); // return ext.equals("mid") || ext.equals("wav") || ext.equals("mp3"); - return ext.equals("wav") || ext.equals("mp3"); // midi disabled + return ext.equals("wav") || ext.equals("mp3") || ext.equals("ogg"); // midi disabled } }); for(File f : sillyFiles) @@ -303,6 +306,39 @@ public class BattleMusic return; } } + else if (suffix.equals("ogg")) { + if(sequencer != null && sequencer.isRunning()) + { + sequencer.stop(); + } + if(clip != null && clip.isActive()) + { + clip.stop(); + clip.close(); + } + if(mp3StreamThread != null && mp3StreamThread.isAlive()) + { + mp3StreamRunnable.setKeepPlaying(false); + try { mp3StreamThread.join(); } catch (Throwable t) { /* ignored */ } + } + + try { + if (oggVorbisStreamRunnable == null) { + oggVorbisStreamRunnable = new OGGVorbisStreamer(next, logger, volume); + } else { + oggVorbisStreamRunnable.setOggVorbisFile(next); + oggVorbisStreamRunnable.setVolume(volume); + } + + oggVorbisStreamThread = new Thread(oggVorbisStreamRunnable); + oggVorbisStreamThread.start(); + logger.info("Started playing OggVorbis " + next.getName()); + } catch (Throwable t) { + logger.error("Failed to play battle music (ogg)"); + t.printStackTrace(); + return; + } + } } } @@ -320,6 +356,10 @@ public class BattleMusic mp3StreamRunnable.setKeepPlaying(false); try { mp3StreamThread.join(); } catch (Throwable t) { /* ignored */ } } + if (oggVorbisStreamThread != null && oggVorbisStreamThread.isAlive()) { + oggVorbisStreamRunnable.setKeepPlaying(false); + try { oggVorbisStreamThread.join(); } catch (Throwable t) { /* ignored */ } + } if(resumeMCSounds) { Minecraft.getInstance().getSoundManager().resume(); @@ -454,4 +494,93 @@ public class BattleMusic } } } + + private class OGGVorbisStreamer implements Runnable { + private AtomicBoolean keepPlaying; + private File oggVorbisFile; + private Logger logger; + private float volume; + + public OGGVorbisStreamer(File oggVorbisFile, Logger logger, float volume) { + keepPlaying = new AtomicBoolean(true); + this.oggVorbisFile = oggVorbisFile; + this.logger = logger; + this.volume = volume; + if (this.volume > 1.0F) { + this.volume = 1.0F; + } else if (this.volume < 0.0F) { + this.volume = 0.0F; + } + } + + public void setKeepPlaying(boolean playing) { + keepPlaying.set(playing); + } + + public void setOggVorbisFile(File oggVorbisFile) { + this.oggVorbisFile = oggVorbisFile; + } + + public void setVolume(float volume) { + this.volume = volume; + } + + @Override + public void run() { + keepPlaying.set(true); + SourceDataLine sdl = null; + try { + VorbisAudioFileReader reader = new VorbisAudioFileReader(); + AudioFormat audioFormat = reader.getAudioFileFormat(oggVorbisFile).getFormat(); + sdl = AudioSystem.getSourceDataLine(audioFormat); + sdl.open(audioFormat); + { + FloatControl volumeControl = (FloatControl) sdl.getControl(FloatControl.Type.MASTER_GAIN); + volumeControl.setValue(volume * 20.0f - 20.0f); // in decibels + } + + AudioInputStream ais = reader.getAudioInputStream(oggVorbisFile); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] cached = null; + int cachedOffset = 0; + int cachedSize = 0; + byte[] buf = new byte[4096]; + sdl.start(); + int read = ais.read(buf); + while (keepPlaying.get()) { + if (baos != null) { + if (read != -1) { + sdl.write(buf, 0, read); + baos.write(buf, 0, read); + read = ais.read(buf); + } else { + ais.close(); + ais = null; + cached = baos.toByteArray(); + baos = null; + } + } else { + cachedSize = cached.length - cachedOffset; + if (cachedSize > 4096) { + cachedSize = 4096; + } + sdl.write(cached, cachedOffset, cachedSize); + cachedOffset += cachedSize; + if (cachedOffset >= cached.length) { + cachedOffset = 0; + } + } + } + } catch (Throwable t) { + logger.error("Stream play oggVorbis", t); + } + + if (sdl != null) { + sdl.stop(); + sdl.flush(); + sdl.close(); + } + } + } }