使用 javax.sound.sampled.Clip 在游戏中播放、循环和停止多个声音。意外错误
Posted
技术标签:
【中文标题】使用 javax.sound.sampled.Clip 在游戏中播放、循环和停止多个声音。意外错误【英文标题】:Using javax.sound.sampled.Clip to play, loop, and stop multiple sounds in a game. Unexpected Errors 【发布时间】:2012-08-08 18:42:34 【问题描述】:我试图在游戏中同时播放两种 wav 声音(背景音乐和效果)。我首先使用 java 中的另一个音频处理程序构建了这段代码,该处理程序将处理声音的播放、停止和循环。这个结构会播放背景音乐或效果,但一次只能播放一个。我环顾互联网,并被告知使用 javax.sound.sampled.Clip 来处理声音,因此重用了相同的构造(播放、停止、循环),但将其切换为使用 javax.sound.sampled.Clip。现在我完全迷路了。从我到目前为止所读的内容来看,我已经完成了所有正确的操作,并且在 Eclipse 编辑器中没有出现任何错误,但是当我运行它时,我得到了两个错误之一。在 Eclipse(在 Linux 上运行)中抛出了 LineUnavailableException。在 Eclipse(在 Windows 7 上运行)中,我在此代码的 loop() 部分中获得了 java.lang.NullPointerException。如果您能告诉我我做错了什么或指向我一些相关文档,我将不胜感激。我假设它与我的处理异常的代码有关,但我不确定。如果您发现任何其他可怕的代码错误,请告诉我,我正在努力成为我能做到的最好的程序员,并且非常感谢建设性的批评。感谢您的宝贵时间。
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.Audiosystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
* Handles play, pause, and looping of sounds for the game.
* @author Tyler Thomas
*
*/
public class Sound
private Clip myClip;
public Sound(String fileName)
try
File file = new File(fileName);
if (file.exists())
Clip myClip = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.getAudioInputStream(file.toURI().toURL());
myClip.open(ais);
else
throw new RuntimeException("Sound: file not found: " + fileName);
catch (MalformedURLException e)
throw new RuntimeException("Sound: Malformed URL: " + e);
catch (UnsupportedAudioFileException e)
throw new RuntimeException("Sound: Unsupported Audio File: " + e);
catch (IOException e)
throw new RuntimeException("Sound: Input/Output Error: " + e);
catch (LineUnavailableException e)
throw new RuntimeException("Sound: Line Unavailable: " + e);
public void play()
myClip.setFramePosition(0); // Must always rewind!
myClip.loop(0);
myClip.start();
public void loop()
myClip.loop(Clip.LOOP_CONTINUOUSLY);
public void stop()
myClip.stop();
【问题讨论】:
【参考方案1】:我能够让代码正常工作,现在对 Clips 有了更好的理解。对我帮助最大的页面是http://www3.ntu.edu.sg/home/ehchua/programming/java/J8c_PlayingSound.html,它分解了所有内容并帮助我了解了我犯错的地方。这是我的最终工作代码。和以前一样,如果您在逻辑或风格上发现任何可怕的错误或过失,请告诉我。
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
* Handles playing, stoping, and looping of sounds for the game.
* @author Tyler Thomas
*
*/
public class Sound
private Clip clip;
public Sound(String fileName)
// specify the sound to play
// (assuming the sound can be played by the audio system)
// from a wave File
try
File file = new File(fileName);
if (file.exists())
AudioInputStream sound = AudioSystem.getAudioInputStream(file);
// load the sound into memory (a Clip)
clip = AudioSystem.getClip();
clip.open(sound);
else
throw new RuntimeException("Sound: file not found: " + fileName);
catch (MalformedURLException e)
e.printStackTrace();
throw new RuntimeException("Sound: Malformed URL: " + e);
catch (UnsupportedAudioFileException e)
e.printStackTrace();
throw new RuntimeException("Sound: Unsupported Audio File: " + e);
catch (IOException e)
e.printStackTrace();
throw new RuntimeException("Sound: Input/Output Error: " + e);
catch (LineUnavailableException e)
e.printStackTrace();
throw new RuntimeException("Sound: Line Unavailable Exception Error: " + e);
// play, stop, loop the sound clip
public void play()
clip.setFramePosition(0); // Must always rewind!
clip.start();
public void loop()
clip.loop(Clip.LOOP_CONTINUOUSLY);
public void stop()
clip.stop();
【讨论】:
您能否详细解释一下该链接,以防万一它出现故障?【参考方案2】:我发现了一种有用的技术来阻止声音。您可以将这两个类复制下来并自己进行测试。尽管如此,clip.stop() 方法更像是一种暂停方法。它会停止播放声音,是的,但它不会清除线路中的声音。结果,声音仍在排队播放,无法播放新声音。因此,使用 clip.close() 方法将清除此排队数据并允许播放新声音或执行其他操作。另请注意,在以下代码中,声音文件被放置在名为“predator.wav”的项目文件夹中,此声音可以是您想要使用的任何类型的声音,而不是我选择的声音,但请确保它是 .wav 格式并且声音必须位于项目文件夹的最顶层。
/*
* File: KeyMap.java
* Author: Andrew Peturis Chaselyn Langley; UAB EE Students
* Assignment: SoundBox - EE333 Fall 2015
* Vers: 1.0.0 10/20/2015 agp - initial coding
*
* Credits: Dr. Green, UAB EE Engineering Professor
*/
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class KeyMap
private char keyCode;
private String song;
private Clip clip;
// Don't allow default constructor
private KeyMap()
public KeyMap(char keyCode, String song) throws LineUnavailableException
this.keyCode = keyCode;
this.song = song;
// Create an audiostream from the inputstream
clip = AudioSystem.getClip();
public boolean match(char key)
return key == keyCode;
// Play a sound using javax.sound and Clip interface
public String play()
try
// Open a sound file stored in the project folder
clip.open(AudioSystem.getAudioInputStream(new File(song + ".wav")));
// Play the audio clip with the audioplayer class
clip.start();
// Create a sleep time of 2 seconds to prevent any action from occuring for the first
// 2 seconds of the sound playing
Thread.sleep(2000);
catch (LineUnavailableException | UnsupportedAudioFileException | IOException | InterruptedException e)
System.out.println("Things did not go well");
System.exit(-1);
return song;
// Stop a sound from playing and clear out the line to play another sound if need be.
public void stop()
// clip.stop() will only pause the sound and still leave the sound in the line
// waiting to be continued. It does not actually clear the line so a new action could be performed.
clip.stop();
// clip.close(); will clear out the line and allow a new sound to play. clip.flush() was not
// used because it can only flush out a line of data already performed.
clip.close();
/*
* File: SoundBox.java
* Author: Andrew Peturis, Chaselyn Langley; UAB EE Students
* Assignment: GUI SoundBox - EE333 Fall 2015
* Vers: 1.0.0 09/08/2015 agp - initial coding
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
import javax.sound.sampled.LineUnavailableException;
/**
*
* @author Andrew Peturis, Chaselyn Langley
*
*/
public class SoundBox
static Scanner scanner = new Scanner(System.in); //Scanner object to read user input
InputStream input;
/**
* @param args the command line arguments
* @throws java.io.IOException
*/
public static void main(String[] args) throws IOException, LineUnavailableException
String line;
Character firstChar;
String predator = "predator";
String explosion = "explosion";
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
KeyMap[] keyedSongs =
new KeyMap('a', predator),;
while (true)
line = br.readLine();
firstChar = line.charAt(0);
for (int i = 0; i < keyedSongs.length; i++)
if (keyedSongs[i].match(firstChar))
// Notice now by running the code, after the first second of sleep time the sound can
// and another sound can be played in its place
keyedSongs[i].stop();
System.out.println("Played the sound: " + keyedSongs[i].play());
break;
if (firstChar == 'q')
break;
【讨论】:
以上是关于使用 javax.sound.sampled.Clip 在游戏中播放、循环和停止多个声音。意外错误的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)