我一次播放多个音频时遇到问题

时间:2020-10-19 07:42:44

标签: java audio

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);
    }
}

**所以我在游戏中播放很多音频,但我认为这是一个问题,但是如果我在相同的六十分之一秒内播放两个音频,则会弹出错误并冻结游戏半秒钟

  1. 我可以以某种方式确定剪辑何时开始播放,以便可以停止下一个剪辑 (我想查看剪辑何时开始播放,而不是何时播放) (但这对我来说也很有趣)

  2. 是否有比此更好的播放音频的方式

1 个答案:

答案 0 :(得分:0)

剪辑没有设计成可以同时打开和启动。在从磁盘加载整个文件之前,它们甚至都不会开始播放。我猜如果您尝试同时使用显示的代码同时播放两个,则文件加载滞后问题将会加剧。

您可以(并且应该)做的是事先初始化Clips,包括将其打开并将其保存在内存中,以备使用。是时候播放它们了,您应该只执行以下操作:

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

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

但是,如果您不想耗尽存储音频的内存,请使用SourceDataLine进行播放。在SourceDataLine开始播放之前,仅从磁盘加载了一个缓冲区的数据(而不是等待整个文件加载)。

这两种文件类型都不适合同时播放(一次播放两次或多次),但是如果正确执行上述操作,声音应该会很好。如果仍然存在问题,或者您对MASTER_GAIN行的笨拙不满意,可以尝试使用几个简单的库。一个称为TinySound,另一个称为AudioCue。我偏爱后者(因为我写了它),它确实处理并发回放,并且比Clip具有更细粒度的实时音量控制。

这是一个非常普遍的问题,很多原因是关于音频的Java教程很难阅读,因此人们会错过这些重要的细节。我猜想许多其他志愿教程的作者在强调最佳实践方面做得不好,只满足于播放声音而已。

编辑:重新阅读您的问题-有一个名为LineListener的类可以接收有关Clip何时开始或停止的通知,如果您想进一步追求这一方面。

此外,如果您收到实际的错误消息,请发布它们!这将有助于确定原因和解决方案。