将音乐淡入新的轨道?

时间:2012-07-18 16:20:11

标签: java audio javasound

我已经开始用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 B的音乐开始之前,为了清楚说明我试图让MAP A音乐完全消失。

到目前为止,感谢您的帮助。

3 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分: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)

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

顺便说一句,最好将控制线值降低到范围的底部。突然切断声音,即使它很安静,或者在音量变化时跳跃很远的距离也会导致声音点击的不连续性。

答案 2 :(得分: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.