Using javax.sound.sampled.Clip to play, loop, and stop multiple sounds in a game. Unexpected Errors
I was able to get the code working and now have a better understanding of Clips. The page that helped me the most was http://www3.ntu.edu.sg/home/ehchua/programming/java/J8c_PlayingSound.html it breaks everything down and helped me see where I made mistakes. Here is my final working code. As before if you see any horrible errors or over sights in logic or style let me know.
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
* Handles playing, stoping, and looping of sounds for the game.
* @author Tyler Thomas
*
*/
public class Sound {
private Clip clip;
public Sound(String fileName) {
// specify the sound to play
// (assuming the sound can be played by the audio system)
// from a wave File
try {
File file = new File(fileName);
if (file.exists()) {
AudioInputStream sound = AudioSystem.getAudioInputStream(file);
// load the sound into memory (a Clip)
clip = AudioSystem.getClip();
clip.open(sound);
}
else {
throw new RuntimeException("Sound: file not found: " + fileName);
}
}
catch (MalformedURLException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Malformed URL: " + e);
}
catch (UnsupportedAudioFileException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Unsupported Audio File: " + e);
}
catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Input/Output Error: " + e);
}
catch (LineUnavailableException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Line Unavailable Exception Error: " + e);
}
// play, stop, loop the sound clip
}
public void play(){
clip.setFramePosition(0); // Must always rewind!
clip.start();
}
public void loop(){
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
public void stop(){
clip.stop();
}
}
I found a useful technique to stop sound. You can copy these two classes down and test it out for yourself. Nevertheless, the clip.stop() method is more of a pause method. It stops the sound from playing, yes, but it does not clear the sound from the line. As a result, the sound is still queued to play and no new sound can be played. So using the clip.close() method will clear out this queued data and allow a new sound to be played or another action to take place. Also note in the following code a sound file was placed in the project folder called "predator.wav" this sound can be any type of sound you want to use instead of the sound I chose, but be sure it is a .wav format and the sound must be in the top-most tier of the project folder.
/*
* File: KeyMap.java
* Author: Andrew Peturis Chaselyn Langley; UAB EE Students
* Assignment: SoundBox - EE333 Fall 2015
* Vers: 1.0.0 10/20/2015 agp - initial coding
*
* Credits: Dr. Green, UAB EE Engineering Professor
*/
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class KeyMap {
private char keyCode;
private String song;
private Clip clip;
// Don't allow default constructor
private KeyMap() {
}
public KeyMap(char keyCode, String song) throws LineUnavailableException {
this.keyCode = keyCode;
this.song = song;
// Create an audiostream from the inputstream
clip = AudioSystem.getClip();
}
public boolean match(char key) {
return key == keyCode;
}
// Play a sound using javax.sound and Clip interface
public String play() {
try {
// Open a sound file stored in the project folder
clip.open(AudioSystem.getAudioInputStream(new File(song + ".wav")));
// Play the audio clip with the audioplayer class
clip.start();
// Create a sleep time of 2 seconds to prevent any action from occuring for the first
// 2 seconds of the sound playing
Thread.sleep(2000);
} catch (LineUnavailableException | UnsupportedAudioFileException | IOException | InterruptedException e) {
System.out.println("Things did not go well");
System.exit(-1);
}
return song;
}
// Stop a sound from playing and clear out the line to play another sound if need be.
public void stop() {
// clip.stop() will only pause the sound and still leave the sound in the line
// waiting to be continued. It does not actually clear the line so a new action could be performed.
clip.stop();
// clip.close(); will clear out the line and allow a new sound to play. clip.flush() was not
// used because it can only flush out a line of data already performed.
clip.close();
}
}
/*
* File: SoundBox.java
* Author: Andrew Peturis, Chaselyn Langley; UAB EE Students
* Assignment: GUI SoundBox - EE333 Fall 2015
* Vers: 1.0.0 09/08/2015 agp - initial coding
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
import javax.sound.sampled.LineUnavailableException;
/**
*
* @author Andrew Peturis, Chaselyn Langley
*
*/
public class SoundBox {
static Scanner scanner = new Scanner(System.in); //Scanner object to read user input
InputStream input;
/**
* @param args the command line arguments
* @throws java.io.IOException
*/
public static void main(String[] args) throws IOException, LineUnavailableException {
String line;
Character firstChar;
String predator = "predator";
String explosion = "explosion";
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
KeyMap[] keyedSongs = {
new KeyMap('a', predator),};
while (true) {
line = br.readLine();
firstChar = line.charAt(0);
for (int i = 0; i < keyedSongs.length; i++) {
if (keyedSongs[i].match(firstChar)) {
// Notice now by running the code, after the first second of sleep time the sound can
// and another sound can be played in its place
keyedSongs[i].stop();
System.out.println("Played the sound: " + keyedSongs[i].play());
break;
}
}
if (firstChar == 'q') {
break;
}
}
}
}