1

The first thing that strikes me: System.currentTimeMillis() i think kind of very accurate, gives a long value, and where as SwingTimers request for an int parameter; what does it say?Don't consider SwingTimers to be accurate?

2)Suppose timing a word with SwingTimer takes x milliseconds; if we are repeating a task (highlighting a word, like karaoke apps), i included this code:

               /*see the time taken for each letter*/                    
                 int tik=(int) delay / words[index].length();
 /* make adjustment(subtract few millisecs)  as per the time taken by each word*/
                   if(tik <69)
                    timer.setDelay((int) (delay / words[index].length())-3);
                   if(tik >=69&&tik<=149)
                    timer.setDelay((int) (delay / words[index].length())-6);
                   else if(tik <=150)
                       timer.setDelay((int) (delay / words[index].length())-9);
                   else if(tik >150)
                   timer.setDelay((int) (delay / words[index].length())-100);

Works quiet well, but i am definitely sure i cannot rely on this,as time, length may change! How to overcome this?As change in few millisec may bring disastrous results to me.

3)At the same time i wonder which techniques dose Karaoke maker&player softwares follow???, Very accurate.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
joey rohan
  • 3,505
  • 5
  • 33
  • 70
  • 1
    *System.currentTimeMillis() i think kind of very accurate* `System.nanoTime()` is more accurate than `System.currentTimeMillis()`. And I agree `SwingTimer` is inaccurate and unrelaibale for exact timings. My fisrt thought is use a `Thread` with a while loop and `System.nanoTime()` and dont forget to wrap all Swing code in `invokeLater`. +1 to trashgod comment below – David Kroukamp Jan 30 '13 at 17:53
  • 2
    The resolution of `System.currentTimeMillis()` varies by [platform](http://mindprod.com/jgloss/time.html#ACCURACY). – trashgod Jan 30 '13 at 17:54
  • @DavidKroukamp this is arguable;I use to think the same before, but i came across few post, which were on favour of `System.currentTimeMillis()` – joey rohan Jan 30 '13 at 17:56
  • @trashgod agree,main issue is about `SwingTimers` – joey rohan Jan 30 '13 at 17:57
  • @joeyrohan IMO not arguable at all I have been doing games and animation for a while and trust me it makes a difference a beeg difference especially if we now convert that time to a float, double , int etc. and vice versa... – David Kroukamp Jan 30 '13 at 17:57
  • @DavidKroukamp ok will try to implement :) – joey rohan Jan 30 '13 at 17:58
  • @trashgod thank-god i am using Win7 :) – joey rohan Jan 30 '13 at 18:07
  • don't understand the question: both system.millis and timer.delays are (nominally) _milliseconds_ - doesn't matter whether data type is long or int, for animation-relevant periods – kleopatra Jan 30 '13 at 18:08
  • 1
    @kleopatra I think the base of the question is how accurate is Swing Timer/is Swing Timer accurate enough for this sort of use... – David Kroukamp Jan 30 '13 at 18:10
  • @kleopatra it came to my mind cause of increase data type size of long over int, my be a silly thing, but was bugging me the difference in the data types – joey rohan Jan 30 '13 at 18:12
  • (i) `System.nanoTime()` IS at least as accurate as `System.currentTimeMillis()` by [contract](http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#nanoTime%28%29) (ii) I have empirically observed that the resolution of swing timers can be as high as 15/20 ms, which might or might not matter depending on your use case (iii) this has little to do with data type: currentTimeMillis is the number of ms since 1/1/1970, which could not fit in an int - however to define a delay in a SwingTimer, an int is big enough (unless you want to time something in more than 25 days). – assylias Jan 30 '13 at 18:14
  • @assylias thanks for the documentation +1 :) – joey rohan Jan 30 '13 at 18:24
  • 1
    Accuracy of SwingTimer is highly impacted by the time of execution of the `ActionListener`. The delay is the time between the end of the execution of the listener and the beginning of the next execution. Therefore, you can definitely not rely on Swing timer for a karaoke. – Guillaume Polet Jan 30 '13 at 18:26
  • @GuillaumePolet any alternative?Same thing goes for Util timers? – joey rohan Jan 30 '13 at 18:29
  • @joeyrohan an alternative to Timers is using Thread with while loop, `Thread.sleep` and `invokeLater` block for Swing code (dont forget to subtract 15 milliseconds from sleep time to make up for average cpu latency) – David Kroukamp Jan 30 '13 at 18:58
  • @DavidKroukamp will try it out :) – joey rohan Jan 30 '13 at 19:01
  • @joeyrohan you can still use Swing Timer but at the end of the ActionListener, you have to set the next delay based on the current time (for example using System.nanoTime()) – Guillaume Polet Jan 30 '13 at 21:21
  • @joeyrohan I would suggest that the reason `javax.swing.Timer` takes a `int` value rather then a `long` value has more to do with the fact that the designers never envisioned the need for some to have a timer that needs to wait more then `Integer.MAX_VALUE` milliseconds (roughly 25 days). The major issue with the accuracy also has a lot to do with the need for the `Timer` to re-sync with the Event Dispatching Thread. Even with a `Thread#sleep` approach, you would need to re-sync with the Event Dispatching Thread, which will reduce the accuracy and can't be accurately measured – MadProgrammer Jan 30 '13 at 22:22
  • @GuillaumePolet i din't get it :/ – joey rohan Jan 31 '13 at 06:27
  • @MadProgrammer hmm yeah..! lets see how will i sort this out. – joey rohan Jan 31 '13 at 06:28

3 Answers3

6

At the same time i wonder which techniques do Karaoke maker & player software follow?

I'm guessing that karaoke software has an engine where the beat and time signature are entered, and the note durations (whole note, half note, quarter note, etc.) are entered along with the lyrics.

The engine calculates the number of milliseconds per quarter note, and displays one letter at a time based on the calculation.

I suspect that the note durations have to be entered manually, but it would be really efficient if the engine listens to the music and determines the note durations from the music.

Keeping perfect time

As you've already determined, Thread.sleep() and Swing timers don't keep perfect time.

You're going to have to build your own timer if you want precise time keeping. Here's one version.

    public void moreAccurateTimer(int period) { // Sleep time in
                                                // milliseconds
        long beforeTime, timeDiff, sleepTime;
        beforeTime = System.currentTimeMillis();
        boolean running = true;
        while (running) {
            doStuff();

            timeDiff = System.currentTimeMillis() - beforeTime;
            sleepTime = period - timeDiff;

            if (sleepTime <= 0L) { // Even if doing stuff took longer than
                                    // period
                sleepTime = 5L; // sleep some anyway
            }

            try {
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
            }

            beforeTime = System.currentTimeMillis();
        }
    }
Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111
  • I have few softwares, where physically you have to first set the karaoke(by pressing a key or something)then the karaoke is displayed accordingly.I am doing the same thing, then how come they are just perfect? – joey rohan Jan 30 '13 at 18:03
  • +1 on the fact that I cannot argue any point even if the engines did not do this they should!!! And @joeyrohan most likey they are 10-15 miliseconds off on avearge but you would never notice it. IMO that Swing Timer is whats setting you back I have had the same though since I posted my answer to your first question on karaoke... Is the Swing Timer accurate enough for a precision based application? and my answer is no. – David Kroukamp Jan 30 '13 at 18:05
  • @DavidKroukamp any alternative?I have reached so far in my 3rd year project (you can understand), now a little delay can spoil evrything.If want to know the real thing about logic of karaoke apps, and difference in my logic ...!But searching for hours have given me nothing! – joey rohan Jan 30 '13 at 18:16
  • @joeyrohan well I would like to know how you got the exact timings for each letter/word to match the song, unless it was very accurate its already going to put you off a couple of milliseconds... And at that how did you start the song and karaoke timer at the exact same timer? or the timer/song would always be another couple of milliseconds off. See what I am getting at everything you do needs to be precise in order to achieve overall accuracy. – David Kroukamp Jan 30 '13 at 18:31
  • @DavidKroukamp taking the timings physically,when user press a key,and check total millisec time elapse between two consecutive' key press,which gives me the timing for a word.Now i play the karaoke .Take the timings respectively from the array, and highlight the letters..! – joey rohan Jan 30 '13 at 18:36
  • I don't think (didn't try nor measure anything ;-) that would really help - doStuff must happen on the EDT and me-guessing that's the bottleneck for (more or less uncontrollable) latency – kleopatra Jan 30 '13 at 20:07
  • @kleopatra and that doStuff is? – joey rohan Jan 31 '13 at 06:29
  • @kleopatra doStuff is already inside swing timer,means inside EDT – joey rohan Jan 31 '13 at 09:23
  • Thanks for the answer, i got the concept of s/w thing i was asking..! – joey rohan Jan 31 '13 at 13:02
6

The approach to base the timing on the computers/OS clock, regardless how accurate the time source is - is generally flawed, although it may work out ok in some scenarios where the timing doesn't need to be all that accurate.

A smart approach is to get the timing information form the thing you want to synchronise to - so for karaoke, get the time elapsed from the playing audio and respond to that. This method naturally avoids common headaches: handling (user initiated) pauses in audio playback as well as the tiny time skews between audio and system hardware.

Durandal
  • 19,919
  • 4
  • 36
  • 70
  • And how to do that?Any kind of documentation support? – joey rohan Jan 30 '13 at 18:27
  • @joeyrohan Take a look at the javax.sound.sampled Javadocs. You can ask an audio line for its current playback/record position http://docs.oracle.com/javase/1.4.2/docs/api/javax/sound/sampled/DataLine.html#getMicrosecondPosition%28%29. This should get you started. (Edit: fixed package name audio -> sound) – Durandal Jan 30 '13 at 18:47
  • @Durandal well thanks +1.But i have already taken tutorials about Sound API and is very complex in this context.Will use this path if i don't get a simple one :) – joey rohan Jan 30 '13 at 18:51
  • @joeyrohan I found the sound API confusing too, at first. Once you get the big picture, everything falls into place and it becomes relatively simple to use. Depending on whatlevel of control you want over your audio you may get away with a high level API. I personally wouldn't want to go back to being stuck with 'premade' simple API's that lock me out of everything (AudioClip anyone ;) – Durandal Jan 30 '13 at 19:14
2

We must accept that we can never arrive precisely on time; we can either be early or late.

Consider for many years, 24 frames per second has made continuous looking movies. And now, weve moved to 59 FPS? So, +/- 20ms or so would be un-noticeable to a human.

If your application requires precise timing on the electronic level, consider that scheduling and concurrency can cause all kinds of problems. When I worked at C******e around Y2K that was a big big deal, and was often affected by video settings and so on. Artifacts of timing-related problems showed-up as latency, glitching, and pitch inaccuracy.

Say that we use the while loop method (pardon my pseudocode):

/** psuedocode **/

something.idLikeToTriggerNow();

time_now = time_then = system.getMicroseconds();

while (time_now < time_then + 1000){

; //NOP

time_now = system.getMicroseconds();

}

something.idLikeToTrigger1msLater();

/** end psuedocode **/

This only guarantees that you will not get out before one millisecond after you enter. However, you could get interrupted getting the system time, somehow, and get out a half second later, instead, because of maybe Norton Antivirus. My point has nothing to do with Java, in particular. Also, even if the while loop worked fine, the next action could get delayed by your NVidia drivers, perhaps, which might have a higher priority than your Java app in the grand scheme of things.

Is there an approach in Java that makes it more likely the two events be 1ms apart to a tolerance of, perhaps, +/- 100us?

  • Well I solved the problem after great efforts and bounty.Please look at this thread : http://stackoverflow.com/questions/15040989/issues-creating-a-very-accurate-swing-timer – joey rohan Aug 13 '14 at 18:20