views:

1938

answers:

1

Basically I am trying to use this SoundEffect class in a simple java game I'm working on for my assignment.

import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;

/**
 * This enum encapsulates all the sound effects of a game, so as to separate the sound playing
 * codes from the game codes.
 * 1. Define all your sound effect names and the associated wave file.
 * 2. To play a specific sound, simply invoke SoundEffect.SOUND_NAME.play().
 * 3. You might optionally invoke the static method SoundEffect.init() to pre-load all the
 *    sound files, so that the play is not paused while loading the file for the first time.
 * 4. You can use the static variable SoundEffect.volume to mute the sound.
 */
public enum SoundEffect {
   EAT("eat.wav"),   // explosion
   GONG("gong.wav"),         // gong
   SHOOT("shoot.wav");       // bullet

   // Nested class for specifying volume
   public static enum Volume {
      MUTE, LOW, MEDIUM, HIGH
   }

   public static Volume volume = Volume.LOW;

   // Each sound effect has its own clip, loaded with its own sound file.
   private Clip clip;

   // Constructor to construct each element of the enum with its own sound file.
   SoundEffect(String soundFileName) {
      try {
         // Use URL (instead of File) to read from disk and JAR.
         URL url = this.getClass().getClassLoader().getResource(soundFileName);
         // Set up an audio input stream piped from the sound file.
         AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
         // Get a clip resource.
         clip = AudioSystem.getClip();
         // Open audio clip and load samples from the audio input stream.
         clip.open(audioInputStream);
      } catch (UnsupportedAudioFileException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      } catch (LineUnavailableException e) {
         e.printStackTrace();
      }
   }

   // Play or Re-play the sound effect from the beginning, by rewinding.
   public void play() {
      if (volume != Volume.MUTE) {
         if (clip.isRunning())
            clip.stop();   // Stop the player if it is still running
         clip.setFramePosition(0); // rewind to the beginning
         clip.start();     // Start playing
      }
   }

   // Optional static method to pre-load all the sound files.
   static void init() {
      values(); // calls the constructor for all the elements
   }
}

Here is an implementation of the EAT sound in my game's Reward class-

public void react(CollisionEvent e)
    {
        Player player = game.getPlayer();
        if (e.contact.involves(player)) {
            player.changePlayerImageEAT();
            SoundEffect.EAT.play();
            player.addPoint();
            System.out.println("Player now has: "+player.getPoints()+ " points.");
            game.getCurrentLevel().getWorld().remove(this);
        }
    }

This should play the EAT sound when player comes in contact with a reward in my game.

However, when my player collides with a reward, I get the following errors in the terminal-

javax.sound.sampled.LineUnavailableException: line with format ALAW 8000.0 Hz, 8 bit, stereo, 2 bytes/frame, not supported. at com.sun.media.sound.DirectAudioDevice$DirectDL.implOpen(DirectAudioDevice.java:494) at com.sun.media.sound.DirectAudioDevice$DirectClip.implOpen(DirectAudioDevice.java:1280) at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:107) at com.sun.media.sound.DirectAudioDevice$DirectClip.open(DirectAudioDevice.java:1061) at com.sun.media.sound.DirectAudioDevice$DirectClip.open(DirectAudioDevice.java:1151) at SoundEffect.(SoundEffect.java:39) at SoundEffect.(SoundEffect.java:15) at Reward.react(Reward.java:41) at city.soi.platform.World.despatchCollisionEvents(World.java:425) at city.soi.platform.World.step(World.java:608) at city.soi.platform.World.access$000(World.java:42) at city.soi.platform.World$1.actionPerformed(World.java:756) at javax.swing.Timer.fireActionPerformed(Timer.java:271) at javax.swing.Timer$DoPostEvent.run(Timer.java:201) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209) at java.awt.EventQueue.dispatchEvent(EventQueue.java:597) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) Exception in thread "AWT-EventQueue-0" java.lang.ExceptionInInitializerError at Reward.react(Reward.java:41) at city.soi.platform.World.despatchCollisionEvents(World.java:425) at city.soi.platform.World.step(World.java:608) at city.soi.platform.World.access$000(World.java:42) at city.soi.platform.World$1.actionPerformed(World.java:756) at javax.swing.Timer.fireActionPerformed(Timer.java:271) at javax.swing.Timer$DoPostEvent.run(Timer.java:201) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209) at java.awt.EventQueue.dispatchEvent(EventQueue.java:597) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) Caused by: java.lang.NullPointerException at com.sun.media.sound.WaveFileReader.getAudioInputStream(WaveFileReader.java:180) at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1128) at SoundEffect.(SoundEffect.java:35) at SoundEffect.(SoundEffect.java:16) ... 15 more

I can't figure out what wrong. I'm guessing it has something to do with my audio files (WAV) being unsupported. However, no matter how many ways I convert them they still don't work.

It would be really helpful if someone can kindly enlighten me on what might be wrong and how I can resolve this.

Sample code and any modifications you can offer to help make this code work will be greatly appreciated.

Thank you.

+4  A: 

Your root cause Exception is

javax.sound.sampled.LineUnavailableException:
 line with format ALAW 8000.0 Hz, 8 bit, stereo, 2 bytes/frame, not supported

This occurs because not all sound drivers support all bit rates or encodings, or because the machine just doesn't have a sound card. Sound can be encoded in A law or mu law (or others, such as MP3) and can be encoded at different bit rates and sample sizes. Java does not always support all possible sound formats, depending on what is supported by the base system.

You probably want to do the following:

  • Ensure that the computer on which you're running the program has a reasonable sound card. Most of the time when I see the above Exception, I'm running on server machine with no built-in sound card or with a really lame sound card or with no audio path.
  • If you're using a remote terminal or something like this, ensure that the sound has a configured way to play.
  • Try re-encoding your sound sample at a different rate, or perhaps as a WAV file, and then try playing it.
Eddie