Game Freezes for Duration of Sounds

I have just implemented my very first sound “engine” for my game and did it probably very messily because I don’t know a whole lot about sounds and Java. Anyways, I have this class:

package Engine;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

public class SoundEngine {

	private static final int BUFFER_SIZE = 128000;
	private static File soundFile;
	public static boolean isLoop = false;
	private static AudioInputStream audioStream;
	private static AudioFormat audioFormat;
	private static SourceDataLine sourceLine;

	public static void play(String filename) {

		String strFilename = filename;

		try {
			soundFile = new File(Frame.class.getResource("imgs/" + strFilename).getFile());
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}

		try {
			audioStream = AudioSystem.getAudioInputStream(soundFile);
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}

		audioFormat = audioStream.getFormat();

		DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
		try {
			sourceLine = (SourceDataLine) AudioSystem.getLine(info);
			sourceLine.open(audioFormat);
		} catch (LineUnavailableException e) {
			e.printStackTrace();
			System.exit(1);
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}

		sourceLine.start();

		int nBytesRead = 0;
		byte[] abData = new byte[BUFFER_SIZE];
		while (nBytesRead != -1 && isLoop != false) {
			try {
				nBytesRead = audioStream.read(abData, 0, abData.length);
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (nBytesRead >= 0) {
				@SuppressWarnings("unused")
				int nBytesWritten = sourceLine.write(abData, 0, nBytesRead);
			}
		}

		sourceLine.drain();
		sourceLine.close();
	}

	public static void playSound(final String fileName, final boolean isLoopw) {
		isLoop = isLoopw;
		Thread t = new Thread(new Runnable() {
			public void run() {
				play(fileName);
			}
		});

		t.setDaemon(true);
		t.start();
	}

	public static void playSound(final String fileName) {
		Thread t = new Thread(new Runnable() {
			public void run() {
				play(fileName);
			}
		});

		t.setDaemon(true);
		t.start();
	}
}

and this class:


package Engine;

public class Sounds {

	public static String explosion = "explosion.wav";
        public static String inGameMusic = "inGameMusic.wav";

}

which holds all the names for my game. My problem is, whenever I call a sound, namely the explosion because that’s the only one I have right now, the game freezes for the duration of the sound, and then continues when the sound is done. I think this definitely has something to do with Threads, but I am not confident in that area at all either so should I multi-thread, one for the game, and one for the sounds and if so, how?

Thanks,
-cMp


Thread t = new Thread(new Runnable()
{
    public void run()
    {
        SoundEngine.playSound(fileName);
    }
});

t.setDaemon(true);
t.start();

EDIT: Added in setDaemon(true); to avoid playing sounds after exit.

Ok, I understand the basic thread calling and making after looking at that and a bit of research, but I wanted the method (playSound) to be something I could just call anywhere. Is there a way to do this, or would I have to type this out every time? I’m guessing just a simple method in my main class would do this but there may be side effects that I am unaware of.


public static void playSound(fileName)
{
    Thread t = new Thread(new Runnable()
    {
        public void run()
        {
            SoundEngine.playSound(fileName);
        }
    });
    t.setDaemon(true);
    t.start();
}

Awesome, this is great and works perfectly! It’s always good to learn something new :slight_smile:

EDIT: This is really awesome, but I have a single problem. For my background music, I start playing it at the beginning, but as soon as another sound is called the music stops. Any reasons this would happen with my current setup?
EDIT 2: The way I access this is by static access. e.g; SoundEngine.playSound(xxx, false);

You’re using static, which means there is only one sound ever being played.

This should work:

New Code

It does, and very well :slight_smile: my game is totally different with music in it!

Never use a Thread per sound, or open multiple lines at the same time - it’ll break or play badly on a variety of systems. If you don’t want to get into handling sound mixing yourself, check out TinySound or other libraries on here.