Using Timekeeper class The example above ..." /> Using Timekeeper class The example above ..." />

Building an accurate Timekeeper in AS3: III

Posted on March 6, 02008
Filed Under Development, Flash, Harrison

Download
Download the source files

Using Timekeeper class

The example above shows the Timekeeper class in action. You'll notice that the temporal drift is always being corrected and generally stays accurate to within 0.1 seconds. I only need accuracy to within one second for my clock so this should be fine. The two more common techniques are shown below again for comparison.

Using movie frame rate

Using AS3 Timer class

The Timekeeper works by using a very fast internal regulator to update a much slower 'user clock'. Periodic accuracy (isochronism) is achieved by maintaining an accumulator based on the system clock. When the value of the accumulator becomes greater than the tick frequency then a user tick event is produced. Abstracting the timekeeping functions from the periodic mechanism allowed me to add some cool features to the Timekeeper class:

getValue():Number
setValue( ms:Number ):void

Get and set the value of time in milliseconds since the Unix epoch. Notice the datatype is Number rather than a Date. This is for reasons of speed, capacity and interoperability with other timekeeping systems. I'll cover this design decision in more detail in a future entry. Conversion to Date is really simple though. If the value of the Timekeeper is ms then you can turn it into a Date like so: var d = new Date(ms)

getTickDuration():Number
setTickDuration( ms:Number ):void
Tick duration is the value in milliseconds that that gets added to the value of the timekeeper every time there is a tick event. The default is one second (e.g. one second per second). Changing the tick duration to one day would run the timekeeper much faster than real time (e.g. one day per second). Changing the tick duration to a negative number will run the timekeeper backwards. Fractional values of a second will work but are not recommended.

getTickFrequency():int
setTickFrequency( ms:int ):void

Tick frequency is the length of time between ticks. The default is one second (e.g. one second per second). Changing the tick frequency to two seconds would run the timekeeper at half real time (e.g. one second per two seconds). The datatype for tick frequency is int rather than Number as all values must be positive and large durations between ticks are impractical.

stopTicking():void
startTicking():void
It is often handy to be able to stop or pause the timekeeper. Tick events are ignored when the Timekeeper is stopped.

setRealTimeValue():void
setRealTimeTick():void
Two functions added for convenience. setRealTimeValue() sets the value of the Timekeeper to "now". setRealTimeTick() sets the running speed to "real time", i.e. one second per second.

Related Journal Entries

Comments

Leave a Comment

If you would like to make a comment, please fill out the form below.

Name (required)

Email (required)

Website

Comments

39 Comments so far
  1. Tedbot July 30, 2008 5:27 pm

    Thanks so much for this– great work. You should mention that the accuracy of the Timekeeper is dependent on the frequency of the regulator, which defaults to 50ms. I haven’t tried changing the regulator but found out quickly that things get crazy when you try to keep time below it ;)

  2. John July 30, 2008 11:17 pm

    Hiya Todbot. You’re right about the regulator – that’s the tradeoff really. The class offers accuracy at the expense of granularity. Glad you found it useful though.

  3. makc November 10, 2008 3:51 pm

    Hey there, my own tests show that timer events cannot be generated more often than 10 times per frame; maybe the drift is a “round-off” error steaming from there. Any way, increasing SWF frame rate should improve timer accuracy, and allow corrections for intervals lower than 50 ms as well.

  4. John November 10, 2008 7:29 pm

    Hiya Makc, My guess is the drift is just a side effect of processing spikes. Flash doesn’t try and ‘catch up’ it just moves onto the next frame and does it’s best.

    My solution is a trade off. You lose resolution (only 10 ticks per second) but you know those ticks will be consistent and on time. It works great for what I need (i.e. real time) but wouldn’t be much use in say, a game engine where number of ticks per second is probably more useful.

  5. Arthur Mingard January 19, 2009 1:29 pm

    Just wanted to say thank you for this tutorial. I have been designing a drum sound sequencer for my final year production and was having a hard time using the timer function in flash. Now my timing is almost perfect although when multiple sounds play at once there can be a delay but that’s always going to be the case.

  6. John January 19, 2009 1:38 pm

    Hi Arthur, Glad you found it helpful. Would love to see a link to the sequencer when you’re done. :)

  7. Aneurin Barker Snook February 25, 2009 12:10 am

    Hi John,

    I’ve been collaborating with Arthur Mingard above on his project and as part of development I rewrote the Timekeeper class to better suit our requirements. As my interpretation is mostly based on yours it seems only polite to let you know about my developments!

    I’ve written about it at {URL removed at authors request. See later post for latest URLs} if you’d care to read up on my changes. It may lack some of the flexible features of your Timekeeper but I believe that in imitating a Timer class it may be a little more accessible to less confident developers.

  8. John February 25, 2009 10:58 am

    Hi Aneurin, glad the code was helpful.

    Appreciate the link-back – it’s always nice to see something you’ve written being used in projects you’ve never considered! Cheers, jd

  9. Futurefabric March 6, 2009 4:04 pm

    I’ve been planning to build some sort of clock in AS3 for a while and have come against the pitfall of Timer’s inaccuracy.

    Cheers for your work on this – a massive help and an excellent workaround to the problem.

  10. John March 6, 2009 5:49 pm

    Cheers Guy, nice to hear from you (I’m a long time Airside/Lemon Jelly fan :) )

    Glad the Timekeeper is working out for you – post me link if you build anything cool!

  11. Futurefabric March 9, 2009 11:13 pm

    Will be sure to let you know and link to you John if I create anything of note.

    Thanks again,
    Guy

  12. Alastair April 15, 2009 10:01 pm

    Good stuff. I built a generative sequencer in AS3 last year and has similar fun trying to build the core sequencer clock. Like Aneurin, I wanted a tracker-style system with Beats Per Minute, Beats Per Bar and Ticks Per Beat.

    I solved the timing drift issues in the end by avoiding the Timer and ENTER_FRAME solutions altogether.

    The Flash engine places pretty much all processing on a single thread using a timesharing system. Look up Ted Patrick’s “elastic racetrack” article for a clearer description of what I’m referring to.

    As makc pointed out, Timer events just get lumped into the first section of each frame processing segment so aren’t really any better or more granular than enter frame.

    However, the sound playback engine is managed on a separate thread. Consequently, SOUND_COMPLETE events can be a good way to keep time independently. Create a blank MP3 file and mathematically determine how much of it you need to play back to cover the duration of a tick, then just play back this section of the sound. You’ll get a pretty accurate SOUND_COMPLETE event at the end of the required time frame.

    This can then be built into a clock with similar internal regulation functions to those you mention.

    Happy to send you some code if you’d like an example of what I’m talking about.

  13. John April 15, 2009 11:33 pm

    Hiya Alistair, yeah I’d love to see some code. That sounds really cool! I’ve heard of the blank audio track technique being used in video to ensure steady streaming, but I hadn’t considered it as timekeeper before – great idea :)

  14. Bart May 7, 2009 9:32 pm

    I am trying to make a tape ticker, but the inaccurate Timer / EnterFrame give a flickering effect, not so nice.

    I like the idea of using the sound engine as time generator, have you tried it yet?

  15. John May 9, 2009 11:16 pm

    Hiya Bart. No not yet, but I did manage to catch up with Alastair on Friday for a pint or two. Lots to talk about :)

  16. Aneurin Barker Snook May 24, 2009 12:15 am

    Hi again,

    Just wanted to let you – and those clicking through, of whom it seems there are quite a few! – know that my AS3 Timekeeper thing has moved to a new address in an upgrade to WordPress from my previous bespoke blog.

    http://aneuri.net/2009/02/as3-timekeeper/

    Regards,
    Aneurin

  17. [...] is something I coded six months ago and need to rehost. This Timekeeper class, based on John Dalziel’s Timekeeper, imitates an ordinary Timer, giving you an accurate relative clock with a very regular, [...]

  18. Aneurin Barker Snook August 23, 2009 12:48 pm

    Hi again John,

    Migrated to a new server and name, my version of the AS3 Timekeeper is now at http://anny.fm/2009/08/as3-timekeeper/

    Sorry about comment spamming!

  19. explorer September 13, 2010 6:07 am

    Hey. This looks to be exactly what I need, but the Duration and Frequency settings kind of confuse me. So lets say I want an event to occur every 50 milliseconds, so I should set both parameters to 50?

  20. John September 13, 2010 8:48 am

    Unfortunately the tradeoff for accuracy is speed, so 50 ms sounds a bit fast. You might want to try using audio as a syncing system. If you read Alistair’s comments you’ll find some details.

  21. chris September 23, 2010 10:31 pm

    Hi,
    I’m somewhat new to classes, but I have a project I want to use this in and it’s the best I’ve found so far. All I really want to do is import a “clock” into my fla. I’m able to trace the clock/timer values, but how do you instantiate this? I can import the main class and create a var and add it, but am having trouble getting the actual clock to work – or display text in my textField. Sorry if this is stupid question, but I really want to start working with this. Any help is appreciated.

    Thanks – Chris

  22. John September 29, 2010 9:42 am

    Sorry for the delay Chris, I’m still down at FOTB right now. The easiest way to think about the Timekeeper class is as a beefed up version of the Timer function. In your FLA add some code to make an instance of the class. Something like:
    var myTimekeeper:Timekeeper = new Timekeeper();

    Then you can call functions to start and stop the timer. Add a listener to listen for tick events and update your clock display in the listener function. Not sure if that is straight forward to understand. Will try and see if i can post a good example explaining how to use it! thx jd

  23. chris September 30, 2010 11:12 pm

    Thank you John. I appreciate you getting back to me. I’ll give this a shot now. Thanks again for your hard work. – Chris

  24. Aneurin Barker Snook October 27, 2010 5:29 pm

    For those still clicking through this article to my version of this Timekeeper, I no longer maintain a blog and previous links that I have posted are now all invalid.

    You can download the raw .as files from these links:

    http://anny.fm/c/flash-as3/fm/anny/utils/Timekeeper.as
    http://anny.fm/c/flash-as3/fm/anny/utils/TimekeeperEvent.as

    John: maybe worth deleting/hiding my previous comments? I get a surprising amount of traffic from this post and I’d like to direct people to the right place so they don’t have to email me :—)

  25. [...] Shizzle Block Clock makes use of two excellent open source libraries for Flash — John Dalziel’s Computus Engine for accurate timekeeping and the Box2D physics [...]

  26. Gx February 10, 2011 4:53 pm

    Hi,

    I really like what I am seeing. Sorry if this is a stupid question. How is the overal performance affected by this? im building a flash movie that I want to run on desktop pc’s and phones.

  27. John February 10, 2011 10:17 pm

    It’s a single timer running, if you keep the tick rate to reasonable level you’ll have no problems.

  28. munkychop January 6, 2012 6:29 pm

    wow, nearly 4 years on and this is still an extremely useful post!

    Thank you so much for this, I can now remove an mp3 SOUND_COMPLETE hack from my project :D

  29. John January 6, 2012 10:25 pm

    Glad it was helpful :)

  30. Artem Aminov May 21, 2012 4:10 pm

    Thanks! Assist to my countup timer )

  31. daniel August 28, 2012 3:23 pm

    nice work!
    Is it possible to count 100 times/second to make
    counter like this:
    http://www.parorrey.com/blog/flash-development/as3-flash-counter-using-the-timer-class-and-formatting-time-in-minutes/

    thank you!

  32. John August 28, 2012 6:51 pm

    You can set the tick frequency (the length of time between ticks) to 100 ticks per second by calling setTickFrequency(10). That said, the Timekeeper class is specifically engineered for accuracy over speed. It may not prove reliable at that speed.

  33. Andy October 8, 2012 6:42 am

    Hi there. Have you come across ‘TrueTimer’?:
    http://www.ericd.net/2009/07/as3-truetimer-from-gritfish.html

    I’m using it at the mo. Seems to implement it’s solution in the same way you do.

    Yours more accurate? Cheers,
    Andy.

  34. Andy October 8, 2012 6:57 am

    just checked and TrueTimer does not use the Timer class! Betting it’s a lot more processor intensive than yours.

  35. John October 8, 2012 8:35 am

    Hi Andy, it looks like we’re both trying to solve the same problem. The main difference I think is that they’re use case is games where mine is clocks. Checking every frame is a good solution though as that’s the lowest granularity you can have, but I’d be worried about instantiating a Date object every time – that could become a bit of a memory hog. getTimer() has a little less friction.

  36. ShadyAck October 12, 2012 2:31 am

    Has anyone made a stopwatch using this timekeeper class? I have failed in my attempts and was hoping someone could share how they got it to work. Thank you.

  37. John October 12, 2012 10:09 am

    @ShadyAck The TimekeeperEvent returns a value in milliseconds. You could start the stopwatch by caching the initial value then every time it ticks subtract the new value from the start value to give you the progress (in ms). That should work.

  38. Tom February 28, 2013 12:30 am

    Thank you for this, I am working on an Android app which requires keeping an accurate BPM, so this will hopefully help out in the process!

  39. John February 28, 2013 12:43 am

    Hi Tom, I hope it works for you. :)