views:

94

answers:

3

I'm developing a Java game and want to bundle and play a number of sampled sound effects. I'm planning to use the standard javax.sound.sampled functionality to play them.

What format is best for these kind of samples? I'm looking for a blend of good compression, decent quality and convenience for programmatic use within Java.

+2  A: 

Java has support for mp3, and the mp3 format gives you the choice where to balance compression vs. quality.

There is a pure java MP3 decoder, http://www.javazoom.net/javalayer/javalayer.html, which plugs into the javax.sound package. Sun also have released a mp3 plugin for java sound.

mdma
There are also ports for FLAC and Vorbis codecs available, look for JFlac/Jorbis (these are slightly more demanding on CPU, but avoid the MP3 license issues).If deployment is a concern, WAV is probably the most painless since support included in the JRE by default. JLayer/JFlac and Jorbis are also (mostly) painless to integrate (i used all of them for a music player).
Durandal
+2  A: 

I'm no expert on this, but all the tutorials and examples from Sun work with .au files. Seems to be a guaranteed lowest-common-denominator. For more flexibility in file formats, you'd need to work with something like the Java Media Framework.

Carl Smotricz
There's an mp3 plugin for the JMF: http://java.sun.com/javase/technologies/desktop/media/jmf/mp3/download.html
Marcus Adams
Thanks this is a useful steer!
mikera
+1  A: 

Quality vs. Size

Here are some interesting articles on the differences of MP3 vs. WAV.

Why MP3 and WAV? These are the ones I see most often when creating program, so compatibility is never an issue.

I have this really useful java file that does everything for you. You construct the object with the path to the sound file, then use methods to play, stop, loop it, etc.

In the meantime, you can look at these for reference, albeit they're not as clean: http://stackoverflow.com/questions/26305/how-can-i-play-sound-in-java .


Simple Programming

Unfortunately, I don't have the file on this computer, but here's a simplified version. This doesn't use javax.swing like you'd hoped, but to be honest, I've always preferred alternative methods.

Because this is not the same as the file I have on my other computer, I cannot guarantee MP3 compatibility.

import  sun.audio.*;
import  java.io.*;

public class Sound {

    private InputStream input;
    private AudioStream audio;

    public Sound (File fileName)
    {
        input = new FileInputStream();
        audio = new AudioStream(input);
    }

    public void play()
    {
        AudioPlayer.player.start(audio);
    }

    public void stop()
    {
        AudioPlayer.player.stop(audio);
    }

}

Instantiation:

String projectPath = <project directory>; // getting this is another question    
Sound helloSound = new Sound(new File(projectPath + "/Sounds"));

Now you can call helloSound.play(); whenever you want the clip to be played.

I prefer this method so you don't have to constantly set everything up a stream each time you want to play a clip. This should work effectively with a few sound bites and blurbs, but be sure not to overuse it and take up memory. Use this for common sound effects.


Simple Programming, Cont'd

Found a good file to play MP3s in the same way as I showed above. I completely forgot to put mine in a separate thread, so this is a much better bet.

import java.io.BufferedInputStream;
import java.io.FileInputStream;

import javazoom.jl.player.Player;


public class MP3 {
    private String filename;
    private Player player; 

    // constructor that takes the name of an MP3 file
    public MP3(String filename) {
        this.filename = filename;
    }

    public void close() { if (player != null) player.close(); }

    // play the MP3 file to the sound card
    public void play() {
        try {
            FileInputStream fis     = new FileInputStream(filename);
            BufferedInputStream bis = new BufferedInputStream(fis);
            player = new Player(bis);
        }
        catch (Exception e) {
            System.out.println("Problem playing file " + filename);
            System.out.println(e);
        }

        // run in new thread to play in background
        new Thread() {
            public void run() {
                try { player.play(); }
                catch (Exception e) { System.out.println(e); }
            }
        }.start();




    }


    // test client
    public static void main(String[] args) {
        String filename = args[0];
        MP3 mp3 = new MP3(filename);
        mp3.play();

        // do whatever computation you like, while music plays
        int N = 4000;
        double sum = 0.0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                sum += Math.sin(i + j);
            }
        }
        System.out.println(sum);

        // when the computation is done, stop playing it
        mp3.close();

        // play from the beginning
        mp3 = new MP3(filename);
        mp3.play();

    }

}

Easy as pie, right? ;).

Get the jar here. See the documentation here.

Justian Meyer
Thanks for the great links and sample code!
mikera
You're welcome :).
Justian Meyer