Java Sound crash fixes for Linux. (issue #1)

- Explicitly supply the AudioFormat when creating a Clip.
- Disable Master Gain if unsupported (e.g. in PulseAudio).
- Do not try to play uninitialized sounds (e.g. LineUnavailableException during creation, seems to happen regularly with PulseAudio).

Other changes:
- Errors replaced with debugs in 'getTrackLength()' if audio fields inaccessible.
- Do not log ThreadDeath exceptions (it's a known issue, and only clutters the log file).

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han 2014-07-08 00:42:50 -04:00
parent a9cc7a3deb
commit 83c475cdc1
3 changed files with 24 additions and 8 deletions

View File

@ -246,7 +246,7 @@ public class MusicController {
/**
* Gets the length of the track, in milliseconds.
* Returns 0f if no file is loaded or an MP3 is currently being converted.
* Returns 0 if no file is loaded or an MP3 is currently being converted.
* @author bdk (http://slick.ninjacave.com/forum/viewtopic.php?t=2699)
*/
public static int getTrackLength() {
@ -265,7 +265,8 @@ public class MusicController {
length.setAccessible(true);
duration = (float) (length.get(audio));
} catch (Exception e) {
Log.error("Could not get track length.", e);
Log.debug("Could not get track length.");
return 0;
}
return (int) (duration * 1000);
}

View File

@ -103,7 +103,8 @@ public class Opsu extends StateBasedGame {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
Log.error("** Uncaught Exception! **", e);
if (!(e instanceof ThreadDeath)) // TODO: see MusicController
Log.error("** Uncaught Exception! **", e);
}
});

View File

@ -23,9 +23,11 @@ import itdelatrisu.opsu.states.Options;
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
@ -154,7 +156,13 @@ public class SoundController {
try {
URL url = ResourceLoader.getResource(ref);
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
// GNU/Linux workaround
// Clip clip = AudioSystem.getClip();
AudioFormat format = audioIn.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(audioIn);
return clip;
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
@ -218,6 +226,9 @@ public class SoundController {
* @param volume the volume [0, 1]
*/
private static void playClip(Clip clip, float volume) {
if (clip == null) // clip failed to load properly
return;
if (volume > 0f) {
// stop clip if running
if (clip.isRunning()) {
@ -225,10 +236,13 @@ public class SoundController {
clip.flush();
}
// set volume
FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
float dB = (float) (Math.log(volume) / Math.log(10.0) * 20.0);
gainControl.setValue(dB);
// PulseAudio does not support Master Gain
if (clip.isControlSupported(FloatControl.Type.MASTER_GAIN)) {
// set volume
FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
float dB = (float) (Math.log(volume) / Math.log(10.0) * 20.0);
gainControl.setValue(dB);
}
// play clip
clip.setFramePosition(0);