392
|
Chapter 10, Audio
#77 Show Audio Information While Playing Sound
HACK
H A C K
#77
Show Audio Information While Playing SoundHack #77
Providing visual feedback for JavaSound audio, or at least trying to….
You might want to play a clip without any corresponding visuals; for exam-
ple, if you were using it to signal the end of a long-running process such as
uploading a file. On the other hand, if the sound is the focus of the applica-
tion, as in a music-player application, you might need to show the user some
information about the audio he’s playing.
The Code
You already know how to play audio from a file or stream [Hack #76]; building
on that, you can create a simple GUI that shows some of the basic traits of
the audio, by pulling fields out of the
AudioFormat object, which can be
retrieved from the
Line once it has been created. These fields include the
audio format, bits/sample, frame size and rate, and endianness (which indi-
cates how two-byte values are to be interpreted: big-endian means the first
byte is more significant, and little-endian means the second is).
More impressively,
DataLine provides a getLevel( ) method that returns the
current level of the audio being played, as a float from
0.0 (silence) to 1.0
(maximum volume). You can use this to create a graphical level meter by
getting the level and coloring in that percentage of a component. For exam-
ple, if the level is
0.5, you’d fill in half of the component.
Drawing this level meter is pretty straightforward: create a
JPanel whose
paint( ) method clears the Graphics, gets the line level, and fills a rectangle
starting at
(0,0) with a height equal to the component’s height and a width
equal to the level times the component’s width. Then you need to set up an
animation loop—a
javax.swing.Timer is convenient because it avoids any
thread-safety issues while doing the painting—to repeatedly call
repaint( )
on the meter.
Figure 10-7. Playing a large AIFF file in JavaSound
Show Audio Information While Playing Sound #77
Chapter 10, Audio
|
393
HACK
Combine this together and you have the DataLineInfoGUI, seen in
Example 10-10. Note that to play the audio, it uses the
PCMFilePlayer class
from the previous hack, so you can use an arbitrarily long AIFF or WAV, as
long as its contents are uncompressed PCM data.
Example 10-10. Displaying audio format information
import javax.sound.sampled.*;
public class DataLineInfoGUI extends JPanel {
PCMFilePlayer player;
JButton startButton;
public DataLineInfoGUI (File f) {
super( );
try {
player = new PCMFilePlayer (f);
} catch (Exception ioe) {
add (new JLabel ("Error: " +
ioe.getMessage( )));
return;
}
DataLine line = player.getLine( );
// layout
// line 1: name
setLayout (new BoxLayout (this, BoxLayout.Y_AXIS));
add (new JLabel ("File: " +
player.getFile().getName( )));
// line 2: levels
add (new DataLineLevelMeter (line));
// line 3: format info as textarea
AudioFormat format = line.getFormat( );
JTextArea ta = new JTextArea( );
ta.setBorder (new TitledBorder ("Format"));
ta.append ("Encoding: " +
format.getEncoding().toString( ) + "\n");
ta.append ("Bits/sample: " +
format.getSampleSizeInBits( ) + "\n");
ta.append ("Endianness: " +
(format.isBigEndian( ) ? " big " : "little") + "\n");
ta.append ("Frame size: " +
format.getFrameSize( ) + "\n");
ta.append ("Frame rate: " +
format.getFrameRate( ) + "\n");
add (ta);
// now start playing
player.start( );
}
394
|
Chapter 10, Audio
#77 Show Audio Information While Playing Sound
HACK
This is a pretty straightforward implementation of the strategy sketched out
previously: the class is a
JPanel with a BoxLayout to which you can add an
arbitrary number of rows. The first is the name of the file, the second is the
level meter, and the third is a
JTextArea to which you can append various
fields pulled from the
AudioFormat.
The level meter’s constructor takes care of setting up its own repaint call-
backs, so there’s no babysitting required on the part of the caller. All that’s
left for the constructor is to start the player to begin feeding bytes to the
Line.
public static void main (String[] args) {
JFileChooser chooser = new JFileChooser( );
chooser.showOpenDialog(null);
File file = chooser.getSelectedFile( );
DataLineInfoGUI demo =
new DataLineInfoGUI (file);
JFrame f = new JFrame ("JavaSound info");
f.getContentPane( ).add (demo);
f.pack( );
f.setVisible(true);
}
class DataLineLevelMeter extends JPanel {
DataLine line;
float level = 0.0f;
public DataLineLevelMeter (DataLine l) {
line = l;
Timer timer =
new Timer (50,
new ActionListener ( ){
public void actionPerformed (ActionEvent e) {
level = line.getLevel( );
repaint( );
}
});
timer.start( );
}
public void paint (Graphics g) {
Dimension d = getSize( );
g.setColor (Color.green);
int meterWidth = (int) (level * (float) d.width);
g.fillRect (0, 0, meterWidth, d.height);
}
}
}
Example 10-10. Displaying audio format information (continued)

Get Swing Hacks now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.