I am currently developing a game.
I would like to implement some sound samples. (MIDI Sequences)
I was wondering if any of you have some experience with that and can point me to
some good resources to learn from. Google only comes up with long tutorials and I just cant
believe implementing sound is that hard in Java. Especially when you know how easy it is to
program GUI and all.
Page 1 of 1
Java Sound
#2
Posted 27 March 2006 - 05:09 AM
heres some code for making a simple audio player.... i'm sure you can slice up what you need.
// you will need to use javax.sound.sampled.SourceDataLine
// and javax.sound.sampled.TargetDataLine to read and write to audio buffers
// for sample code see http://www.jsresources.org/examples/audio_misc.html
// http://javaalmanac.com/egs/javax.sound.sampled/StreamAudio.html
// http://207.150.176.83/archive/index.php?t-54523.html
//package je3.sound;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.sound.sampled.*;
/**
* This class is a Swing component that can load and play a sound clip,
* displaying progress and controls. The main( ) method is a test program.
* This component can play sampled audio or MIDI files, but handles them
* differently. For sampled audio, time is reported in microseconds, tracked in
* milliseconds and displayed in seconds and tenths of seconds. For midi
* files time is reported, tracked, and displayed in MIDI "ticks".
* This program does no transcoding, so it can only play sound files that use
* the PCM encoding.
*/
public class AudioPlayer extends JComponent
{
Clip clip; // Contents of a sampled audio file
boolean playing = false; // whether the sound is currently playing
// Length and position of the sound are measured in milliseconds for
// sampled sounds and MIDI "ticks" for MIDI sounds
int audioLength; // Length of the sound.
int audioPosition = 0; // Current position within the sound
// The following fields are for the GUI
JButton play; // The Play/Stop button
JSlider progress; // Shows and sets current position in sound
JLabel time; // Displays audioPosition as a number
Timer timer; // Updates slider every 100 milliseconds
// The main method just creates a AudioPlayer in a Frame and displays it
public static void main(String[ ] args)
throws IOException,
UnsupportedAudioFileException,
LineUnavailableException
{
AudioPlayer player;
File file = new File("test.wav");//args[0]); // This is the file we'll be playing
// Determine whether it is midi or sampled audio
// Create a AudioPlayer object to play the sound.
player = new AudioPlayer(file);
// Put it in a window and play it
JFrame f = new JFrame("AudioPlayer");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane( ).add(player, "Center");
f.pack( );
f.setVisible(true);
}
// Create a AudioPlayer component for the specified file.
public AudioPlayer(File f)
throws IOException,
UnsupportedAudioFileException,
LineUnavailableException
{
// Getting a Clip object for a file of sampled audio data is kind
// of cumbersome. The following lines do what we need.
AudioInputStream ain = AudioSystem.getAudioInputStream(f);
try {
DataLine.Info info =
new DataLine.Info(Clip.class,ain.getFormat( ));
clip = (Clip) AudioSystem.getLine(info);
clip.open(ain);
}
finally { // We're done with the input stream.
ain.close( );
}
// Get the clip length in microseconds and convert to milliseconds
audioLength = (int)(clip.getMicrosecondLength( )/1000);
// Now create the basic GUI
play = new JButton("Play"); // Play/stop button
progress = new JSlider(0, audioLength, 0); // Shows position in sound
time = new JLabel("0"); // Shows position as a #
// When clicked, start or stop playing the sound
play.addActionListener(new ActionListener( ) {
public void actionPerformed(ActionEvent e)
{
if (playing) stop( );
else play( );
}
});
// Whenever the slider value changes, first update the time label.
// Next, if we're not already at the new position, skip to it.
progress.addChangeListener(new ChangeListener( ) {
public void stateChanged(ChangeEvent e)
{
int value = progress.getValue( );
time.setText(value/1000 + "." + (value%1000)/100); // Update the time label
if (value != audioPosition) skip(value); // If we're not already there, skip there.
}
});
// This timer calls the tick( ) method 10 times a second to keep
// our slider in sync with the music.
timer = new javax.swing.Timer(100, new ActionListener( )
{
public void actionPerformed(ActionEvent e) { tick( ); }
});
// put those controls in a row
Box row = Box.createHorizontalBox( );
row.add(play);
row.add(progress);
row.add(time);
// And add them to this component.
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
this.add(row);
// Now add additional controls based on the type of the sound
addSampledControls( );
}
// Start playing the sound at the current position
public void play( )
{
clip.start( );
timer.start( );
play.setText("Stop");
playing = true;
}
// Stop playing the sound, but retain the current position
public void stop( )
{
timer.stop( );
clip.stop( );
play.setText("Play");
playing = false;
}
// Stop playing the sound and reset the position to 0
public void reset( )
{
stop( );
clip.setMicrosecondPosition(0);
audioPosition = 0;
progress.setValue(0);
}
// Skip to the specified position
public void skip(int position) // Called when user drags the slider
{
if (position < 0 || position > audioLength) return;
audioPosition = position;
clip.setMicrosecondPosition(position * 1000);
progress.setValue(position); // in case skip( ) is called from outside
}
// Return the length of the sound in ms or ticks
public int getLength( ) { return audioLength; }
// An internal method that updates the progress bar.
// The Timer object calls it 10 times a second.
// If the sound has finished, it resets to the beginning
void tick( )
{
if (clip.isActive( ))
{
audioPosition = (int)(clip.getMicrosecondPosition( )/1000);
progress.setValue(audioPosition);
}
else reset( );
}
// For sampled sounds, add sliders to control volume and balance
void addSampledControls( )
{
try {
FloatControl gainControl =
(FloatControl)clip.getControl(FloatControl.Type.MASTER_GAIN);
if (gainControl != null) this.add(createSlider(gainControl));
}
catch(IllegalArgumentException e) {
// If MASTER_GAIN volume control is unsupported, just skip it
}
try {
// FloatControl.Type.BALANCE is probably the correct control to
// use here, but it doesn't work for me, so I use PAN instead.
FloatControl panControl =
(FloatControl)clip.getControl(FloatControl.Type.PAN);
if (panControl != null) this.add(createSlider(panControl));
}
catch(IllegalArgumentException e) { }
}
// Return a JSlider component to manipulate the supplied FloatControl
// for sampled audio.
JSlider createSlider(final FloatControl c)
{
if (c == null) return null;
final JSlider s = new JSlider(0, 1000);
final float min = c.getMinimum( );
final float max = c.getMaximum( );
final float width = max-min;
float fval = c.getValue( );
s.setValue((int) ((fval-min)/width * 1000));
java.util.Hashtable labels = new java.util.Hashtable(3);
labels.put(new Integer(0), new JLabel(c.getMinLabel( )));
labels.put(new Integer(500), new JLabel(c.getMidLabel( )));
labels.put(new Integer(1000), new JLabel(c.getMaxLabel( )));
s.setLabelTable(labels);
s.setPaintLabels(true);
s.setBorder(new TitledBorder(c.getType( ).toString( ) + " " +
c.getUnits( )));
s.addChangeListener(new ChangeListener( ) {
public void stateChanged(ChangeEvent e)
{
int i = s.getValue( );
float f = min + (i*width/1000.0f);
c.setValue(f);
}
});
return s;
}
}
#3 Guest_Smartin_*
Posted 27 March 2006 - 02:01 PM
Yes, I found it a lot more difficult to find something about sound in Java than about graphics.
Here's another smaller example. It is very basic though. You can do stuff like changing the tempo and things later.
Here's another smaller example. It is very basic though. You can do stuff like changing the tempo and things later.
import java.io.File;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
String file = "C:/Java/MyGame/Sound/Music.mid";
void play()
throws Exception {
//preparations
Sequencer sequencer = MidiSystem.getSequencer();
sequencer.open();
Sequence seq = MidiSystem.getSequence(new File(file));
sequencer.setSequence(seq);
//start
sequencer.start();
//wait until finished
while (sequencer.isRunning()) {
Thread.sleep(1000); }
//close
sequencer.stop();
sequencer.close();
}
This post has been edited by Smartin: 27 March 2006 - 02:03 PM
#5
Posted 28 March 2006 - 12:08 AM
Yeah i'd go with code Smartin provided, as you probably wont have much need for some of the things in the one i put up.
As we're on this topic, anyone got any info on implementing a text-to-speech synthesizer in java? I've got to make one for a uni class and if anyone knows of any good resources that'd be cool.
As we're on this topic, anyone got any info on implementing a text-to-speech synthesizer in java? I've got to make one for a uni class and if anyone knows of any good resources that'd be cool.
#6 Guest_PhatCat_*
Posted 18 April 2006 - 06:17 PM
First of all, thanks for the replies, they were to say the least, very helpful.
This is my code right now :
Is it correct to assume that when the method 'play' of this class is called it will play the midi file once and sleep the thread while doing it ?
So all I need to do is call this call somewhere in my main program and the song will play once?
This is my code right now :
import java.lang.Thread;
import java.io.File;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
public class SoundManager {
public void play () throws Exception {
//preparations
Sequencer sequencer = MidiSystem.getSequencer ();
sequencer.open ();
Sequence seq = MidiSystem.getSequence (
(new File (new File ("prog","sounds"), "Battle.mid"))
);
sequencer.setSequence (seq);
//start
sequencer.start();
//wait until finished
while (sequencer.isRunning ())
Thread.sleep (1000);
//close
sequencer.stop ();
sequencer.close ();
}
}Is it correct to assume that when the method 'play' of this class is called it will play the midi file once and sleep the thread while doing it ?
So all I need to do is call this call somewhere in my main program and the song will play once?
This post has been edited by PhatCat: 18 April 2006 - 06:19 PM
Page 1 of 1

Sign In
Register
Help
MultiQuote
