summaryrefslogtreecommitdiff
path: root/src/tetris/audio/SoundPlayer.java
diff options
context:
space:
mode:
authorJesse Morgan <jesse@jesterpm.net>2012-12-13 22:14:24 -0800
committerJesse Morgan <jesse@jesterpm.net>2012-12-13 22:14:24 -0800
commit87e98e00e0ca5ac4229091aa9bb0e5c09093f50f (patch)
treeb3e73ba3a22d1e04a6dd87111db27ac7d698d5f3 /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.java323
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