summaryrefslogtreecommitdiff
path: root/src/tetris/audio
diff options
context:
space:
mode:
Diffstat (limited to 'src/tetris/audio')
-rw-r--r--src/tetris/audio/SoundPlayer.java323
-rw-r--r--src/tetris/audio/TetrisSounds.java73
-rw-r--r--src/tetris/audio/papercrumple.wavbin0 -> 369638 bytes
-rw-r--r--src/tetris/audio/pencileraser.wavbin0 -> 474152 bytes
-rw-r--r--src/tetris/audio/pencilsharpen.aifbin0 -> 1303926 bytes
5 files changed, 396 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
diff --git a/src/tetris/audio/TetrisSounds.java b/src/tetris/audio/TetrisSounds.java
new file mode 100644
index 0000000..b28e49a
--- /dev/null
+++ b/src/tetris/audio/TetrisSounds.java
@@ -0,0 +1,73 @@
+/*
+ * Jesse Morgan <jesterpm@u.washington.edu>
+ *
+ * TCSS 305 - Autumn 2009
+ * Tetris Project
+ * 17 November 2009
+ */
+
+package tetris.audio;
+
+import java.util.Observable;
+import java.util.Observer;
+
+import tetris.board.TetrisBoardEvent;
+
+
+/**
+ * Class to play sounds for a tetris game.
+ *
+ * @author Jesse Morgan <jesterpm@u.washington.edu>
+ * @version 1.0 23 November 2009
+ */
+public class TetrisSounds implements Observer {
+ // Private fields.
+ /**
+ * The SoundPlayer.
+ */
+ private final SoundPlayer my_soundplayer;
+
+ /**
+ * Create a Tetris Sound Effects player.
+ */
+ public TetrisSounds() {
+ my_soundplayer = new SoundPlayer();
+ }
+
+ /**
+ * Handle notifications.
+ *
+ * @param the_observable The TetrisBoard.
+ * @param the_arg The Event.
+ */
+ public void update(final Observable the_observable, final Object the_arg) {
+ if (the_arg instanceof TetrisBoardEvent) {
+ final TetrisBoardEvent event = (TetrisBoardEvent) the_arg;
+
+ try {
+ switch (event.getType()) {
+ case NEW_GAME:
+ my_soundplayer.play("tetris/audio/pencilsharpen.aif");
+ break;
+
+ case LINES_CLEARED:
+ my_soundplayer.play("tetris/audio/pencileraser.wav");
+ break;
+
+ case GAME_OVER:
+ my_soundplayer.play("tetris/audio/papercrumple.wav");
+ break;
+
+ default:
+ }
+
+ } catch (final IllegalArgumentException the_exception) {
+ // Couldn't play for some reason...
+ // Sounds aren't important anyways, gracefully ignore
+ return;
+ }
+ }
+ }
+
+
+}
diff --git a/src/tetris/audio/papercrumple.wav b/src/tetris/audio/papercrumple.wav
new file mode 100644
index 0000000..ed8e759
--- /dev/null
+++ b/src/tetris/audio/papercrumple.wav
Binary files differ
diff --git a/src/tetris/audio/pencileraser.wav b/src/tetris/audio/pencileraser.wav
new file mode 100644
index 0000000..ca371ec
--- /dev/null
+++ b/src/tetris/audio/pencileraser.wav
Binary files differ
diff --git a/src/tetris/audio/pencilsharpen.aif b/src/tetris/audio/pencilsharpen.aif
new file mode 100644
index 0000000..a7344b5
--- /dev/null
+++ b/src/tetris/audio/pencilsharpen.aif
Binary files differ