Java 同时播放多个 Clips
Posted
技术标签:
【中文标题】Java 同时播放多个 Clips【英文标题】:Java play multiple Clips simultaneously 【发布时间】:2014-01-18 23:14:26 【问题描述】:所以我的应用程序应该在我每次点击面板时播放 WAV 文件。但现在的问题是,它要等待第一个完成,然后再播放第二个。我希望能够让它们同时播放。
我放 Thread.sleep(500) 的原因是因为如果我不放,那么它根本不会播放声音:(
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.Audiosystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JFrame;
@SuppressWarnings("serial")
public class SoundEffectPlayer extends JFrame
/*
* Jframe stuff
*/
public SoundEffectPlayer()
this.setSize(400, 400);
this.setTitle("Mouse Clicker");
this.addMouseListener(new Clicker());
this.setVisible(true);
private class Clicker extends MouseAdapter
public void mouseClicked(MouseEvent e)
try
playSound(1);
catch (InterruptedException e1)
// TODO Auto-generated catch block
e1.printStackTrace();
/*
* Directory of your sound files
* format is WAV
*/
private static final String DIRECTORY = "file:///C:/Users/Jessica/Desktop/audio/effects/sound 1.wav";
/*
* The volume for sound effects
*/
public static float soundEffectsVolume = 0.00f;
/*
* Loads the sound effect files from cache
* into the soundEffects array.
*/
public void playSound(int ID) throws InterruptedException
try
System.out.println("playing");
Clip clip;
URL url = new URL(DIRECTORY);
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.setFramePosition(0);
FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
gainControl.setValue(soundEffectsVolume);
clip.start();
System.out.println("played");
Thread.sleep(3000);
System.out.println("closing");
catch (MalformedURLException e)
System.out.println("Sound effect not found: "+ID);
e.printStackTrace();
return;
catch (UnsupportedAudioFileException e)
System.out.println("Unsupported format for sound: "+ID);
return;
catch (LineUnavailableException e)
e.printStackTrace();
return;
catch (IOException e)
e.printStackTrace();
return;
public static void main(String[] args) throws InterruptedException
new SoundEffectPlayer();
更新:好的,所以我让它们同时播放,但我想在 Clip 播放完毕后关闭线程,而不是让线程等待 500 毫秒
我该怎么做?
【问题讨论】:
看起来您正在事件调度线程上播放音频,这基本上会冻结应用程序,直到音频完成。是这样吗?您可能想创建一个新线程来播放音频。你知道怎么做吗? How do I play two sounds at once?的可能重复 不,我是线程新手:c 我看到你是intending to ignore me。请注意,可以双向.. 对不起,安德鲁,我的帖子冒犯了你,我没有回复,因为帖子被锁定了,我意识到这里不允许人们回答这个问题:| 【参考方案1】:我总是像这样运行多个声音。我没有产生新线程,因为我猜 javaSound 已经在另一个线程中运行剪辑。主要的“游戏循环”可能会继续做自己的事情。应用可以注册回调监听器或使用 getter 来查看剪辑在做什么。
有时,如果我们要让多媒体或游戏应用程序更容易使用 getter。运行 gameloop 30-60fps 为大多数情况提供了足够的粒度,我们可以完全控制发生的事情和时间。这个小测试应用程序播放两个 wav 文件,第一个运行一次,第二个在 3 秒后启动,第二个循环。
// java -cp ./classes SoundTest1 clip1=sound1.wav clip2=sound2.wav
import java.util.*;
import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;
public class SoundTest1
public Clip play(String filename, boolean autostart, float gain) throws Exception
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File(filename));
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.setFramePosition(0);
// values have min/max values, for now don't check for outOfBounds values
FloatControl gainControl = (FloatControl)clip.getControl(FloatControl.Type.MASTER_GAIN);
gainControl.setValue(gain);
if(autostart) clip.start();
return clip;
public static void main(String[] args) throws Exception
Map<String,String> params = parseParams(args);
SoundTest1 test1 = new SoundTest1();
Clip clip1 = test1.play(params.get("clip1"), true, -5.0f);
Clip clip2 = test1.play(params.get("clip2"), false, 5.0f);
final long duration=Long.MAX_VALUE;
final int interval=500;
float clip2IncGain=0.4f;
for(long ts=0; ts<duration; ts+=interval)
System.out.println(String.format("clip1=%d/%d(%.2f), clip2=%d/%d(%.2f)"
,clip1.getFramePosition(), clip1.getFrameLength()
,((FloatControl)clip1.getControl(FloatControl.Type.MASTER_GAIN)).getValue()
,clip2.getFramePosition(), clip2.getFrameLength()
,((FloatControl)clip2.getControl(FloatControl.Type.MASTER_GAIN)).getValue()
));
if (ts>6000 && !clip2.isRunning())
clip2.setFramePosition(0);
clip2.start();
if (!clip1.isRunning())
clip1.close();
if(ts % 2000 == 0)
// values have min/max values, for now don't check for outOfBounds values
FloatControl gainControl = (FloatControl)clip2.getControl(FloatControl.Type.MASTER_GAIN);
float oldVal=gainControl.getValue();
clip2IncGain = oldVal>=5.5 ? clip2IncGain*-1
: oldVal<=-5.5 ? clip2IncGain*-1
: clip2IncGain;
gainControl.setValue(oldVal+clip2IncGain);
Thread.sleep(interval);
private static Map<String,String> parseParams(String[] args)
Map<String,String> params = new HashMap<String,String>();
for(String arg : args)
int delim = arg.indexOf('=');
if (delim<0) params.put("", arg.trim());
else if (delim==0) params.put("", arg.substring(1).trim());
else params.put(arg.substring(0, delim).trim(), arg.substring(delim+1).trim() );
return params;
更多信息请参见JavaSound documentation。
【讨论】:
真的很好,但请您强调一下核心,好吗?所以更容易理解需要什么。 @user7185318 你的意思是添加一个关于发生了什么的 cmets 吗?我不确定这是否会增加真正的价值,因为这个测试应用程序真的已经很简单了。我也不知道JavaSound系统的内部细节。 是否需要所有这些代码?也许只需要同时播放两个声音文件。 @user7185318 是的,这就是您所需要的,实际上,如果您删除命令行参数,那就更少了。 : 一定不是 Clip clip=(Clip)AudioSystem.getLine(new DataLine.Info(Clip.class,audioInputStream.getFormat()));【参考方案2】:尝试查看这个开源音板程序的源代码:DBoard。
您对使用MediaPlayer 类特别感兴趣。您可以使用
调用它(new Thread(new MediaPlayer(PATHTOFILE)).start();
【讨论】:
以上是关于Java 同时播放多个 Clips的主要内容,如果未能解决你的问题,请参考以下文章
Java:使用 AudioClips 或 Clips 一次播放 multibleSounds