【问题标题】:Syncing Frames to Audio and channel.position Accuracy将帧同步到音频和 channel.position 精度
【发布时间】:2009-05-30 15:32:04
【问题描述】:

在 ENTER_FRAME 事件上调用 channel.position,我注意到它不是每帧都更新,但它看起来更像是每帧半。

var sound:Sound = new Sound(new URLRequest('music.mp3')); 
var channel:SoundChannel = sound.play(); // assume the sound is completely,
                                         // totally, 100% loaded

addEventListener(Event.ENTER_FRAME, function(e:Event):void{
   trace(  "Position : " + channel.position 
         + " - Frame : " + int(channel.position / 30));
});

将产生类似于 (30 FPS) 的结果

   ...
   Position : 1439.6371882086166 - Frame : 47
   // 48 is missing
** Position : 1486.077097505669 -  Frame : 49
** Position : 1486.077097505669 -  Frame : 49
   Position : 1532.517006802721 -  Frame : 51
   Position : 1578.9569160997733 - Frame : 52
   // 53 is missing
** Position : 1625.3968253968253 - Frame : 54
** Position : 1625.3968253968253 - Frame : 54
   Position : 1671.8367346938776 - Frame : 55
   // 56 is missing
   Position : 1718.2766439909296 - Frame : 57
   ...

以前有没有人注意到这种行为?知道这种不准确性,是否有任何技术可以确定正在播放的音频“帧”?

【问题讨论】:

    标签: actionscript-3 actionscript synchronization audio


    【解决方案1】:

    是的,这是正常行为,因为事件是线程化的,因此只要线程具有优先级,就会调用它们的委托。打印到控制台也是线程化的,因此它也可能并不总是在正确的时间打印消息。事实上,您看到的问题可能只是打印问题。尝试提高帧率,看看会发生什么。

    不过,为了更准确,您可以尝试使用计时器类。通常,您可以使滴答声发生得比帧快得多,这意味着误差幅度会更低。不过,您正在使用该事件,因此可能会有一些偏差。

    为了弥补这一点,您可以检查时间与帧以确定偏移量。这使您可以纠正任何漂移。

    编辑:此示例直接来自 ActionScript 3 文档中的 this page,请注意他们正在使用的 positionTimer

    package {
        import flash.display.Sprite;
        import flash.events.*;
        import flash.media.Sound;
        import flash.media.SoundChannel;
        import flash.net.URLRequest;
        import flash.utils.Timer;
    
        public class SoundChannelExample extends Sprite {
            private var url:String = "MySound.mp3";
            private var soundFactory:Sound;
            private var channel:SoundChannel;
            private var positionTimer:Timer;
    
            public function SoundChannelExample() {
                var request:URLRequest = new URLRequest(url);
                soundFactory = new Sound();
                soundFactory.addEventListener(Event.COMPLETE, completeHandler);
                soundFactory.addEventListener(Event.ID3, id3Handler);
                soundFactory.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
                soundFactory.addEventListener(ProgressEvent.PROGRESS, progressHandler);
                soundFactory.load(request);
    
                channel = soundFactory.play();
                channel.addEventListener(Event.SOUND_COMPLETE, soundCompleteHandler);
    
                positionTimer = new Timer(50);
                positionTimer.addEventListener(TimerEvent.TIMER, positionTimerHandler);
                positionTimer.start();
            }
    
    
            private function positionTimerHandler(event:TimerEvent):void {
                trace("positionTimerHandler: " + channel.position.toFixed(2));
            }
    
            private function completeHandler(event:Event):void {
                trace("completeHandler: " + event);
            }
    
            private function id3Handler(event:Event):void {
                trace("id3Handler: " + event);
            }
    
            private function ioErrorHandler(event:Event):void {
                trace("ioErrorHandler: " + event);
                positionTimer.stop();       
            }
    
            private function progressHandler(event:ProgressEvent):void {
                trace("progressHandler: " + event);
            }
    
            private function soundCompleteHandler(event:Event):void {
                trace("soundCompleteHandler: " + event);
                positionTimer.stop();
            }
        }
    }
    

    【讨论】:

    • 将帧速率提升到 60 可以处理丢失的帧,但不会增加 channel.position 请求的粒度。这导致第 55 帧被报告 3 次,或 4 次被报告 56 被报告 3 次或 4 次,依此类推。
    • 这很奇怪,因为 ENTER_FRAME 事件每帧应该只触发一次。
    • 对,并不是每帧触发不止一次,而是它的 channel.position 正在以低于帧速率的速度更新。
    • 在您的示例中,将 50ms(大约 20FPS)更改为 33(30FPS)仍然会导致 positionTimerHandler 每隔几帧“加倍” - 因为 channel.position 的刷新率更快低于 50 毫秒,但低于 33 毫秒
    • 这不是最理想的答案,但它确实提供了可能对其他人有帮助的问题信息。
    猜你喜欢
    • 2012-09-06
    • 1970-01-01
    • 2014-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    • 2016-05-26
    相关资源
    最近更新 更多