0

我已经开始用 Java 制作一个基本的游戏了。

一切进展顺利,我有地图加载,绘图工作正常等。

我让它为地图播放音乐,为碰撞之类的东西播放音效。

但是我觉得 MAP A(我要离开的那个)的音乐应该淡入 MAP B(我正在进入的那个地图)的音乐中,这可能吗?

我用来播放音乐的代码如下:

    try
    {
        if(clip != null)
        {
            clip.stop();
            clip.close();
        }

        clip = AudioSystem.getClip();

        URL a = this.getClass().getResource("/resource/sound/"+Filename + ".mid");

        ais = AudioSystem.getAudioInputStream(a);

        clip.open(ais);
        clip.loop(999);
        clip.start();
    }
    catch(Exception e)
    {

    }

正如您很可能看到的那样,我在 Java 方面不是很好,但我的游戏到目前为止进展顺利,但我不是,我拒绝使用“引擎”,因为我想要完全控制。

有任何想法吗?

谢谢

编辑:

感谢所有的答案,我已经修改了你给我的代码,但它不起作用=/

我现在制作了下面的代码,它在一个新线程上运行(因此是 Runnable),因此音乐在播放时会消失。

代码如下:

private Boolean _SwapMusic = false;
private String _Filename;
Thread soundThread;

    Runnable r1 = new Runnable() {
      public void run() {
        while(true)
        {
            if(_SwapMusic)
            {
                _SwapMusic = false;
                try
                {
                    //Try to lower volume
                    for (int i = 0; i < 80; i ++) {
                        FloatControl gainControlA = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
                           gainControlA.setValue(i * -1f);
                        Thread.sleep(10);
                    }
                }
                catch(Exception e){ System.out.print("Lower volume error: " + e + " ");}


                try{
                    clip.stop();
                    clip.close();
                }
                catch (Exception e) { System.out.print("clip.stop/close error: " + e + " ");}
                try
                {
                    clip = AudioSystem.getClip();

                    URL a = this.getClass().getResource("/resource/sound/"+ _Filename + ".mid");

                    ais = AudioSystem.getAudioInputStream(a);

                    clip.open(ais);

                    FloatControl gainControlB = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
                    gainControlB.setValue(-80f);

                    clip.loop(999);
                    clip.start();
                }
                catch(Exception e){ System.out.print("Play error: " + e + " ");}


                try
                {
                    //Try to higher volume
                    for (int i = -80; i < 0; i ++) {
                        FloatControl gainControlC = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
                           gainControlC.setValue(i);
                        Thread.sleep(3);
                    }
                }
                catch(Exception e){ 
                System.out.print("Higher volume error: " + e + " ");
                }
            }         
        }
      }
    };

只是为了说明这一点,我试图让 MAP A 的音乐在 MAP B 的音乐开始之前完全消失。

感谢到目前为止的所有帮助。

4

3 回答 3

1

您可以使用MASTER_GAIN控件降低第一个剪辑的声音,同时提高第二个剪辑的声音,您可能需要调整 dB 和时序,但这应该可以:

Clip clipA = AudioSystem.getClip();
Clip clipB = AudioSystem.getClip();
clipA.open(aisA);
clipB.open(aisB);

for (int i = 0; i < 100; i ++) {
   FloatControl gainControlA = (FloatControl) clipA.getControl(FloatControl.Type.MASTER_GAIN);
   gainControlA.setValue(i * -1f);
   FloatControl gainControlB = (FloatControl) clipB.getControl(FloatControl.Type.MASTER_GAIN);
   gainControlB.setValue(-100f + i);

   Thread.sleep(100);
}
于 2012-07-18T17:14:09.070 回答
1

这并不是一个答案,而是添加一些不适合评论的可能有用的信息。

是的,-80 到 6.0 有点时髦。我认为它应该在舷外混音器上复制分贝。但到耳朵的斜率几乎不是线性的。如果我没记错的话,当你降到 -20 时,声音可能已经听不见了。在这和试图在音量变化中进行实时精度的性能问题之间,我放弃了使用控制线并开始直接处理 PCM 数据。但我不建议你在这种情况下这样做。

为了使控件的数字范围更均匀渐变,您可以映射某种指数或三角函数。我不知道最合适的,但我已经通过以下两个函数获得了有用的结果。

对于 PCM 数据,我一直在尝试将音量标准化为 0 到 1 的范围。以下是我一直在使用的一些函数示例。

newValue = 1 - Math.cos(NormalizedPCMValue * PI/2)

newValue = Math.pow(NormalizedPCMValue, 6) 

newValue = Math.pow(2, NormalizedPCMValue)

这些对我来说都比直线更好。我正在使用查找表,但您可能可以即时计算值。如果你得到一个非常好用的映射函数,我很想在这里听到它。

顺便说一句,最好将控制线值实际降低到范围的底部。突然切断声音,即使它很安静,或者在音量变化中跳跃很远的距离,都可能导致不连续性,表现为可听见的咔嗒声。

于 2012-07-19T18:21:25.410 回答
0

Ryuk,你为什么不从你要离开的级别淡出剪辑,同时开始播放下一个剪辑,调高音量。

您必须原谅我,我不能 100% 确定您使用的是什么库,但剪辑对象肯定有一个 .adjustVolume() 方法。

随着时间的推移调整音量,它看起来像:(请注意伪代码)

clip2.adjustVolume(0*time.deltaTime()+5); //Start the clip at volume 0, and increment it each frame, not second.
clip1.adjustVolume(100*time.deltaTime()-5); //Inverse, adjust volume down to fade out.
于 2012-07-18T16:38:05.820 回答