diff options
author | Jesse Morgan <jesse@jesterpm.net> | 2012-12-13 22:14:24 -0800 |
---|---|---|
committer | Jesse Morgan <jesse@jesterpm.net> | 2012-12-13 22:14:24 -0800 |
commit | 87e98e00e0ca5ac4229091aa9bb0e5c09093f50f (patch) | |
tree | b3e73ba3a22d1e04a6dd87111db27ac7d698d5f3 /src/tetris/audio/SoundPlayer.java |
Tetris project from TCSS305 class.
Original project was in SVN on the school servers, so the
versioning history is gone.
Diffstat (limited to 'src/tetris/audio/SoundPlayer.java')
-rw-r--r-- | src/tetris/audio/SoundPlayer.java | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/src/tetris/audio/SoundPlayer.java b/src/tetris/audio/SoundPlayer.java new file mode 100644 index 0000000..6e2cf8f --- /dev/null +++ b/src/tetris/audio/SoundPlayer.java @@ -0,0 +1,323 @@ +/* + * Audio Clip Player TCSS 305 - Autumn 2008 (Zimmerman) + */ + +package tetris.audio; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.Line; +import javax.sound.sampled.LineEvent; +import javax.sound.sampled.LineListener; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.UnsupportedAudioFileException; + +/** + * A class to play audio clips. Caches previously-played clips, allowing fast + * re-playback of previously played sounds. + * + * @author Marty Stepp + * @author Daniel M. Zimmerman (code cleanup) + * @version 1.0 + */ + +public class SoundPlayer { + /** + * A cache of previously-played audio clips. + */ + + private final Map<String, Clip> my_clips = new HashMap<String, Clip>(); + + /** + * Plays the audio file with the given file name. This method returns + * instantly, without waiting for the clip to finish playing. + * + * @param the_filename The name of the file (relative to the current working + * directory) to play. + * @return a Clip object representing the sound played. (for convenience; this + * result need not be used/stored). + * @exception IllegalArgumentException if there is a problem reading from the + * sound file. + */ + + public Clip play(final String the_filename) throws IllegalArgumentException { + final Clip clip = getClip(the_filename); + + if (clip != null) { + clip.start(); + } + + return clip; + } + + /** + * Plays the audio file with the given file name, waiting until the clip is + * done playing before returning. + * + * @param the_filename The name of the file (relative to the current working + * directory) to play. + * @return a Clip object representing the sound played. (for convenience; this + * result need not be used/stored). + * @exception IllegalArgumentException if there is a problem reading from the + * sound file. + */ + + public Clip playAndWait(final String the_filename) throws IllegalArgumentException { + final Clip clip = getClip(the_filename); + + if (clip != null) { + clip.start(); + try { + synchronized (clip) { + while (clip.isRunning()) { + clip.wait(); // wait for clip to finish + } + } + } catch (final InterruptedException ie) { + // ignored + return clip; + } + } + + return clip; + } + + /** + * Plays the clip with the given file name in a continuous loop. The clip + * keeps looping until it is later stopped by calling the stop() method. This + * function returns instantly + * + * @param the_filename The name of the file (relative to the current working + * directory) to play. + * @return a Clip object representing the sound played. (for convenience; this + * result need not be used/stored). + * @exception IllegalArgumentException if there is a problem reading from the + * sound file. + */ + + public Clip loop(final String the_filename) throws IllegalArgumentException { + return loop(the_filename, Clip.LOOP_CONTINUOUSLY); + } + + /** + * Plays the clip with the given file name in a loop. The clip loops until it + * has played the specified number of times, or until it is later stopped by + * calling the stop() method. This function returns instantly, without waiting + * for the clip to finish looping. + * + * @param the_filename The name of the file (relative to the current working + * directory) to play. + * @param the_number_of_times The number of times to loop the clip. + * @return a Clip object representing the sound played. (for convenience; this + * result need not be used/stored). + * @exception IllegalArgumentException if there is a problem reading from the + * sound file. + */ + + public Clip loop(final String the_filename, final int the_number_of_times) + throws IllegalArgumentException { + final Clip clip = getClip(the_filename); + + if (clip != null) { + clip.loop(the_number_of_times); + } + + return clip; + } + + /** + * Plays the clip with the given file name in a loop. The clip loops + * continuously until it is stopped by calling the stop() method. This method + * waits until the clip is done looping before returning. Note that since the + * clip loops continuously, this method will not return unless some other + * thread stops the clip. + * + * @param the_filename The name of the file (relative to the current working + * directory) to play. + * @return a Clip object representing the sound played. (for convenience; this + * result need not be used/stored). + * @exception IllegalArgumentException if there is a problem reading from the + * sound file. + */ + + public Clip loopAndWait(final String the_filename) throws IllegalArgumentException { + return loopAndWait(the_filename, Clip.LOOP_CONTINUOUSLY); + } + + /** + * Plays the clip with the given file name in a loop. The clip loops until it + * has played the specified number of times, or until it is stopped by calling + * the stop() method. This method waits until the clip is done looping before + * returning. + * + * @param the_filename The name of the file (relative to the current working + * directory) to play. + * @param the_number_of_times The number of times to loop the clip. + * @return a Clip object representing the sound played. (for convenience; this + * result need not be used/stored). + * @exception IllegalArgumentException if there is a problem reading from the + * sound file. + */ + + public Clip loopAndWait(final String the_filename, final int the_number_of_times) + throws IllegalArgumentException { + final Clip clip = getClip(the_filename); + + if (clip != null) { + clip.loop(the_number_of_times); + try { + while (clip.isRunning()) { + clip.wait(); // wait for clip to finish + } + } catch (final InterruptedException ie) { + return clip; + } + } + + return clip; + } + + /** + * Pauses the clip with the given file name. If the clip is later played, it + * will resume from where it was paused. Calling this method does not resume a + * thread that is suspended on a playAndWait() or a loopAndWait(). + * + * If stop() is called on a paused clip, it will reset to the beginning of the + * clip for the next play. + * + * @param the_filename The name of the file (relative to the current working + * directory) to pause. + * @exception IllegalArgumentException if there is a problem reading from or + * playing the sound file. + */ + + public void pause(final String the_filename) throws IllegalArgumentException { + final Clip clip = getClip(the_filename); + + if (clip != null) { + final int pos = clip.getFramePosition(); + clip.stop(); + clip.setFramePosition(pos); + } + } + + /** + * Stops the clip with the specified filename (and wakes up any threads + * waiting for it to finish playing). + * + * @param the_filename The name of the file (relative to the current working + * directory) to stop. + * @return a Clip object representing the sound stopped. + * @exception IllegalArgumentException if there is a problem reading from the + * sound file. + */ + + public Clip stop(final String the_filename) throws IllegalArgumentException { + final Clip clip = getClip(the_filename); + stopClip(clip); + + return clip; + } + + /** + * Stops all currently playing sound clips (and wakes up the threads waiting + * for them to finish playing). + */ + + public void stopAll() { + for (Clip clip : my_clips.values()) { + stopClip(clip); + } + } + + /** + * Preloads the clip at the given file name. This means the clip will be + * available faster, when requested for playing the first time. + * + * @param the_filename The name of the file (relative to the current working + * directory) to preload. + * @return a Clip object representing the preloaded sound. + * @exception IllegalArgumentException if there is a problem reading from the + * sound file. + */ + + public Clip preLoad(final String the_filename) throws IllegalArgumentException { + return getClip(the_filename); + } + + /** + * Returns a Clip object for a filename, either by creating a new one or + * loading it from the cache. + * + * @param the_filename The name of the file (relative to the current working + * directory) to load. + * @return a Clip object, or null if one is not found. + * @exception IllegalArgumentException if there is a problem reading from the + * sound file. + */ + + private Clip getClip(final String the_filename) throws IllegalArgumentException { + Clip clip = null; + AudioInputStream ais = null; + + if (my_clips.containsKey(the_filename)) { + clip = my_clips.get(the_filename); + } else { + // read audio file from disk + try { + ais = AudioSystem.getAudioInputStream(ClassLoader.getSystemResource(the_filename)); + clip = (Clip) AudioSystem.getLine(new Line.Info(Clip.class)); + clip.open(ais); + clip.addLineListener(new LineListener() { + /** + * Responds to audio events generated by clips. + * + * @param the_event The event generated. + */ + + public void update(final LineEvent the_event) { + if (the_event.getType() == LineEvent.Type.STOP) { + // clip is done playing + stopClip((Clip) the_event.getSource()); + } + } + }); + my_clips.put(the_filename, clip); + } catch (final UnsupportedAudioFileException uafe) { + throw new IllegalArgumentException("Not a valid supported audio file: \"" + + the_filename + "\""); + } catch (final LineUnavailableException lue) { + throw new IllegalArgumentException("Line is not available to play sound \"" + + the_filename + "\""); + } catch (final IOException ioe) { + throw new IllegalArgumentException("I/O error while reading file: \"" + the_filename + + "\""); + } + } + + return clip; + } + + /** + * Stops the playing of the specified clip. + * + * @param the_clip The clip. + */ + + private void stopClip(final Clip the_clip) { + if (the_clip != null) { + synchronized (the_clip) { + the_clip.stop(); + the_clip.setFramePosition(0); + the_clip.notifyAll(); // awaken threads waiting for this Clip + } + } + } +} + +// end of class SoundPlayer |