2009-12-07 43 views
2

我正尝试将动画同步到特定BPM中的音乐。我试过使用计时器,但在处理毫秒级的小间隔时不准确。我做了一些阅读,并找到了一种替代方法,它使用一个小型无声音频文件和SOUND_COMPLETE事件作为Timer。AS3中准确的BPM事件监听器

我用这个代码使用了167ms长的声音文件。

package 
{ 
    import flash.events.Event; 
    import flash.events.EventDispatcher; 
    import flash.media.Sound; 
    import flash.media.SoundChannel; 
    import flash.net.URLRequest; 

    public class BetterTimer extends EventDispatcher 
    { 
     private var silentSound:Sound; 

     public function BetterTimer(silentSoundUrl:String):void { 
      super(); 
      silentSound = new Sound(new URLRequest(silentSoundUrl)); 
      silentSound.addEventListener(Event.COMPLETE, start); 
     } 
     public function start():void { 
      this.timerFired(new Event("start")); 
     } 
     private function timerFired(e:Event):void { 
      dispatchEvent(new Event("fire")); 
      var channel:SoundChannel = silentSound.play(); 
      channel.addEventListener(Event.SOUND_COMPLETE, timerFired, false, 0, true); 
     } 
    } 
} 

这仍然没有停留在节拍上。 Flash Player的声音是否准确?

回答

2

这是非常棘手的得到正确的!有一个名为BeatTimer的小库试图做到这一点。我自己并没有试过这个代码,但是如果它确实声称它应该正是你所需要的。

+0

我刚刚给了BeatTimer一试。这是写在一个特定的BPM季度节拍踢事件。我测试了它的八分之一和十六分之一,它在我的2分钟循环期间保持准确。我也想尝试Joa的解决方案,但为了我的目的,这个BeatTimer运作良好。谢谢。 – knuckfubuck 2009-12-08 07:17:55

1

设置帧速率以使事件间隔为帧速率的倍数可能会有所帮助(例如,167ms等于6 fps; 12,18,24等也可以)。

如果我理解正确,更好的解决方案是使用enterframe事件。不是通过计算事件来确定动画的位置,而是使用经过的时间(getTimer或声音位置)来计算它。这也会使动画在滞后的较慢计算机上工作。

5

您还可以将新的Sound API与SampleDataEvent一起使用,并使用Sound.extract()手动播放MP3。在这种情况下,您可以预先知道延迟时间,甚至可以在您的(延迟)事件发生时计数到样本。

这就是我们在AudioTool中所做的,它工作得很好。

0

我正在浏览popforge库的AudioBuffer,并尝试使用其中一种方法。这是创建同步声音。以下是我所做的。

var syncSamples:ByteArray = new ByteArray(); 
syncSamples.length = (2646000/_bpm) << 1; /*44100*60=2646000*/ 
SoundFactory.fromByteArray(syncSamples, Audio.MONO, Audio.BIT16, Audio.RATE44100, soundInit); 

ms延迟非常接近,例如:在120 BPM时,它在509-512ms之间。问题是,我正朝着正确的方向前进吗?