1

I'd like to write an Android application (a game, to be exact), that needs to perform certain actions at specified time. The precision of those updates should be not lower than 1ms. Is that possible?

I've tried running a thread and measure the time between updates using the System.nanoTime(). In result, there are hundreds of times when the time between updates was equal or longer than 1ms.

Can I somehow achieve a precision which would assure me that there's at least one loop executed per each 1ms?

Here's the code I've used for my test:

public class MyThread extends Thread
{
    private boolean running = false;
    public void setRunning(boolean running)
    {
        this.running = running;
    }

    public MyThread()
    {
        this.setPriority(MAX_PRIORITY);
    }

    @Override
    public void run()
    {
        long currentTimeNano = 0;
        long lastFrameTimeNano = 0;
        long nanoFrameDelay = 0;
        int longDelays = 0; //Number of delays >= 1ms

        while(running)
        {
            currentTimeNano = System.nanoTime();

            //Measure delay between updates in ns
            nanoFrameDelay = currentTimeNano - lastFrameTimeNano;

            if(nanoFrameDelay >= 1000000)
                longDelays++;

            lastFrameTimeNano = currentTimeNano;
        }
    }
}

Thank you in advance!

  • 2
    it is quite unusual to need that much update. Could you give more background ? – njzk2 Oct 08 '13 at 15:10
  • 2
    Why would you need to update at least every millisecond? That would mean having a framerate of over 1000 FPS, most games are in the 30-120 range. – npace Oct 08 '13 at 15:12
  • I want to sync the application's behavior with music. For example, I want to do something when the music's current playtime is equal to 571ms, then 823ms, then 6531ms, etc. – Grzegorz Brose Oct 08 '13 at 15:16
  • It's NOT FPS. I don't want to render a frame every millisecond, I only want to perform the needed calculations. – Grzegorz Brose Oct 08 '13 at 15:17
  • 1
    How will users perceive the difference between you doing "something when the music's current playtime is equal to 571ms" instead of 570ms or 572ms? Also, please explain what specifically you wish to do at these points in time. – CommonsWare Oct 08 '13 at 15:22
  • The correct solution is to pre-calculate the next (let's say) 1 second of music, find the next time when you want to react and sleep until that moment. – Joachim Sauer Oct 08 '13 at 15:22
  • If it's a music game, doesn't it make more sense to fire events, etc based on the soundwave's form? – npace Oct 08 '13 at 15:29
  • @CommonsWare - I'll have a list of pre-calculated times when the user is going to touch the screen (in ms) and I want to measure the difference between it and the actual touch time. – Grzegorz Brose Oct 08 '13 at 15:30
  • @npace - Yes, it is a music game. I'll have charts created by humans, rather than based on the soundwave and auto-generated. Though those charts still will have times specified in milliseconds. – Grzegorz Brose Oct 08 '13 at 15:33
  • See my edit. I studied this as my masters thesis. Strive for 50ms max...anything less than that is unnoticeable. – dberm22 Oct 08 '13 at 15:38
  • Many years ago, I measured the accuracy of the famous brasil band Olodum: They were able to play acurately to some 1/1000s (analysis of waveform of drums) so the OP apporach is correct to desire 1/1000 acuracy, howver if using the tounch screen, or other sensoric they will introduce much delay – AlexWien Oct 08 '13 at 16:46

4 Answers4

2

1ms accuracy is not possible to achieve using regular java, hardware, and something like Thread.sleep().

What you will need to reach 1ms precision is a Real-Time platform.

Taken from http://www.onjava.com/pub/a/onjava/2006/05/10/real-time-java-introduction.html

According to Greg Bollella, a distinguished engineer at Sun Microsystems and one of the authors of the real-time Java specification, real time means "the ability to reliably and predictably reason about and control the temporal behavior of program logic." Real time does not mean "fast," as many developers might think; it means predictable and reliable when a reaction to real-world events is required. The real-time computer will always respond before a particular deadline that you've assigned it. Depending on how you set your deadlines, numerous systems could be called real-time.

See this discussion: Java - alternative to thread.sleep

And more specifically, this article which discusses how possible a real-time application would be to deploy: http://www.embedded.com/electronics-blogs/cole-bin/4372870/Real-time-Android--real-possibility--really-really-hard-to-do---or-just-plain-impossible--

or this one: http://www.ittc.ku.edu/~niehaus/classes/753-f10/notes/sarvesh_android.pdf

Basically, I think you're out of luck for a stock, market app. If this is for your company, you can try rooting each device and going with a realtime kernal, but you're venturing into mostly unchartered waters. No gaurantee that 1ms accuracy is possible even with that route.

HOWEVER....


EDIT: It appears you do not need 1ms accuracy for your case. It just so happens that my thesis was based on audio-visual cues and perception of simultaneity.

Long story short, for 2 audio signals (1 from the left ear and one from the right), one can tell if the two impulse inputs have a delay only if the two signals are spaced more than 10ms apart. Most people had issues distinguishing the order of events at 50ms.

For eyesight, normal eyes only operate at roughly 150Hz, so a delay of anything less than 7ms, it would make no difference. The best refresh rate that I've seen was around 200Hz, or 5ms delay. However, that is only for DETECTING a bright flash of light, not your case of determining concurrency of 2 events. For something similar to what you are trying to do, I was able to safely get delays of up to 60ms without any major noticeable mismatches in audio-visual simultaneity. Your use case might require something less. ~50ms seems to be the magic number. For that type of accuracy, sleep() should be more than sufficient. A real-time system is not needed for your case.

Community
  • 1
  • 1
dberm22
  • 3,187
  • 1
  • 31
  • 46
  • Wow, 60ms is definitely not enough for a game like this! I play games of this kind since years and they measure the player's accuracy even as exact as ~16ms. – Grzegorz Brose Oct 08 '13 at 15:52
  • Obviously you would want it as small as possible, and I remember seeing somewhere that Sleep() gives you somewhere around 15ms resolution - cannot find the source though. The whole point of my post was to say that 1ms is not possible on android and that normal thread delays should be sufficient (Definitely less than 50ms). From my studies, though probably slightly different from your game, 60ms is the point at which it becomes noticeable.Try to keep it under 50ms, just don't make yourself crazy with programming delays. – dberm22 Oct 08 '13 at 16:03
1

I'll have a list of pre-calculated times when the user is going to touch the screen (in ms) and I want to measure the difference between it and the actual touch time.

That does not require "to run a thread update at least once per millisecond". You can find out the millisecond offset of the music from MediaPlayer, and compare that to your expected value. Your expected value is based off of the time when you start this whole thing up and the current time as of the touch event.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • If I make a condition like: if(mediaPlayer.getCurrentPosition() == desiredMillisecond) it fires VERY rarely. For example if my desiredMillisecond is 500 and the update runs at 499 and the next one is 501, the desired time is skipped and I'm stuck... – Grzegorz Brose Oct 08 '13 at 15:43
  • @GrzegorzBrose: If you are expecting game players to match your times *exactly*, you are either insane, planning on cyborgs playing your game, or possibly both. You need to give the user a time window. dberm22 suggested 50ms, but you could also experiment and come up with a suitable value. So if the difference between the player's position and the desired time is less than your window, you say the user hit the mark. Bear in mind that the difference in times may be negative, so compare the absolute value with, say, 25ms, to allow for slightly-quicker or slightly-slower responses. – CommonsWare Oct 08 '13 at 15:51
  • Uh, no, I'm not expecting THE PLAYER to play with accuracy of 1ms, I doubt any human would be able to do that, lol. Of course I'm going to implement a timing windows. Though 50ms is way too long. For example "Dance Dance Revolution"'s timing windows are defined for 16ms. – Grzegorz Brose Oct 08 '13 at 16:01
  • 1
    Not being sarcastic, I'd love to see the source for that 16ms number. In my tests for a person drumming to a steady beat, the best I recorded was from a professional musician, and she averaged around a 16ms standard deviation - some more, some less.The average person was atleast twice that. If I remember correctly, it was something around 50ms, though it might have been less - I can't remember exactly...but definitely not 16ms. If I were you I would do as CommonsWare suggests and do your own study to find an appropriate time. – dberm22 Oct 08 '13 at 16:15
  • Not a problem at all! Here's the source: http://www.stepmania.com/wiki/Stepmania.ini#Timing_Windows And here's a proof that it's totally possible: http://www.youtube.com/watch?v=nt0nFKpTH3I - this guy is playing "In the groove" and scored 100% of the notes with accuracy marked as "Fantastic" (aka "Marvelous"). From the first link you can see the timing window for "Marvelous" in that game is set to 21,5ms. I can't find a video of someone getting 100% at "Dance Dance Revolution Extreme" which has the mentioned 16ms timing window, though believe me, it definitely is possible :) – Grzegorz Brose Oct 08 '13 at 16:24
  • And, of course, that's just a one example. I can assure you that even an average player scores MOST of the notes with the "Marvelous" timing. I don't mean 100% of them, as that's extremely hard, but it's not like this guy is the only person in the world who can step on the panels with accuracy of 21,5ms. – Grzegorz Brose Oct 08 '13 at 16:35
  • Thanks for that. And color me impressed. I find it funny that Marvellous is better than perfect, but thats another issue lol. So then go with those windows of 22ms, 45 ms, etc. Instead of uodating your thread every ms, I like CommonsWares approach of using onclick to capture the taps, getting the theoretical tapping time from MediaPlayer and comparing it with the current time. Seems much more efficient if you ask me. – dberm22 Oct 08 '13 at 16:35
  • Okay, I think I'm beginning to understand the different approach for this problem. I'll give it a try, thanks! – Grzegorz Brose Oct 08 '13 at 16:42
  • @dberm22 16ms might be a value for western drummers, I measured "Olodum" at some ms, it think it was 3ms. from beat to beat. – AlexWien Oct 08 '13 at 16:52
0
class SampleTask extends TimerTask {
    public void run() {
       System.out.println("Hello World!"); 
    }
 }


 Timer timer = new Timer();
 timer.schedule(new SampleTask(), 1);
Prabhakaran Ramaswamy
  • 25,706
  • 10
  • 57
  • 64
0

Your problem is how to associate user input with audio output with sufficient accuracy in time (1ms) to make the appropriate work.

First, I think that 1ms is the right accuracy to strive to achieve.

Second, it's not going to be easy. JAVA is not real time, nor is Android. I think you might as well forget all the conventional approaches because there's too much delay variability in the hardware, OS and language.

Third, have you considered an alternative format if user input, say, voice? If your app could record whilst also playing the music, what you would be recording is (hopefully) the music with all other sounds superimposed on top. So all you'd have to do is a Correlation between the recording and the original to gauge the alignment of the recording with respect to the original, and then process the recording for a recognisable user sound.

That way any real time software requirement is avoided, and you exploit the only part of the platform that is semi real time; sound input and output. Trust the platform to play and record in real time, and do your processing in an ordinary way.

You won't be producing a user reaction time measurement immediately after their input so if you need to update the screen immediately after then this technique might not be suitable. But when your measurement is complete it will at least be accurate.

EDIT

The user's sound input could be really simple. For example, if they just put their finger over the microphone then the recording would suddenly get quieter. Easy to process for. Or any increase in volume in the recording that doesn't exist in the original could be considered as user input without any need to actually recognised what that additional sound is.

Also this isn't likely to work with headphones...

bazza
  • 7,580
  • 15
  • 22
  • Thanks, but I need to immediately show the accuracy to the player, not after the game is over. And yeah, it wouldn't work with headphones... – Grzegorz Brose Oct 09 '13 at 17:08