问题
I'm trying to develop a game and I've found 2 sources for sound.
I posted the whole class below, it won't seem to loop even when looped_forever
or loop_times
is setup to do so:
package com.jayitinc.ponygame;
import java.io.*;
import javax.sound.sampled.*;
public class Sound
{
Thread t;
String read;
String name;
AudioInputStream stream = null;
AudioFormat format = null;
// New sound, the String it it's location relative to your project folder.
// I suggest you add a class folder in the project properties to access the
// files from there.
public Sound(String read, String name)
{
sound = new File("sound/" + read);
try
{
stream = AudioSystem.getAudioInputStream(sound);
} catch (Exception e)
{
e.printStackTrace();
}
format = stream.getFormat();
this.name = name;
}
// New sound with set volume
public Sound(String read, float volume, String name)
{
this(read, name);
setVolume(volume);
try
{
stream = AudioSystem.getAudioInputStream(sound);
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
format = stream.getFormat();
}
public void play()
{
t = new Thread(play);
// Write you own file location here and be aware that it need to be an
// .wav file
t.start();
}
// ONLY USE IF YOU HAVE STARTED THE THREAD FIRST
public void stop()
{
// stops the sound thread from playing
t.stop();
}
// Just in case you would like to change it
public void setVolume(float volume)
{
this.volume = volume;
}
File sound;
boolean muted = false; // This should explain itself
float volume = 100.0f; // This is the volume that goes from 0 to 100
float pan = 0.0f; // The balance between the speakers 0 is both sides and it
// goes from -1 to 1
boolean isPlaying;
double seconds = 0.0d; // The amount of seconds to wait before the sound
// starts playing
boolean looped_forever = false; // It will keep looping forever if this is
// true
int loop_times = 0; // Set the amount of extra times you want the sound to
// loop (you don't need to have looped_forever set to
// true)
int loops_done = 0; // When the program is running this is counting the
// times the sound has looped so it knows when to stop
// The rest of this is pretty complicated, you don't need to bother with it.
final Runnable play = new Runnable() // This Thread/Runnable is for playing
// the sound
{
public void run()
{
try
{
// Check if the audio file is a .wav file
if (sound.getName().toLowerCase().contains(".wav"))
{
if (format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED)
{
format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, format.getSampleRate(), format.getSampleSizeInBits() * 2, format.getChannels(), format.getFrameSize() * 2, format.getFrameRate(), true);
stream = AudioSystem.getAudioInputStream(format, stream);
}
SourceDataLine.Info info = new DataLine.Info(SourceDataLine.class, stream.getFormat(), (int) (stream.getFrameLength() * format.getFrameSize()));
SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
line.open(stream.getFormat());
line.start();
// Set Volume
FloatControl volume_control = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN);
volume_control.setValue((float) (Math.log(volume / 100.0f) / Math.log(10.0f) * 20.0f));
// Mute
BooleanControl mute_control = (BooleanControl) line.getControl(BooleanControl.Type.MUTE);
mute_control.setValue(muted);
FloatControl pan_control = (FloatControl) line.getControl(FloatControl.Type.PAN);
pan_control.setValue(pan);
int num_read = 0;
byte[] buf = new byte[line.getBufferSize()];
while ((num_read = stream.read(buf, 0, buf.length)) >= 0)
{
int offset = 0;
while (offset < num_read)
{
offset += line.write(buf, offset, num_read - offset);
}
}
line.drain();
line.stop();
if (looped_forever)
{
new Thread(play).start();
} else if (loops_done < loop_times)
{
loops_done++;
new Thread(play).start();
}
}
} catch (Exception ex)
{
ex.printStackTrace();
}
}
};
public int getLength()
{
long audioFileLength = sound.length();
int frameSize = format.getFrameSize();
float frameRate = format.getFrameRate();
float durationInSeconds = (audioFileLength / (frameSize * frameRate));
return (int) durationInSeconds;
}
public void setPan(float pan)
{
this.pan = pan;
}
public float getPan()
{
return pan;
}
public void setLoop(boolean loop)
{
looped_forever = loop;
}
public boolean getLoop()
{
return looped_forever;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
Edit: I need to be able to control volume so if you have another class please make sure it can control volume!
回答1:
(re
Clip
) ..how do you control volume?
Try this variant of the code seen on the Java Sound tag Wiki.
import java.net.URL;
import javax.sound.sampled.*;
import javax.swing.*;
import javax.swing.event.*;
public class VolumeControl {
public static void main(String[] args) throws Exception {
URL url = new URL(
"http://pscode.org/media/leftright.wav");
Clip clip = AudioSystem.getClip();
// getAudioInputStream() also accepts a File or InputStream
AudioInputStream ais = AudioSystem.
getAudioInputStream( url );
clip.open(ais);
Control[] c = clip.getControls();
FloatControl temp = null;
for (Control control : c) {
System.out.println(control);
if (control.toString().toLowerCase().contains("master gain")) {
// we found it!
temp = (FloatControl)control;
}
}
final FloatControl vol = temp;
clip.loop(Clip.LOOP_CONTINUOUSLY);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JComponent c = null;
if (vol!=null) {
final JSlider volControl = new JSlider(
(int)(100*vol.getMinimum()),
(int)(100*vol.getMaximum()),
(int)(100*vol.getValue())
);
ChangeListener cl = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
System.out.println( "Vol: " + volControl.getValue()/100f );
vol.setValue(volControl.getValue()/100f);
}
};
volControl.addChangeListener(cl);
c = volControl;
} else {
c = new JLabel("Close to exit!");
}
JOptionPane.showMessageDialog(null, c);
}
});
}
}
来源:https://stackoverflow.com/questions/14510981/java-sound-class-not-looping