0

I am trying to create a function that will allow me to enter the desired frames per second and the maximum frame count and then have the function "cout" to the console on the fixed time steps. I am using Sleep() to avoid busy waiting as well. I seem to make the program sleep longer than it needs to because it keeps stalling on the sleep command i think. Can you help me with this? i am having some trouble understanding time, especially on windows.

Ultimately i will probably use this timing method to time and animate a simple game , maybe like pong, or even a simple program with objects that can accelerate. I think i already understand GDI and wasapi enough to play sound and show color on the screen, so now i need to understand timing. I have looked for a long time before asking this question on the internet and i am sure that i am missing something, but i can't quite put my finger on it :( here is the code :

#include <windows.h>
#include <iostream>

// in this program i am trying to make a simple function that prints frame:  and the number frame  in between fixed time intervals
// i am trying to make it so that it doesn't do busy waiting

using namespace std;


void frame(LARGE_INTEGER& T, LARGE_INTEGER& T3, LARGE_INTEGER& DELT,LARGE_INTEGER& DESI, double& framepersec,unsigned long long& count,unsigned long long& maxcount,bool& on, LARGE_INTEGER& mili)
{
    QueryPerformanceCounter(&T3); // seccond measurement

    DELT.QuadPart = &T3.QuadPart - &T.QuadPart; // getting the ticks between the time measurements

    if(DELT.QuadPart >= DESI.QuadPart) {count++; cout << "frame: " << count << " !" << endl; T.QuadPart = T3.QuadPart; } // adding to the count by just one frame (this may cause problems if more than one passes)

     if(count > maxcount) {on = false;} // turning off the loop

    else {DESI.QuadPart = T.QuadPart + DESI.QuadPart;//(long long)framepersec; // setting the stop tick
        unsigned long long sleep = (( DESI.QuadPart - DELT.QuadPart) / mili.QuadPart);
        cout << sleep << endl;
        Sleep(sleep);} // sleeping to avoid busy waiting
}


int main()
{

    LARGE_INTEGER T1, T2, Freq, Delta, desired, mil;
    bool loopon = true; // keeps the loop flowing until max frames has been reached

    QueryPerformanceFrequency(&Freq); // getting num of updates per second
    mil.QuadPart = Freq.QuadPart / 1000; // getting the number clock updates that occur in  a millisecond
    double framespersec; // the number of clock updates that occur per target frame
    unsigned long long framecount,maxcount; //to stop the program after a certain amount of frames
    framecount = 0;


    cout << "Hello world! enter the amount of frames per second : " << endl;
    cin >> framespersec;
    cout << "you entered: " << framespersec << " ! how many max frames?" << endl;
    cin >> maxcount;
    cout << "you entered: " << maxcount << " ! now doing the frames !!!" << endl;
    desired.QuadPart = (Freq.QuadPart / framespersec);

    while(loopon == true) {
        frame(T1, T2, Delta, desired, framespersec, framecount, maxcount,loopon, mil);
    }


    cout << "all frames are done!" << endl;
    return 0;
}
user3023723
  • 7
  • 1
  • 4
  • Make sure you're passing milliseconds to Sleep. If your math yields other units (I didn't check the logic in detail), then you won't get what you want. Also, note that Sleep is traditionally not all that accurate. For instance, Sleep(1) may very well Sleep for considerably more than 1 millisecond. – TheUndeadFish Jan 14 '15 at 23:47
  • i will look into using time begin period to increase the resolution of Sleep(), but how can i make sure that i am using milliseconds? i thought i was ... – user3023723 Jan 15 '15 at 00:01
  • Having a closer look at your code, your function parameters are pointers but you are not dereferencing them. You also fail to initialise some values (e.g. you never initialise framecount). When you pass in framecount as a pointer and then do count++, you are incrementing the pointer, not the value of count. – awr Jan 15 '15 at 00:07
  • Ah okay !! I have now added a * in front of the count++ instruction. It still gets stuck though. I think i need to re write the function after i find out how to get the correct wait time. – user3023723 Jan 15 '15 at 00:14
  • It's not just count. You never initialise T1 either. I recommend you don't use pointers at all, but references: void frame(LARGE_INTEGER& T, LARGE_INTEGER& T3, LARGE_INTEGER& DELT,LARGE_INTEGER& DESI, double& framepersec,unsigned long long& count,unsigned long long& maxcount,bool& on, LARGE_INTEGER& mili). Also ensure that you correctly initialise all variables before using them – awr Jan 15 '15 at 00:16
  • I printed the value of sleep(), and well, it says : 255,852,152,499,226,9 just before it gets stuck in the sleep mode. That must have been the problem all along! I thought i was passing the correct values though, by dividing the clocks by the milliseconds clock. – user3023723 Jan 15 '15 at 00:26

2 Answers2

2

The time that you sleep is limited by the frequency of the system clock. The frequency defaults to 64 Hz, so you'll end up seeing sleeps in increments of 16ms. Any sleep that's less than 16ms will be at least 16ms long - it could be longer depending on CPU load. Likewise, a sleep of 20ms will likely be rounded up to 32ms.

You can change this period by calling timeBeginPeriod(...) and timeEndPeriod(...), which can increase sleep accuracy to 1ms. If you have a look at multimedia apps like VLC Player, you'll see that they use these functions to get reliable frame timing. Note that this changes the system wide scheduling rate, so it will affect battery life on laptops.

More info: http://msdn.microsoft.com/en-us/library/windows/desktop/dd757624%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298%28v=vs.85%29.aspx

awr
  • 530
  • 4
  • 18
  • thanks for your fast response time ! :D I think i will definitely look into that for timing a game on Win 32. But i am not getting a 60 frames per second readout, it just seams to hang on sleep like i have set it to sleep too long or something. I keep stumbling on the timing when i am trying to make a game or a program with timing needs. – user3023723 Jan 14 '15 at 23:50
  • @user3023723: Do some debugging. Print out the value you're passing to Sleep and check it seems sane. Remember that Sleep takes its value in milliseconds. – Jonathan Potter Jan 15 '15 at 00:01
  • It is not letting me print in the code. I think it either gets stuck on the console or the program stops at the first if statement in frame(). – user3023723 Jan 15 '15 at 00:09
0

Waitable timers are more accurate than Sleep, and also integrate with a GUI message loop better (replace GetMessage with MsgWaitForMultipleObjects). I've used them successfully for graphics timing before.

They won't get you high precision for e.g. controlling serial or network output at sub-millisecond timing, but UI updates are limited by VSYNC anyway.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Or call [SetTimer](http://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx). – Dan Korn Jan 14 '15 at 23:56
  • @DanKorn: That won't work in his console application at all, and also accumulates error over time, unlike the waitable timer. – Ben Voigt Jan 15 '15 at 00:23
  • What makes you think that SetTimer won't work in a console app? We use it in a Windows Service, without any UI, and it works perfectly. Also, [there's no error accumulation under Vista and later](http://www.virtualdub.org/blog/pivot/entry.php?id=272). – Dan Korn Jan 15 '15 at 18:01