sparklyllama
sparklyllama

Reputation: 1326

Playing .wav Song in Java?

I'm trying to play a song in the .wav format in my Java Game, and here's some of the code of the SoundPlayer class:

private static HashMap<String, Clip> clips;
private static int gap;

public static void init() {
    clips = new HashMap<String, Clip>();
    gap = 0;
}

public static void load(String s, String n) {
    if(clips.get(n) != null) return;
    Clip clip;
    try {
        InputStream in = SoundPlayer.class.getResourceAsStream(s);
        InputStream bin = new BufferedInputStream(in);
        AudioInputStream ais = AudioSystem.getAudioInputStream(bin);
        AudioFormat baseFormat = ais.getFormat();
        AudioFormat decodeFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16, baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false);
        AudioInputStream dais = AudioSystem.getAudioInputStream(decodeFormat, ais);
        clip = AudioSystem.getClip();
        clip.open(dais);
        clips.put(n, clip);
    } catch(Exception e) {
        e.printStackTrace();
    }
}

When I call the load() method, it crashes on the line clip.open(dais) and I'm given this error: javax.sound.sampled.LineUnavailableException: Failed to allocate clip data: Requested buffer too large.

This works with short sound effects, so I'm guessing this is because the file is over a minute long. Are there any better ways of doing this?

Thanks!

Upvotes: 2

Views: 866

Answers (2)

Boodog
Boodog

Reputation: 176

I've had some trouble in the past getting sound to work in Java. Here is a good way to load .wav soundclips.

private Clip clip;

public Sound(String fileName)
{
    try
    {
        File file = new File(fileName);
        if (file.exists())
        {
            AudioInputStream sound = AudioSystem.getAudioInputStream(file);
            clip = AudioSystem.getClip();
            clip.open(sound);
        }
        else
        {
            throw new RuntimeException("Sound: file not found: " + fileName);
        }
    }
    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);
    }
}

public void play()
{
    clip.setFramePosition(0);
    clip.start();
}
public void loop()
{
    clip.loop(Clip.LOOP_CONTINUOUSLY);
}
public void stop()
{
    clip.stop();
}

I find that this works great! You can add more exceptions if you'd like as well, like LineUnavailableException, and MalformedURLException. To create a sound clip you make something as such:

private Sound sound = new Sound("/sounds/sound.wav");

then doing

sound.play();

Upvotes: 2

MadProgrammer
MadProgrammer

Reputation: 347324

I don't know why you're trying to decode the AudioFormat manually.

I typically use something along the lines of...

try (InputStream is = new BufferedInputStream(new FileInputStream(SoundPlayer.class.getResourceAsStream(s)))) {
    AudioInputStream audioStream = AudioSystem.getAudioInputStream(is);

    AudioFormat format = audioStream.getFormat();
    DataLine.Info info = new DataLine.Info(Clip.class, format);
    Clip clip = (Clip) AudioSystem.getLine(info);
    clip.open(audioStream);
    clip.start();
    try {
        Thread.sleep(250);
    } catch (InterruptedException ex) {

    }
    clip.drain();
} catch (IOException | LineUnavailableException | UnsupportedAudioFileException ex) {
    ex.printStackTrace();
}

Note, this will block until the Clip is drained, playing all the way to end. I tested a music file of 5 minutes and 48 seconds. I used the above code as well as you code successfully, but to be frank, the code I use is just simpler (less complicated - simple == good :))

Having said all that, try (InputStream is = new BufferedInputStream(new FileInputStream(SoundPlayer.class.getResourceAsStream(s)))) { isn't actually required, as AudioSystem.getAudioInputStream(...); can accept URL and File references, for example...

try {
    AudioInputStream audioStream = AudioSystem.getAudioInputStream(
        SoundPlayer.class.getResourceAsStream(s))));

Upvotes: 0

Related Questions