Metronome app with clock set to 250ms is running at 190 BPM instead of 240 BPM

1,103 views
Skip to first unread message

Greg Marsh

unread,
Jun 11, 2014, 1:08:14 PM6/11/14
to mitappinv...@googlegroups.com
I'm trying to do a metronome app where the person can enter beats per minute (BPM). When testing at 240 BPM, or 4 beats per second, a clock was set with TimerInterval of 250 ms. The metronome ran approximately 190 BPM instead of 240 BPM. The code logic is shown below. Does anyone have suggestions on getting a metronome to run at the set speed? 

using 1 clock and a counter variable
in the clock.timer event:

counter = counter + 1
if counter = 1
then play sound 1
elseif counter = 2
then play sound 2
elseif counter = 3
then play sound 3
       set counter = 0

Taifun

unread,
Jun 11, 2014, 1:21:23 PM6/11/14
to mitappinv...@googlegroups.com
if you need it exactly, you will not be able to do it

Working with the Timer I find that the TimerInterval is from the time you exit the .Timer procedure until it restarts, ie if TimerInterval is 1000ms (1 second) and it takes 45ms for the phone to do your blocks the total time between any one block will be 1045ms.

Remember that your App is not the only thing running on the phone. If it's time for your Timer to go off and the phone is busy doing something else, your event will be delayed until the phone can get to it. This is shown by downloading TimerCheck to your phone and with .TimerAlwaysFires set to True start a second program and then come back to TimerCheck and you will see delays in the timestamps.

Taifun

Trying to push the limits of App Inventor! Snippets and Tutorials from Pura Vida Apps by Taifun.         

Scott Ferguson

unread,
Jun 11, 2014, 2:44:46 PM6/11/14
to mitappinv...@googlegroups.com
You may be able to do it by checking against the system clock as I did in > this < project. If more than *316 ms has elapsed since the clock last fired you can subtract the difference from 316ms to keep the beats approximately on track. Test it with a connected device, not the emulator which is just too slow to keep up.
Your app would use 316 rather than 100 for 190 bpm.

*316ms/beat = 60000ms/min x 1min/190beats 
---
Scott

Abraham Getzler

unread,
Jun 11, 2014, 2:47:20 PM6/11/14
to mitappinv...@googlegroups.com
Here's an alternative approach, off the top of my head ...

Run a very fast clock, much faster than your metronome,
say 100 ms.


Convert your BPM to MillisecondsPerBeat, and keep it in a global.

Keep a global Instant called LastBeat, initially Now().

At every fast clock tick, see if the Duration between the new NOW()
and LastBeat in milliseconds exceeds MillisecondsPerBeat.
  If so, emit a tick sound and set LastBeat to Now()
  Otherwise do nothing until the next fast clock beat.

The slowness of the processing of each step should not
accumulate, unless it's all too low to do in a single cycle
of your fast clock.

ABG


Abraham Getzler

unread,
Jun 11, 2014, 2:55:52 PM6/11/14
to mitappinv...@googlegroups.com
P.S.
 I keep Scott's AI2 Developer's Library at the top of my head.
ABG

Abraham Getzler

unread,
Jun 11, 2014, 4:23:50 PM6/11/14
to mitappinv...@googlegroups.com
Here's another idea, with better long term correction than my prior idea ...

Keep track of when your metronome started at its current rate.
Use a fast clock (50 ms, say)
Keep track of how many times you've beat time since the start,
a simple counter.

At each fast clock cycle, compare how many times you've beat time
against how many times you should have beat time, based on the
Duration between Now() and your metronome's start Instant,
and your desired BPM.
(Insert math here.)

If you're low, beat time and up your counter.
Otherwise do nothing.

This should long-term self-correct.

ABG


Greg Marsh

unread,
Jun 12, 2014, 10:51:28 AM6/12/14
to mitappinv...@googlegroups.com
Thanks for the help. Issue seems fixed by adding another timer that see how long the cycle actually takes, and then correcting the TimerInterval by 1/2 the difference. Need more optimization, but the metronome is accurate within a beat or two.

Scott Ferguson

unread,
Jun 16, 2014, 6:40:46 PM6/16/14
to mitappinv...@googlegroups.com
Great!
---
Scott

Greg Marsh

unread,
Jul 21, 2014, 1:05:59 PM7/21/14
to mitappinv...@googlegroups.com
Just updating the final solution: Got it working, have a timer set for 30ms, in the timer have empty do until clock duration timer start - now < beat interval * beat count, and after that have the play the metronome sound. No drift off time. Tested it for minutes at various beats intervals (Beats per minute).

Branden Smale

unread,
Jan 22, 2015, 11:12:22 PM1/22/15
to mitappinv...@googlegroups.com
Can you provide a screenshot how you did this. I have a 10 min timer im trying to get right and i think this would help. Thx.

Enis

unread,
Jan 24, 2015, 12:17:15 AM1/24/15
to
Branden... what's the problem?  A 10 minute timer interval should be set at 600000 (six hundred thousand).  1000 (1 sec) x 60 (secs in a minute) x 10 (# of mins you want!).
____________________________________________________________________

http://twodogapps.com?page_id=686

For my App Inventor Tips, visit TwoDogApps.com by clicking here!


Reply all
Reply to author
Forward
0 new messages