Add mp3 support
This commit is contained in:
parent
3c6c22432e
commit
f32d872bbf
4 changed files with 206 additions and 26 deletions
|
@ -58,3 +58,6 @@ licenced under the [Apache License 2.0](https://github.com/johnrengelman/shadow/
|
||||||
|
|
||||||
This mod also uses [Cava-Toml](https://github.com/ConsenSys/cava/tree/master/toml)
|
This mod also uses [Cava-Toml](https://github.com/ConsenSys/cava/tree/master/toml)
|
||||||
which is licenced under the [Apache License 2.0](https://github.com/ConsenSys/cava/blob/master/LICENSE).
|
which is licenced under the [Apache License 2.0](https://github.com/ConsenSys/cava/blob/master/LICENSE).
|
||||||
|
|
||||||
|
This mod also uses [JavaMP3](https://github.com/kevinstadler/JavaMP3)
|
||||||
|
which is licensed under the [MIT License](https://github.com/kevinstadler/JavaMP3/blob/master/LICENSE).
|
||||||
|
|
|
@ -38,6 +38,8 @@ dependencies {
|
||||||
// or you may define them like so..
|
// or you may define them like so..
|
||||||
//compile "some.group:artifact:version:classifier"
|
//compile "some.group:artifact:version:classifier"
|
||||||
//compile "some.group:artifact:version"
|
//compile "some.group:artifact:version"
|
||||||
|
|
||||||
|
// toml parser
|
||||||
compile "net.consensys.cava:cava-toml:0.3.1"
|
compile "net.consensys.cava:cava-toml:0.3.1"
|
||||||
|
|
||||||
// real examples
|
// real examples
|
||||||
|
@ -83,6 +85,8 @@ shadowJar {
|
||||||
relocate 'net.consensys.cava', 'shadow.turnbasedmc.net.consensys.cava'
|
relocate 'net.consensys.cava', 'shadow.turnbasedmc.net.consensys.cava'
|
||||||
relocate 'org.antlr.v4', 'shadow.turnbasedmc.org.antlr.v4'
|
relocate 'org.antlr.v4', 'shadow.turnbasedmc.org.antlr.v4'
|
||||||
relocate 'javax.annotation', 'shadow.turnbasedmc.javax.annotation'
|
relocate 'javax.annotation', 'shadow.turnbasedmc.javax.annotation'
|
||||||
|
|
||||||
|
relocate 'fr.delthas', 'shadow.turnbasedmc.fr.delthas'
|
||||||
}
|
}
|
||||||
|
|
||||||
reobf { shadowJar { mappingType = "SEARGE" } }
|
reobf { shadowJar { mappingType = "SEARGE" } }
|
||||||
|
|
BIN
libs/javamp3-1.0.3.jar
Normal file
BIN
libs/javamp3-1.0.3.jar
Normal file
Binary file not shown.
|
@ -1,18 +1,17 @@
|
||||||
package com.seodisparate.TurnBasedMinecraft.client;
|
package com.seodisparate.TurnBasedMinecraft.client;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.*;
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FilenameFilter;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import javax.sound.midi.MidiSystem;
|
import javax.sound.midi.MidiSystem;
|
||||||
import javax.sound.midi.Sequencer;
|
import javax.sound.midi.Sequencer;
|
||||||
import javax.sound.sampled.AudioSystem;
|
import javax.sound.sampled.*;
|
||||||
import javax.sound.sampled.Clip;
|
|
||||||
import javax.sound.sampled.FloatControl;
|
|
||||||
import javax.sound.sampled.LineUnavailableException;
|
|
||||||
|
|
||||||
|
import fr.delthas.javamp3.Sound;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import com.seodisparate.TurnBasedMinecraft.common.TurnBasedMinecraftMod;
|
import com.seodisparate.TurnBasedMinecraft.common.TurnBasedMinecraftMod;
|
||||||
|
@ -31,7 +30,9 @@ public class BattleMusic
|
||||||
private Clip clip;
|
private Clip clip;
|
||||||
private boolean playingIsSilly;
|
private boolean playingIsSilly;
|
||||||
private boolean isPlaying;
|
private boolean isPlaying;
|
||||||
|
private Thread mp3StreamThread;
|
||||||
|
private MP3Streamer mp3StreamRunnable;
|
||||||
|
|
||||||
public BattleMusic(Logger logger)
|
public BattleMusic(Logger logger)
|
||||||
{
|
{
|
||||||
initialized = false;
|
initialized = false;
|
||||||
|
@ -39,7 +40,9 @@ public class BattleMusic
|
||||||
battleMusic = new ArrayList<File>();
|
battleMusic = new ArrayList<File>();
|
||||||
sillyMusic = new ArrayList<File>();
|
sillyMusic = new ArrayList<File>();
|
||||||
isPlaying = false;
|
isPlaying = false;
|
||||||
|
mp3StreamThread = null;
|
||||||
|
mp3StreamRunnable = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sequencer = MidiSystem.getSequencer();
|
sequencer = MidiSystem.getSequencer();
|
||||||
sequencer.open();
|
sequencer.open();
|
||||||
|
@ -88,14 +91,15 @@ public class BattleMusic
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String ext = name.substring(extIndex + 1).toLowerCase();
|
String ext = name.substring(extIndex + 1).toLowerCase();
|
||||||
return ext.equals("mid") || ext.equals("wav");
|
return ext.equals("mid") || ext.equals("wav") || ext.equals("mp3");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for(File f : battleFiles)
|
for(File f : battleFiles)
|
||||||
{
|
{
|
||||||
battleMusic.add(f);
|
battleMusic.add(f);
|
||||||
}
|
}
|
||||||
|
logger.info("Got " + battleMusic.size() + " battle music files");
|
||||||
|
|
||||||
File[] sillyFiles = sillyMusicFolder.listFiles(new FilenameFilter() {
|
File[] sillyFiles = sillyMusicFolder.listFiles(new FilenameFilter() {
|
||||||
@Override
|
@Override
|
||||||
public boolean accept(File dir, String name)
|
public boolean accept(File dir, String name)
|
||||||
|
@ -106,14 +110,15 @@ public class BattleMusic
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String ext = name.substring(extIndex + 1).toLowerCase();
|
String ext = name.substring(extIndex + 1).toLowerCase();
|
||||||
return ext.equals("mid") || ext.equals("wav");
|
return ext.equals("mid") || ext.equals("wav") || ext.equals("mp3");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for(File f : sillyFiles)
|
for(File f : sillyFiles)
|
||||||
{
|
{
|
||||||
sillyMusic.add(f);
|
sillyMusic.add(f);
|
||||||
}
|
}
|
||||||
|
logger.info("Got " + sillyMusic.size() + " battle music files");
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
pickNextBattle();
|
pickNextBattle();
|
||||||
|
@ -154,7 +159,7 @@ public class BattleMusic
|
||||||
{
|
{
|
||||||
volume = 1.0f;
|
volume = 1.0f;
|
||||||
}
|
}
|
||||||
play(nextBattle, volume);
|
play(nextBattle, volume, true);
|
||||||
pickNextBattle();
|
pickNextBattle();
|
||||||
playingIsSilly = false;
|
playingIsSilly = false;
|
||||||
isPlaying = true;
|
isPlaying = true;
|
||||||
|
@ -170,13 +175,13 @@ public class BattleMusic
|
||||||
{
|
{
|
||||||
volume = 1.0f;
|
volume = 1.0f;
|
||||||
}
|
}
|
||||||
play(nextSilly, volume);
|
play(nextSilly, volume, false);
|
||||||
pickNextSilly();
|
pickNextSilly();
|
||||||
playingIsSilly = true;
|
playingIsSilly = true;
|
||||||
isPlaying = true;
|
isPlaying = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void play(File next, float volume)
|
private void play(File next, float volume, boolean isBattleType)
|
||||||
{
|
{
|
||||||
if(initialized && next != null)
|
if(initialized && next != null)
|
||||||
{
|
{
|
||||||
|
@ -187,9 +192,21 @@ public class BattleMusic
|
||||||
String suffix = next.getName().substring(next.getName().length() - 3).toLowerCase();
|
String suffix = next.getName().substring(next.getName().length() - 3).toLowerCase();
|
||||||
if(suffix.equals("mid"))
|
if(suffix.equals("mid"))
|
||||||
{
|
{
|
||||||
sequencer.stop();
|
if(sequencer.isRunning())
|
||||||
clip.stop();
|
{
|
||||||
clip.close();
|
sequencer.stop();
|
||||||
|
}
|
||||||
|
if(clip.isActive())
|
||||||
|
{
|
||||||
|
clip.stop();
|
||||||
|
clip.close();
|
||||||
|
}
|
||||||
|
if(mp3StreamThread != null && mp3StreamThread.isAlive())
|
||||||
|
{
|
||||||
|
mp3StreamRunnable.setKeepPlaying(false);
|
||||||
|
try { mp3StreamThread.join(); } catch (Throwable t) { /* ignored */ }
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sequencer.setSequence(new BufferedInputStream(new FileInputStream(next)));
|
sequencer.setSequence(new BufferedInputStream(new FileInputStream(next)));
|
||||||
} catch (Throwable t)
|
} catch (Throwable t)
|
||||||
|
@ -197,7 +214,7 @@ public class BattleMusic
|
||||||
logger.error("Failed to play battle music (midi)");
|
logger.error("Failed to play battle music (midi)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sequencer.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
|
sequencer.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
|
||||||
sequencer.start();
|
sequencer.start();
|
||||||
}
|
}
|
||||||
|
@ -212,22 +229,67 @@ public class BattleMusic
|
||||||
clip.stop();
|
clip.stop();
|
||||||
clip.close();
|
clip.close();
|
||||||
}
|
}
|
||||||
|
if(mp3StreamThread != null && mp3StreamThread.isAlive())
|
||||||
|
{
|
||||||
|
mp3StreamRunnable.setKeepPlaying(false);
|
||||||
|
try { mp3StreamThread.join(); } catch (Throwable t) { /* ignored */ }
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
clip.open(AudioSystem.getAudioInputStream(next));
|
clip.open(AudioSystem.getAudioInputStream(next));
|
||||||
} catch(Throwable t)
|
} catch(Throwable t)
|
||||||
{
|
{
|
||||||
logger.error("Failed to load battle music (wav)");
|
logger.error("Failed to play battle music (wav)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set volume
|
// set volume
|
||||||
FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
|
FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
|
||||||
gainControl.setValue(volume * 20.0f - 20.0f); // in decibels
|
gainControl.setValue(volume * 20.0f - 20.0f); // in decibels
|
||||||
|
|
||||||
clip.loop(Clip.LOOP_CONTINUOUSLY);
|
clip.loop(Clip.LOOP_CONTINUOUSLY);
|
||||||
clip.start();
|
clip.start();
|
||||||
}
|
}
|
||||||
|
else if(suffix.equals("mp3"))
|
||||||
|
{
|
||||||
|
if(sequencer.isRunning())
|
||||||
|
{
|
||||||
|
sequencer.stop();
|
||||||
|
}
|
||||||
|
if(clip.isActive())
|
||||||
|
{
|
||||||
|
clip.stop();
|
||||||
|
clip.close();
|
||||||
|
}
|
||||||
|
if(mp3StreamThread != null && mp3StreamThread.isAlive())
|
||||||
|
{
|
||||||
|
mp3StreamRunnable.setKeepPlaying(false);
|
||||||
|
try { mp3StreamThread.join(); } catch (Throwable t) { /* ignored */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(mp3StreamRunnable == null)
|
||||||
|
{
|
||||||
|
mp3StreamRunnable = new MP3Streamer(next, logger, volume);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mp3StreamRunnable.setMp3File(next);
|
||||||
|
mp3StreamRunnable.setVolume(volume);
|
||||||
|
}
|
||||||
|
mp3StreamThread = new Thread(mp3StreamRunnable);
|
||||||
|
mp3StreamThread.start();
|
||||||
|
|
||||||
|
logger.info("Started playing mp3 " + next.getName());
|
||||||
|
}
|
||||||
|
catch (Throwable t)
|
||||||
|
{
|
||||||
|
logger.error("Failed to play battle music (mp3)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,11 +298,14 @@ public class BattleMusic
|
||||||
sequencer.stop();
|
sequencer.stop();
|
||||||
clip.stop();
|
clip.stop();
|
||||||
clip.close();
|
clip.close();
|
||||||
|
if(mp3StreamThread != null && mp3StreamThread.isAlive())
|
||||||
|
{
|
||||||
|
mp3StreamRunnable.setKeepPlaying(false);
|
||||||
|
try { mp3StreamThread.join(); } catch (Throwable t) { /* ignored */ }
|
||||||
|
}
|
||||||
if(resumeMCSounds)
|
if(resumeMCSounds)
|
||||||
{
|
{
|
||||||
Minecraft.getMinecraft().addScheduledTask(() -> {
|
Minecraft.getMinecraft().addScheduledTask(() -> Minecraft.getMinecraft().getSoundHandler().resumeSounds() );
|
||||||
Minecraft.getMinecraft().getSoundHandler().resumeSounds();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
isPlaying = false;
|
isPlaying = false;
|
||||||
}
|
}
|
||||||
|
@ -264,4 +329,112 @@ public class BattleMusic
|
||||||
{
|
{
|
||||||
return !sillyMusic.isEmpty();
|
return !sillyMusic.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class MP3Streamer implements Runnable
|
||||||
|
{
|
||||||
|
private AtomicBoolean keepPlaying;
|
||||||
|
private File mp3File;
|
||||||
|
private Logger logger;
|
||||||
|
private float volume;
|
||||||
|
|
||||||
|
public MP3Streamer(File mp3File, Logger logger, float volume)
|
||||||
|
{
|
||||||
|
keepPlaying = new AtomicBoolean(true);
|
||||||
|
this.mp3File = mp3File;
|
||||||
|
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 setMp3File(File mp3File)
|
||||||
|
{
|
||||||
|
this.mp3File = mp3File;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVolume(float volume)
|
||||||
|
{
|
||||||
|
this.volume = volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
keepPlaying.set(true);
|
||||||
|
SourceDataLine sdl = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Sound mp3Sound = new Sound(new FileInputStream(mp3File));
|
||||||
|
AudioFormat audioFormat = mp3Sound.getAudioFormat();
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
byte[] cached = null;
|
||||||
|
int cachedOffset = 0;
|
||||||
|
int cachedSize = 0;
|
||||||
|
byte[] buf = new byte[4096];
|
||||||
|
sdl.start();
|
||||||
|
int read = mp3Sound.read(buf, 0, 4096);
|
||||||
|
while(keepPlaying.get())
|
||||||
|
{
|
||||||
|
if(baos != null)
|
||||||
|
{
|
||||||
|
if(read != -1)
|
||||||
|
{
|
||||||
|
sdl.write(buf, 0, read);
|
||||||
|
baos.write(buf, 0, read);
|
||||||
|
read = mp3Sound.read(buf, 0, 4096);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mp3Sound.close();
|
||||||
|
mp3Sound = 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 mp3", t);
|
||||||
|
}
|
||||||
|
if(sdl != null)
|
||||||
|
{
|
||||||
|
sdl.stop();
|
||||||
|
sdl.flush();
|
||||||
|
sdl.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue