Home Journal Building an accurate Timekeeper in AS3: III

Building an accurate Timekeeper in AS3: III

by John

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.

You may also like

49 comments

Tedbot July 30, 02008 - 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 😉

Reply
John July 30, 02008 - 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.

Reply
makc November 10, 02008 - 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.

Reply
John November 10, 02008 - 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.

Reply
Arthur Mingard January 19, 02009 - 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.

Reply
John January 19, 02009 - 1:38 pm

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

Reply
Aneurin Barker Snook February 25, 02009 - 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.

Reply
John February 25, 02009 - 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

Reply
Futurefabric March 6, 02009 - 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.

Reply
John March 6, 02009 - 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!

Reply
Futurefabric March 9, 02009 - 11:13 pm

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

Thanks again,
Guy

Reply
Alastair April 15, 02009 - 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.

Reply
John April 15, 02009 - 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 🙂

Reply
Bart May 7, 02009 - 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?

Reply
John May 9, 02009 - 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 🙂

Reply
Aneurin Barker Snook May 24, 02009 - 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

Reply
AS3 Timekeeper — Aneurin "Anny" Barker Snook August 23, 02009 - 12:39 pm

[…] 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, […]

Reply
Aneurin Barker Snook August 23, 02009 - 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!

Reply
explorer September 13, 02010 - 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?

Reply
John September 13, 02010 - 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.

Reply
chris September 23, 02010 - 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

Reply
John September 29, 02010 - 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

Reply
chris September 30, 02010 - 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

Reply
Aneurin Barker Snook October 27, 02010 - 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 :—)

Reply
Blog – Airside » Blog Archive » Block Clock November 17, 02010 - 4:18 pm

[…] 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 […]

Reply
Gx February 10, 02011 - 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.

Reply
John February 10, 02011 - 10:17 pm

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

Reply
munkychop January 6, 02012 - 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 😀

Reply
John January 6, 02012 - 10:25 pm

Glad it was helpful 🙂

Reply
Artem Aminov May 21, 02012 - 4:10 pm

Thanks! Assist to my countup timer )

Reply
daniel August 28, 02012 - 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!

Reply
John August 28, 02012 - 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.

Reply
Andy October 8, 02012 - 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.

Reply
Andy October 8, 02012 - 6:57 am

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

Reply
John October 8, 02012 - 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.

Reply
ShadyAck October 12, 02012 - 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.

Reply
John October 12, 02012 - 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.

Reply
A A Mon February 19, 02014 - 5:33 am

Hi John, can I use your Timekeeper class to make a stopwatch with minutes:seconds:tenths of second with 10 fps?

Reply
John February 26, 02014 - 8:01 pm

@AAMon Yes you can, but remember that if the movie is set to 10fps then that’s the minimum resolution you can track.

Reply
A A Mon March 2, 02014 - 5:11 am

Hi John, Thank you for your reply. At first, I thought 10 fps would be enough because I would like to have accuracy to deciseconds. But after I found an article about actual frame rates (http://www.kaourantin.net/2006/05/frame-rates-in-flash-player.html), I increased my fps to 20. What do you think about that?

Tom February 28, 02013 - 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!

Reply
John February 28, 02013 - 12:43 am

Hi Tom, I hope it works for you. 🙂

Reply
Andy Whiteley August 30, 02013 - 5:48 pm

I’m using the Timekeeper as an alternative to the inaccurate AS3 Timer class. At the moment I can stop and start the timer although it restarts from where it would have been if I didn’t press stop. How do I reset to zero and restart from zero?

Reply
John August 30, 02013 - 6:20 pm

Hi Andy, you can set the value of the timer to anything you like using setValue( ms:Number ):void. So to set it to zero just call setValue(0) on your Timekeeper instance.

Reply
Andy Whiteley August 31, 02013 - 11:35 pm

Thanks. I was using setValue() already. After looking at the trace output it turned out that I was using getTimer(); to get the current time value instead of myTimekeeper.getValue();

Reply
Andy Whiteley September 11, 02013 - 2:35 am

How would I get tenths of a second while keeping the timekeeper seconds accurate? I’m developing an app for the iPhone and I’ve tried setting the tickDuration and tickFrequency to 100, but as you mentioned it isn’t as accurate as 1000.

Reply
John September 11, 02013 - 9:07 am

The Timekeeper class is a trade-off that favours accuracy over speed. It’s the best we can achieve using this technique, and within the constraints of the Flash Player. If you’re working with AIR you could try building an AIR Extension to tap into the native clock?

Reply
andytwoodsAndy March 7, 02014 - 7:24 am

I’ve a silly question. Why not have a while loop that continually looks at system time. When X milliseconds has elapsed, emit an event?

Quite the waste in system resource this I guess, but it could be sent to a worker?

Reply
John March 28, 02014 - 10:09 pm

Flash has a frame based structure so we work with that. You have a few more options in JavaScript but we’re at the mercy of many underlying levels of abstraction.

Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.