| Home > Core Java FAQ
> Miscellaneous FAQ |
| Miscellaneous |
| java.lang
& java.util Package(08) * Sound(14)
* Jar (06) |
| |
|
Q . How do I play sounds in an applet?
|
Ans :
Invoke one
of Applet's getAudio
methods to get an AudioClip object,
then invoke start and stop on that object.
The
java.applet package provides bare-bones support for
playing sounds. Using the Applet and AudioClip
classes, you can load sound files over the network, start them
playing, and stop them in midstream. Using audio well in an applet
is challenging, and requires that you understand the details of
the different audio-related methods. The following discussion
includes implementation details, especially concerning threads,
that hold in the JDK 1.0.2 and 1.1.
Applet's getAudioClip
method is synchronous: it fetches data for the audio clip and
returns when the data is fully loaded and ready to play. (This is
the opposite of Component's getImage
method, which returns immediately without loading its data) After
a call to getAudioClip, invoking play on the AudioClip
object should should start the sound immediately:
/* code in an applet ... */
String filename = ...
AudioClip currentSound = getAudioClip(getCodeBase(), "gong.au");
currentSound.play();
AudioClip
objects are usually cached, so that subsequent calls to getAudioClip
for the same clip do not incur the delay of fetching the data over
the net.
AudioClip's play method
is asynchronous: it issues a request to another thread to play the
sound, and it returns almost immediately. In other words, it does
not wait for the sound to actually start playing, let alone finish
playing. Unfortunately, the current JDK implementations, 1.0.2 and
1.1, do not provide any direct way for your program to find out
when an audio clip has finished playing.
AudioClip's stop method
is also asynchronous, but its effects are pretty much immediate,
so you can think of it as stopping the sound as soon you invoke
it. Invoking start on an audio clip that is already playing first
stops the clip and then starts it again from the beginning.
For the simplest uses, the Applet
class also provides convenience methods, play(URL)
and play(URL, String), which combine the work of
fetching and starting an audio clip. Applet's play(...)
methods are functionally equivalent to getAudioClip(...).play().
|
|
Q .
How do I play several audio clips simultaneously?
|
Ans
:
You can
play several audio clips almost simultaneously by creating
distinct AudioClip objects and then starting them all
at roughly the same time.
AudioClip's
start method works asynchronously: it sends a request to another
thread, which manages the actual playing of sounds through the
native platform's audio device. Because start returns almost
immediately, you can start several different audio clips almost
simultaneously simply by preloading the clips and then invoking
start on them in sequence:
/* ... in an applet ... */
AudioClip clip1 = getAudioClip(getCodeBase(), "bass.au");
AudioClip clip2 = getAudioClip(getCodeBase(), "guitar.au");
AudioClip clip3 = getAudioClip(getCodeBase(), "drums.au");
clip1.play();
clip2.play();
clip3.play();
|
|
Q . Can I tell when an audio clip has finished playing?
|
Ans
:
No—the
best you can do for now is estimate when the audio clip will
finish; the current audio API (JDK 1.0.2 and 1.1) does not provide
any notification when an audio clip finishes playing.
The
audio support in the JDK 1.0.2 and 1.1 is quite limited, and one
glaring gap is that there is no way to notify your program when an
audio clip has finished playing. If you have actions whose timing
depends on when a clip finishes, you have to estimate the timing
yourself.
As an example, consider the problem
of playing two sound clips in succession. If you know in advance
the length of the first audio clip, you can predict when to start
the second one, as follows:
/* ... in an applet ... */
AudioClip firstClip = getAudioClip(...);
AudioClip secondClip = getAudioClip(...);
long playLength = ...; // length of firstClip in milliseconds
// (somehow we know this from elsewhere)
firstClip.play();
try {
Thread.sleep(playLength);
secondClip.play();
} catch (InterruptedException e) {
// ... handle exception
}
The
forthcoming Java Media Framework will provide a much richer
foundation for controlling the capture and playback of media
streams (audio and video). Notification of playback completion is
one of the planned capabilities.
|
|
Q . How can I play audio in a stand-alone application?
|
Ans
:
Stand-alone
applications can't yet play audio in a cross-platform manner; the
current API (JDK 1.0.2 and 1.1) requires the support of a browser
or other applet context.
In
the current JDK releases (1.0.2 and 1.1), the java.applet package
contains the only cross-platform Java support for playing audio.
However, this functionality is ultimately backed up by the
applet's execution context—either the Applet Viewer or a
Java-enabled browser. For example, when you invoke the getAudioClip
method on an Applet instance, the call gets forwarded
to an AppletContext object:
/* in Applet.java (JDK 1.0.2 and 1.1): */
public AudioClip getAudioClip(URL url) {
return getAppletContext().getAudioClip(url);
}
AppletContext
is an interface; the applet's execution context has the role of
providing an actual object from a class that implements this
interface. If you merely define an Applet subclass
and place instances of it in your application, you haven't
actually provided your applets with the proper context to support
audio.
The upcoming work on the Java Media
Framework will provide a much richer set of cross-platform
capabilities for both applets and applications.
|
|
Q . What audio formats does the JDK support besides Sun's .au format?
|
Ans
:
No other
ones; the JDK 1.0.2 (and 1.1) supports only the .au
format.
The current
releases of the JDK (1.0.2 and 1.1) support only the .au audio
file format:
- 8 bits per
sample
- 8000 samples per
second (8000 Hz)
- one channel
(mono)
- mu-law encoding
of amplitude (nonlinear, quasi-logarithmic)
This
format represents sound with approximately telephone-voice
quality. It is commonly used to compress the dynamic range of a
16-bit linear format into half as many bits.
Sound files in other formats can be
converted to the .au format with varying degrees of
difficulty. The easiest is NeXT's .snd format, which
is practically identical to the .au format. If you
have a NeXT .snd file, you can simply rename it from XXX.snd
to XXX.au and it should work. The two formats differ
slightly in their sampling rate—8000 samples per second (.au)
versus 8012 samples per second (.snd)—but this 0.15
percent difference should be negligible for many uses.
Sound files in other audio formats
require more work to convert to the .au format. The
best-known tool for this is the free SoX program; for
further information, see http://www.spies.com/Sox/.
|
|
Q . Is there a method for generating sounds of a given frequency, something along the lines of playTone(int frequency, int duration)?
|
Ans :
No; the
current JDK (1.0.2 and 1.1) does not provide any methods for sound
generation.
The
audio capabilities provided by the JDK (1.0.2 and 1.1) have
focused on basic support for applet audio. You can load and play
audio files specified by URLs, but there is no way to generate
sounds directly from within your program. The JavaMedia APIs and
implementation under development at JavaSoft will provide
stunningly improved sound capabilities in upcoming releases.
|
|
Q . How do I play a sound in an application?
|
Ans
:
Java's audio support comes from the AppletContext class and the AudioClip interface. Since applications don't have applet contexts, they have no easy way to play audio clips. This is supposed to be fixed in Java 1.2. In the meantime you have to use undocumented classes in the sun packages. The following example demonstrates:
import sun.audio.*;
import java.awt.*;
import java.io.*;
public class SoundPlayer extends Frame implements FilenameFilter {
Button openButton = new Button("Open");
Button playButton = new Button("Play");
Button loopButton = new Button("Loop");
Button stopButton = new Button("Stop");
Label filename = new Label(" ");
File theFile = null;
AudioData theData = null;
InputStream nowPlaying = null;
public SoundPlayer() {
super("Sound Player");
resize(300, 200);
Panel north = new Panel();
north.setLayout(new FlowLayout(FlowLayout.LEFT));
north.add(new Label("File: "));
north.add("North", filename);
add("North", north);
Panel south = new Panel();
south.add(openButton);
south.add(playButton);
south.add(loopButton);
south.add(stopButton);
add("South", south);
}
public static void main(String[] args) {
SoundPlayer sp = new
SoundPlayer();
sp.show();
}
public void open() {
FileDialog fd = new FileDialog(this, "Please select a .au file:");
fd.setFilenameFilter(this);
fd.show();
try {
theFile = new File(fd.getDirectory() + "/" + fd.getFile());
if (theFile != null) {
filename.setText(theFile.getName());
FileInputStream fis = new FileInputStream(theFile);
AudioStream as = new AudioStream(fis);
theData = as.getData();
}
}
catch (IOException e) {
System.err.println(e);
}
}
public void play() {
stop();
if (theData == null) open();
if (theData != null) {
AudioDataStream ads = new AudioDataStream(theData);
AudioPlayer.player.start(ads);
nowPlaying = ads;
}
}
public void stop() {
if (nowPlaying != null) {
AudioPlayer.player.stop(nowPlaying);
nowPlaying = null;
}
}
public void loop() {
stop();
if (theData == null) open();
if (theData != null) {
ContinuousAudioDataStream cads = new ContinuousAudioDataStream(theData);
AudioPlayer.player.start(cads);
nowPlaying = cads;
}
}
public boolean action(Event e, Object what) {
if (e.target == playButton) {
play();
return true;
}
else if (e.target == openButton) {
open();
return true;
}
else if (e.target == loopButton) {
loop();
return true;
}
else if (e.target == stopButton) {
stop();
return true;
}
return false;
}
public boolean accept(File dir, String name) {
name = name.toLowerCase();
if (name.endsWith(".au")) return true;
if (name.endsWith(".wav")) return true;
return false;
}
}
This example is taken from Chapter 10 of Java Secrets, available from
amazon
and various independent bookstores. It's published by IDG Books, ISBN number 0-764-58007-8. Chapters 8-17 cover various of the sun packages including sun.audio. (Chapters 1-7 cover the internals of Java like byte code and class files. Chapter 19 and 20 cover platform dependent Java including native methods.)
|
|
Q . Why won't my audio clip play?
|
Ans
:
It's probably in the wrong format. Java 1.1 and earlier only understand 8 bit, mulaw-encoded, 8000 Hz, one-channel files. Many sound conversion programs will convert various formats to .au files but not necessarily to 8 bit, mulaw-encoded, 8000 Hz, one-channel files.
|
|
Q . Why won't my audio file play?
|
Ans
:
Java 1.1 and earlier releases use one audio format exclusively. The
audio file must be in .au format, recorded at 8 KHz, mono, in mu-law
encoding. If your audio clip is in a different format (e.g., .wav) or a
different frequency it must be converted to the exact specifications above before Java can play it. Support for .wav and other formats is
part of the Java Media Framework coming in JDK 1.2. Search at http://www.yahoo.com for GoldWave for Win 95, sox for Unix
and similar conversion utilities for other systems. Other sites:
o One conversion utility in Java is at http://saturn.math.uaa.alaska.edu/~hursha
o The source of a Java class to play linear PCM .WAV files is at: http://www.shef.ac.uk/~cs1mjp/Java/WhiteBoard/WavePlayer.html
. It can be used in any Java application or applet.
|
|
Q . How can I do video streaming using Java?
|
Ans
:
That is the purpose of
StreamBean. See http://www.streambean.com/streambean/
|
|
Q .
How do I play video in Java?
|
Ans
:
Use the Java Media Framework Player API.
Other sites:
o The Java Media Framework Player API spec can be found at http://java.sun.com/products/java-media/jmf/
o Intel has released a SDK for the Java Media Framework Player API.
The SDK is for Windows 95 and Windows NT. For more information, see http://developer.intel.com/ial/jmedia
o SGI has released an implementation of JMF for IRIX: See http://www.sgi.com/Products/motion/
|
|
Q .
How can I play *.au files from an application?
|
Ans
:
A new static method was introduced in JDK1.2 in the class Applet:
public final static AudioClip newAudioClip(URL url) {
The method turns a URL (pointing to an audio file) into an AudioClip. Since the method is static it can be used without any objects of class
Applet needing to exist, e.g. in an application. Once you have an
AudioClip, you can play it with:
MyAudioClip.play();
The Java Media Framework provides a richer API for playing sounds in an application.
For code prior to JDK 1.2, you can use the AudioClip or AudioPlayer class in sun.audio
http://www.javaworld.com/javaworld/javatips/jw-javatip24.html. If you do this your code is no longer 100% pure Java, as it relies on a vendor
library.
import sun.audio.*;
URL url; ...
AudioStream audiostream = new AudioStream(url.openStream());
AudioPlayer.player.start(audiostream);
...
AudioPlayer.player.stop(audiostream);
Also in the FAQ:
Use the new Java Media Framework API, allowing a wide range of video and audio formats to be played back. See previous question.
|
|
Q . How can I record sound in an applet?
|
Ans
:
If you are using win95/nt, you could use SoundBite - Audio
Recording in Applets. See http://www.scrawl.com/store/
It provides easy access to audio data in arrays: short[] left, right;
|
|
Q .
How can I edit sound files?
|
Ans
:
The JaWavedit java code lets you edit .wav and .au files. It can be
found at http://www.bome.com/JaWavedit/
. It's free to use.
If you are inspired to write freeware like this yourself, many file formats are explained and described at
http://www.wotsit.org
|