JavaSE, via Java Sound API (in packages javax.sound ), supports two types of audio: - Sampled Audio: Sampled audio is represented as a sequence of time-sampled data of the amplitude of sound wave. It is supported in package
javax.sound.sampled . The supported file formats are: "wav", "au" and "aiff". The samples can be either 8-bit or 16-bit, with sampling rate from 8 kHz to 48 kHz. - Musical Instrument Digital Interface (MIDI): MIDI music is synthesized from musical notes and special sound effects, instead of time-sampled, like a recipe for creating musical sound. MIDI is supported in package
javax.sound.midi .
Java Sound API also include a software sound mixer that supports up to 64 channels for sound effect and background music. Java Media Framework (JMF), which is not part of JavaSE, is needed to support MP3 and advanced features. JOAL (Java Bindings on OpenAL) supports 3D sound effect. Sampled AudioTo play sampled audio, you create an instance of a SourceDataLine or a Clip , which acts as a source to the software audio mixer. Audio samples are then loaded into it, and delivered to the mixer. The mixer may mix the samples with those from other sources and then deliver the mix to a target (usually an audio output device on a sound card). javax.sound.Clip
Code Example: import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;
import javax.swing.*;
public class SoundClipTest extends JFrame {
public SoundClipTest() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Test Sound Clip");
this.setSize(300, 200);
this.setVisible(true);
try {
URL url = this.getClass().getClassLoader().getResource("gameover.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new SoundClipTest();
}
}
The steps of playing sounds via Clip are: - Allocate a
AudioInputStream piped from a file or URL, e.g.,
File soundFile = new File("eatfood.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(soundFile);
URL url = new URL("http://www./eatfood.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
URL url = this.getClass().getClassLoader().getResource("eatfood.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
- Allocate a sound
Clip resource via the static method AudioSystem.getClip() :Clip clip = AudioSystem.getClip();
- Open the clip to load sound samples from the audio input stream opened earlier:
clip.open(audioIn);
- You can now play the clip by invoking either the
start() or loop() method
clip.start();
clip.loop(0);
clip.loop(5);
clip.loop(Clip.LOOP_CONTINUOUSLY);
- You can stop the player by invoking
stop() , which may be useful to stop a continuous loop() .if (clip.isRunning()) clip.stop();
Playing Sound Effects for Java GamesA typical game requires various sound effects, e.g., move, eat, shoot, kill, gameover, and etc. The following enumeration encapsulates all the sound effects in a single class, to simplify game programming. import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;
public enum SoundEffect {
EXPLODE("explode.wav"),
GONG("gong.wav"),
SHOOT("shoot.wav");
public static enum Volume {
MUTE, LOW, MEDIUM, HIGH
}
public static Volume volume = Volume.LOW;
private Clip clip;
SoundEffect(String soundFileName) {
try {
URL url = this.getClass().getClassLoader().getResource(soundFileName);
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
clip = AudioSystem.getClip();
clip.open(audioInputStream);
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
public void play() {
if (volume != Volume.MUTE) {
if (clip.isRunning())
clip.stop();
clip.setFramePosition(0);
clip.start();
}
}
static void init() {
values();
}
}
Dissecting the Program [PENDING] 
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SoundEffectDemo extends JFrame {
public SoundEffectDemo() {
SoundEffect.init();
SoundEffect.volume = SoundEffect.Volume.LOW;
Container cp = this.getContentPane();
cp.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
JButton btnSound1 = new JButton("Sound 1");
btnSound1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SoundEffect.EXPLODE.play();
}
});
cp.add(btnSound1);
JButton btnSound2 = new JButton("Sound 2");
btnSound2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SoundEffect.GONG.play();
}
});
cp.add(btnSound2);
JButton btnSound3 = new JButton("Sound 3");
btnSound3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SoundEffect.SHOOT.play();
}
});
cp.add(btnSound3);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Test SoundEffct");
this.pack();
this.setVisible(true);
}
public static void main(String[] args) {
new SoundEffectDemo();
}
}
Dissecting the Program [PENDING] (optional) javax.sound.SourceDataLine A source data line acts as a source to the audio mixer. Unlike Clip (which pre-load the audio samples), an application writes audio samples to a source data line, which handles the buffering of the bytes and delivers them to the mixer, in a streaming manner. import java.io.*;
import javax.sound.sampled.*;
public class SoundLineTest {
public static void main(String[] args) {
SourceDataLine soundLine = null;
int BUFFER_SIZE = 64*1024;
try {
File soundFile = new File("gameover.wav");
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(soundFile);
AudioFormat audioFormat = audioInputStream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
soundLine = (SourceDataLine) AudioSystem.getLine(info);
soundLine.open(audioFormat);
soundLine.start();
int nBytesRead = 0;
byte[] sampledData = new byte[BUFFER_SIZE];
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(sampledData, 0, sampledData.length);
if (nBytesRead >= 0) {
soundLine.write(sampledData, 0, nBytesRead);
}
}
} catch (UnsupportedAudioFileException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (LineUnavailableException ex) {
ex.printStackTrace();
} finally {
soundLine.drain();
soundLine.close();
}
}
}
MIDI Synthesized SoundIn a computer game, MIDI can be used for providing the background music, as it save you quite a bit of bandwidth if you are downloading the file from a slow connection. Java Sound API supports three types of MIDI: MIDI Type 1, MIDI Type 2 and Rich Music Format (RMF). The steps are: - Allocate a Sequence piped from a MIDI file:
Sequence song = MidiSystem.getSequence(new File("song.mid"));
- Allocate a Sequencer to play a MIDI sequence:
Sequencer player = MidiSystem.getSequencer();
- Set the current sequence for the sequencer to play:
player.setSequence(song);
- Open the sequencer to load the sequence:
player.open();
- You could set the loop count via
setLoopCount() and start playing the music by invoking start() :player.setLoopCount(0);
player.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
player.start();
- You can set the tempo (rate of play) via
setTempoFactor() , which is useful in a computer game when the difficulty level is increased.player.setTempoFactor(1.0F);
player.setTempoFactor(1.5F);
- You can stop the play via
stop() :if (player.isRunning()) player.stop();
Code Example The method is declared static , as we only need one global copy, and no instance variable involved in the operation. import java.io.*;
import javax.sound.midi.*;
public class MidiSoundTest {
private static Sequencer midiPlayer;
public static void main(String[] args) {
startMidi("song1.mid");
try {
Thread.sleep(10000);
} catch (InterruptedException e) { }
System.out.println("faster");
midiPlayer.setTempoFactor(2.0F); try {
Thread.sleep(10000);
} catch (InterruptedException e) { }
if (!midiPlayer.isRunning()) {
midiPlayer.stop();
midiPlayer.close();
startMidi("song2.mid");
}
}
public static void startMidi(String midFilename) {
try {
File midiFile = new File(midFilename);
Sequence song = MidiSystem.getSequence(midiFile);
midiPlayer = MidiSystem.getSequencer();
midiPlayer.open();
midiPlayer.setSequence(song);
midiPlayer.setLoopCount(0);
midiPlayer.start();
} catch (MidiUnavailableException e) {
e.printStackTrace();
} catch (InvalidMidiDataException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
|
MP3 & Java Media Framework (JMF)Java Media Framework (JMF) is not part of JavaSE, but can be downloaded from http://java./javase/technologies/desktop/media/jmf. JMF, among other things, provides support for playing MP3, AAC music. Download JMF and run the installation. Check to ensure that "jmf.jar " is installed into "$JAVA_HOME\jre\lib\ext ". Example: Playing MP3 Music import javax.media.*;
import java.net.URL;
public class Mp3PlayerDemo extends Thread {
private String filename;
Player player;
public Mp3PlayerDemo(String mp3Filename) {
this.filename = mp3Filename;
}
public void run() {
try {
URL url = this.getClass().getClassLoader().getResource(filename);
MediaLocator locator = new MediaLocator(url);
player = Manager.createPlayer(locator);
player.addControllerListener(new ControllerListener() {
public void controllerUpdate(ControllerEvent event) {
if (event instanceof EndOfMediaEvent) {
player.stop();
player.close();
}
}
});
player.realize();
player.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Mp3PlayerDemo("song.mp3").start();
}
}
Notes: Windows Vista seems to have lot of problems with Midi.
|