Link to home
Start Free TrialLog in
Avatar of bitmask
bitmask

asked on

Timing Procedures in C++

    I am writing some MIDI sequencing software, and have found the standard Timer component for Visuall C++ to be too slow, and it skips beats.  I know that you can implement your own timing code into your program, which is extremely accurate (milisecond intervals).  You do this with the SetTimer and TimerProc functions.  Can you show me an example *.cpp file which illustrates how to write your own callback function TimerProc, and how to call the SetTimer function to use the callback function every time the interval has expired?  Basicly, I need some kind of very accurate timing mechanism that will execute a block of code every time a timer message is recieved.  Can you Help?  I use Borland C++ Builder.
Avatar of nietod
nietod

First of all, do you understand that the SetTimer timers and the TimerProc will function only if your program has a windows message loop operating at the same time.  This is because the timer procedure is called after a timer message has been handled by the default window procedure.  Is that going to work for you?
Avatar of bitmask

ASKER

Please, I need simple responses.  I just want to know how to get an accurate timer going.  Step by step, what to put in the *.h and what to put in the *.cpp.  I already know that I am doing things wrong, so telling me that doesn't help me!!!!!
You missunderstood me.  I'm not saying you're doing anything wrong.  I'm trying to determine whethor or not a timer will function for your case.  Window's timers are a bit missleading.  But I'll post the sample code next and we'll see.
VOID CALLBACK TimPrc(HWND hwnd, UINT uMsg, UINT idEvent,DWORD dwTime)
{
}

   *    *    *
{
   UINT TimHnd = SetTimer( NULL,0,1000,TimPrc);


   *    *    *

   KillTimer(NULL,TimHnd);

}
I haven't looked at this topic in a while, but I seem to remember the multimedia timer is the way to go for fine timing of things.

Also I believe there is a limit to the number of timers you can set.  An alternative that will let you have unlimited timers is to set one timer and then build a class that allows multiple instances and each instance to have its own timestamp.

Essentially at creation of the first one you install your timerproc (settimer)
At each time thereafter you simply get the time off the multimedia timer,  then when you are done you collect the finish time off the multimedia timer and you have an elapsed time.

I have old code that does this, I just have to find it.


In the example, the timer procedure called TimPrc() will be called every second  (I set the interval to 1000 milliseconds which is 1 second).  

The parameters passed to TimPrc will probably be ignored.  They must be there however.  The last parameter is the current time, of sorts, and might be useful, but the rest probably not.

The SetTimer() procedure creates a timer and stores a handle to it in TimHnd.   Whent he timer is not needed KillTimer() is used to destroy it.  You may want to make TimHnd a global varialbe depending on your needs.  (since SetTimer() and KillTimer()) will probably be in different procedures).

That's all there is to it except for one detail.  You must have a windows message loop runing or the timer procedure won't get called.  That is your program must be doing GetMessage() and DispatchMessage() or the procedure doesn't get called.  
I also should mention that there is no gaurantee that your procedure will be called as frequently as you request.  If you set the interval very small it may be called irregularly.  Usually 10 times a second is not a problem when your program is in the foreground AND is not taking a long time to process messages.  Note that when you are processing a non timer message (like WM_PAINT) you can't be processing timer messages, so the response of the timer depends in large part on your application.
Because timers use windows messages, they are NOT accurate.
For timing purposes, use either multimedia timers (e.g., timeSetEvent() etc.) or the performance monitoring functions (QueryPerformanceCounter() etc.) which give the best resolution.
Okay where were you guys when I was trying get across that this might not be what he wants?
Avatar of bitmask

ASKER

I am trying this just to see if the timer stuff works, and I am having no success.  Also, once this is written, how can I use variable names, and object names for stuff on my main form from within the TimerProc?  At the very least, how can I call other functions on the same form/*.cpp?

//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "mmsystem.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent,DWORD dwTime)
{
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
      : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
MMRESULT timeSetEvent(100, 0, TimerProc, NULL, TIME_PERIODIC);
}
//---------------------------------------------------------------------------
>> Okay where were you guys when I was trying get across that this might not be what he wants?

Probably off line.
>> I am trying this just to see if the timer stuff works, and I am having no success.  
This probably isn't the right way to go because the timing isn't accurate enough.  But it will work and you should be able to access variables,objects, and functions as usual.  

There is a MAJOR problem with using the TimerProc function.  It is of the LEAST priority in the messaging scheme.  If there is another message, then the WM_TIMER message gets pushed down in the message queue.  It is USUALLY fairly acurate, but if your program processes many messages, then I would NOT suggest using the WM_TIMER message.  I dunno if this is of any use to you, but I figured that you should know about it.

~Aaron
I am currently working on a real-time test system for use in the Win32 environment.  Using a fairly small callback module, I am seeing timing problems at 50Hz.  At slower speeds, the timing does become more accurate, but keep in mind that any action that queues messages will kill your determinism (i.e. moving the window, resizing, opening menus, etc.)  One option I can think of that might work:
Using Borland C++ 5.0, I was able to use the new WinNT timing function SetWaitableTimer with WaitForSingleObjectEx to get a fairly accurate timer system (and it doesn't rely on messaging).
Avatar of bitmask

ASKER

It would be greatly appreciated to have not only suggestions, but also some code to go with it.
Avatar of tuvi
If I am not wrong, Borland C++ Builder has a TTimer Component. Why don't you use it?
Avatar of bitmask

ASKER

I cant use the Timer component that comes with visual c++ development environment because it is way too slow.  And it ends up skipping beats.  I need accuracy - not ease of use!
ASKER CERTIFIED SOLUTION
Avatar of tuvi
tuvi
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Bitmask, I forgot to mention the TWMTimer structure (wrapper for WM_TIME message) as defined in <Messages.hpp>

struct TWMTimer
{
  Cardinal Msg;
  long TimerID;
  void *TimerProc;
  long Result;
} ;
Avatar of bitmask

ASKER

Kudos to tuvi!!!!!!!!!!!!!!!!!!!!!  I wrote a little timer app with the source code provided by tuvi and it works very well.  I am anxious to try implementing it into my MIDI program.  It seems like very solid timing code.  VERY MUCH APPRECIATED.  I will post an update detailing my success or failure.  THANK YOU!!!!
If VC's timer component is too slow this will be as well.  They are based on the same mechansim.  This is what I was trying to warn you of.
Avatar of bitmask

ASKER

nietod --
if that is the case can you suggest an alternate method.  I know it can be done, as many people write sequencing software.  What other means of building timers are available?  Code examples would be great!
As alexo suggested, you need to be using the multimedia timers.  I don't have any source code, but most likely no one has builder type source code for this.  You are going to have to learn how to combine ordinary C++ with your builder code.
Avatar of bitmask

ASKER

If thats the case couldn't I use assembler code then?
You could, but I see no reason why you should.  You can use ordinary C++.  Builder is a C++ compiler.  It has neat framework that hides some of the C++ details from you.  In order to make some things work, like the code I originaly posted, you are going to have to learn how to use ordinary C++ code in your project (like what file to stick it in and where) or you going to have to learn how to convert the C++ code so it fits into the framework.
>> If thats the case couldn't I use assembler code then?
You could also deep fry your privates.  However, I see no reason for both activities.

bitmask, let me summarize:
1. Windows timers (SetTimer() etc.) are extremely unaccurate.
2. Multimedia timers (timeSetEvent() etc.) are better.
3. Performance monitoring functions (QueryPerformanceCounter() etc.) give good resolution but cannot schedule events.
4. Pentium counters have even better resolution than #4 but are non-portable and require deep-frying your privates..., err..., Assembly coding.

Now, a WDJ column came up with an interesting solution.
Basically, you schedule an event (using multimedia timers) a bit before it must occur, then busy wait (using performance monitoring) until the exact time.