我有一个问题,关于同时播放多个音频。

huangapple go评论117阅读模式
英文:

I Have A Problem With Playing Multiple Audios At Once

问题

package me.Warrior;
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.FloatControl;

public class SoundPlayer {
    static URL path = null;
    static AudioInputStream inputStream;
    public static Clip clip;

    public static synchronized void Play(final String url, float Volume) {
        new Thread(new Runnable() {
            public void run() {
                try {
                    clip = AudioSystem.getClip();
                    URL resource = getClass().getClassLoader().getResource(url);
                    path = resource;
                    inputStream = AudioSystem.getAudioInputStream(path);
                    clip.open(inputStream);
                    setVolume(Volume, clip);
                    clip.start();
                } catch (Exception e) {
                }
            }
        }).start();
    }

    public static void setVolume(float Volume, Clip clip) {
        FloatControl gainControl =
                (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
        float dB = (float) (Math.log(Volume) / Math.log(10) * 20);
        gainControl.setValue(dB);
    }
}

这是你提供的代码的翻译部分。如果你有关于这段代码的问题或需要进一步的帮助,请随时提问。

英文:
package me.Warrior;
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.FloatControl;
public class SoundPlayer {
	static URL path=null;
	static AudioInputStream inputStream; 
	public static Clip clip;
	public static synchronized void Play(final String url,float Volume) { 
		  new Thread(new Runnable() {
			public void run() {
		      try {
		    	  clip = AudioSystem.getClip();
		    	  URL resource = getClass().getClassLoader().getResource(url);
				path=resource;
		        inputStream = AudioSystem.getAudioInputStream(path);
				clip.open(inputStream);
				setVolume(Volume,clip);
		        clip.start();
		      } catch (Exception e) {
		      }
		    }
		  }).start();
		}

	public static void setVolume(float Volume,Clip clip) {
		 FloatControl gainControl = 
		    	    (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
		 float dB=(float)(Math.log(Volume)/Math.log(10)*20);
		    	gainControl.setValue(dB);
	}
}

**So i play lots of audios in my Game and i think there is a problem whereas if i play two audios at the same sixtieth of a second it pops an Error and Freezes the Game for half a second

  1. Can i somehow determine when the clip starts playing, so i can stop the next clip
    (I want to see when the clip starts Playing, not When it is Playing)
    (But that would be interesting for me as well)

  2. Is there any better way to Play Audio than this

答案1

得分: 0

以下是您要翻译的内容:

剪辑并不是设计用来同时打开和启动的。甚至在整个文件从磁盘加载完毕之前,它们都不会开始播放。我猜想,如果您尝试在几乎同一时间播放两个剪辑,使用您展示的代码,文件加载的延迟问题将会叠加。

您可以(也应该)事先初始化您的剪辑,包括打开它们,并将它们保存在内存中,随时准备播放。当需要播放它们时,您只需要执行以下操作:

public void playMyAudioFX() {
    myAudioFX.setFramePosition(0);
    myAudioFX.start();
}

通过将帧位置设置为起始位置,您可以重复使用Clip,而不必一遍又一遍地加载它。

但是,如果您不想占用内存来保存音频,可以使用SourceDataLine进行播放。在SourceDataLine开始播放之前,只会从磁盘加载一个缓冲区的数据(而不是等待整个文件加载)。

这两种文件类型都不适合并发播放(同时播放两次或更多次),但是如果您按照上述方法进行操作,声音应该会正常开始。如果仍然存在问题,或者如果您对“MASTER_GAIN”线的表现不满意,有几个简单的库可以尝试。一个叫做TinySound,另一个是AudioCue。我比较偏爱后者(因为我写了它),它可以处理并发播放,并且在音量方面具有比Clip更精细的实时控制。

这是一个非常常见的问题,很大程度上是因为Java关于音频的教程很难阅读,所以人们会忽略这些重要细节。我猜测,许多其他志愿者编写的教程在强调最佳实践方面做得不够好,只满足于让声音播放,然后就这样了。

编辑:重新阅读您的问题 - 如果您遇到实际的错误消息,请将它们发布出来!这将有助于确定原因和解决方案。

英文:

Clips were NOT designed to be opened and started at the same time. They won't even start playing until the entire file is loaded from disk. I'm guessing if you try to play two at virtually the same time with the code you are showing, the file-loading lag issues will compound.

What you can (and should) do instead is to initialize your Clips beforehand, including opening them, and hold them in memory, ready to go. When it is time to play them, you should only execute the following:

public void playMyAudioFX() {
    myAudioFX.setFramePosition(0);
    myAudioFX.start();
}

By setting the frame position to the start, you can re-use the Clip without having to load it over and over.

But if you don't want to use up your memory holding audio, then use SourceDataLine for playback. Only one buffer's worth of data is loaded from disk before the SourceDataLine starts playing (as opposed to waiting for the entire file to load).

Neither of these file types works well with concurrent playback (playing it twice or more at the same time), but if you do the above correctly, the sounds should start off fine. If there are still problems, or if you are unhappy with how clunky the MASTER_GAIN line is, there are a couple simple libraries to try. One is called TinySound, the other AudioCue. I'm partial to the latter (since I wrote it) and it does handle concurrent playback and has much finer-grained real-time control for volume than Clip.

This is a really common issue, and a lot of the reason is that the Java tutorials on audio are difficult to read, so people miss these important details. I guess many other volunteer tutorial writers don't do a good job of emphasizing best practices, are content to just get a sound playing and leave it at that.

EDIT: rereading your question--There is a class called a LineListener that can receive notifications as to when a Clip starts or stops if you want to pursue that aspect further.

Also, if you are getting actual error messages, please post them! That will help with determining causes and solutions.

huangapple
  • 本文由 发表于 2020年10月19日 15:42:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/64423063.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定