Click here to Skip to main content
15,889,403 members
Home / Discussions / C / C++ / MFC
   

C / C++ / MFC

 
GeneralMessage Closed Pin
14-Mar-13 18:20
Robert Inventor14-Mar-13 18:20 
GeneralMessage Closed Pin
14-Mar-13 18:53
Robert Inventor14-Mar-13 18:53 
GeneralMessage Closed Pin
14-Mar-13 19:19
Robert Inventor14-Mar-13 19:19 
AnswerRe: timeGetTime() is unreliable on my computer too, not monotonic! Pin
Robert Inventor19-Mar-13 7:31
Robert Inventor19-Mar-13 7:31 
QuestionQueryPerformanceCounter inaccurate timing even with use of SetThreadAffinityMask Pin
Robert Inventor14-Mar-13 15:50
Robert Inventor14-Mar-13 15:50 
AnswerRe: QueryPerformanceCounter inaccurate timing even with use of SetThreadAffinityMask Pin
Robert Inventor14-Mar-13 18:07
Robert Inventor14-Mar-13 18:07 
GeneralRe: QueryPerformanceCounter inaccurate timing even with use of SetThreadAffinityMask Pin
dusty_dex15-Mar-13 0:24
dusty_dex15-Mar-13 0:24 
GeneralRe: QueryPerformanceCounter inaccurate timing even with use of SetThreadAffinityMask Pin
Robert Inventor18-Mar-13 14:44
Robert Inventor18-Mar-13 14:44 
Hi, sorry I didn't reply. I've got involved in a long discussion with some friends on Facebook and doing many tests, but nothing clear yet it is quite puzzling.

But - some things I have found out.

First - you get really big errors sometimes as much as 15 ms was the largest I got which seems to rule out things like OOX?

Also - it seems to be something to do with the cores the thread runs on - and seems that SetThreadAffinityMask is not quite doing what I expect it to do.

I've tested:
RTDSC
QueryPerformanceCounter
GetSystemTimeAsFileTime
timeGetTime
GetTickCount

All of them run backwards sometimes, typically you get glitches like that every second or so on the higher resolution timers (HPC and RTDSC) and somewhat less often but still frequent on the other timers.

If I use SetThreadAffinityMask before every single time check, that doesn't fix the issue.

I think that maybe after you use SetThreadAffinityMask(..) then the thread or process has to sleep before the OS assigns it to the desired core.

SOLUTION ATTEMPT - TIE RHYTHM THREAD TO A SINGLE CORE

So - I set the thread affinity for the entire rhythm playing thread to core 1.

When I do that then again all the timers are monotonic.

So it rather looks as if it is a cpu core issue.

BTW my laptop has turbo boost. So I wondered if it was something to do with that. Ran the turbo boost monitor and I can see it going up and down a lot from 2.7 to 2.8 Ghz say. I don't know if it is anything to do with that.

Anyway - but this still doesn't seem to have solved the issue.

NOTES ARE STILL NOT PLAYED TO SUB MILLISECOND PRECISION - ERRORS OF up to 20 MS

I tested this by recording to audio as the notes are played.

One test I did just now has notes that according to my program and the windows timers were sent at 100 ms intervals with maximum error 27.576 µs (this is with the program running at real time base priority and with the rhythm playing thread at time critical on top of that so should have nothing at all interrupting it).

But it was audibly well out - and when I look at the audio recording, I had for instance one note of 80 ms immediately followed by another note of 110 ms, or a variation in the timing of about 140 % over a single note, for 100 ms notes.

That's using QueryPerformanceCounter localized to a single core - it is monotonic now, but doesn't seem to be accurate.

It might alternatively be some delay in the synth, but seems unlikely that any synth could be so badly programmed that it causes delays of as much as 30 ms, though I can do more tests by testing different synths that way.

It is unlikely to be midi relaying causing these delays as I am using a virtual cable to do the midi relaying, and I can relay about 10 midi notes per ms around a loopback and back to my program again.

Also don't see how my app could be introducing these sorts of errors - I have very much simplified the code so that the code to play the notes is very lightweight.

Basically it calculates the notes to play well before they are needed, then sits in a realtime busy wait for a few ms until the note is ready to be sent out via midi out. So there are just a few lines of code at the moment the note is played. It exits the busy wait, checks the time (which it reports as the time the note was sent) and then in the next line of code, sends it using MidiOutShortMsg.

HARDWARE CLOCKS

Anyway I have also researched and found out that there are actually two hardware clocks on the processor, the real time clock (over 1 Mhz so would achieve microsecond precision), and the HPET timer. Windows however by default doesn't seem to use either of them for its timers which might be the reason for the performance issues..

You can force Windows to use the HPET timer by using

bcdedit /set useplatformclock true and rebooting (and also setting HPET in the bios)

(Which some people find causes other performance issues so not sure if it is a good solution).

But I don't seem to have any way to enable HPET in the bios on this computer so it might not have it.

I haven't tested this yet to see if it makes a difference

OTHER WAYS TO ACCESS THE RTC

I think you can access the real time clock in kernel mode while writing a driver. Not sure, but KeQueryPerformanceCounter might access the RTC (or HPET). In Windows CE you have OEMGetRealTime but that doesn't seem to be available in Windows 7.

In Windows 8 you have GetSystemTimePreciseAsFileTime which at least according to the description seems to be using one of the hardware timers because it claims less than microsecond precision - could be using HPET but could be using the RTC which would give sufficient precision too (just).

I only have Windows 8 within a virtual machine however (seems unlikely it would work there) and haven't tested that.

THE WAY AHEAD

If I can't solve this, the only solution I can think of is to create my own sample player- and that would work because it would use audio streaming and you can simply count the number of samples played to work out the time, which is guaranteed to be accurate so long as the audio is played without any breaking up of the sound. It is for a metronome so a reasonable enough sample player for that purpose doesn't seem to tricky to do, playing non melodic percussion.

Then - presumably will get cleared up for anyone running it on Windows 8 on native hardware with GetSystemTimePreciseAsFileTime() though I haven't tested that yet.

ANY THOUGHTS ANYONE?

So anyway that's where it is at now. Once more really interested to know if anyone has any other thoughts about this or other avenues to explore.

There are so many tests you can do - and can't seem to find any online account of this in detail, just some intriguing but not complete forum discussions.


Thanks!
GeneralRe: QueryPerformanceCounter inaccurate timing even with use of SetThreadAffinityMask Pin
dusty_dex18-Mar-13 22:08
dusty_dex18-Mar-13 22:08 
AnswerRe: QueryPerformanceCounter inaccurate timing even with use of SetThreadAffinityMask Pin
Robert Inventor19-Mar-13 6:19
Robert Inventor19-Mar-13 6:19 
GeneralRe: QueryPerformanceCounter inaccurate timing even with use of SetThreadAffinityMask Pin
dusty_dex19-Mar-13 8:34
dusty_dex19-Mar-13 8:34 
GeneralRe: QueryPerformanceCounter inaccurate timing even with use of SetThreadAffinityMask Pin
Robert Inventor20-Mar-13 10:10
Robert Inventor20-Mar-13 10:10 
GeneralRe: QueryPerformanceCounter inaccurate timing even with use of SetThreadAffinityMask Pin
Robert Inventor20-Mar-13 11:12
Robert Inventor20-Mar-13 11:12 
GeneralRe: QueryPerformanceCounter inaccurate timing even with use of SetThreadAffinityMask Pin
dusty_dex20-Mar-13 11:18
dusty_dex20-Mar-13 11:18 
GeneralRe: QueryPerformanceCounter inaccurate timing even with use of SetThreadAffinityMask Pin
Robert Inventor20-Mar-13 12:15
Robert Inventor20-Mar-13 12:15 
QuestionHelp in Win32 programming with c++ Pin
naseer86114-Mar-13 8:44
naseer86114-Mar-13 8:44 
AnswerRe: Help in Win32 programming with c++ Pin
NotPolitcallyCorrect14-Mar-13 8:50
NotPolitcallyCorrect14-Mar-13 8:50 
GeneralRe: Help in Win32 programming with c++ Pin
naseer86118-Mar-13 9:41
naseer86118-Mar-13 9:41 
AnswerRe: Help in Win32 programming with c++ Pin
Maximilien14-Mar-13 8:54
Maximilien14-Mar-13 8:54 
AnswerRe: Help in Win32 programming with c++ Pin
Captain Price16-Mar-13 2:55
professionalCaptain Price16-Mar-13 2:55 
QuestionNeed a free image library, png, Visual Studio 6.0 Pin
Andrlage14-Mar-13 5:52
Andrlage14-Mar-13 5:52 
AnswerRe: Need a free image library, png, Visual Studio 6.0 Pin
Richard MacCutchan14-Mar-13 6:22
mveRichard MacCutchan14-Mar-13 6:22 
AnswerRe: Need a free image library, png, Visual Studio 6.0 Pin
_Flaviu14-Mar-13 21:19
_Flaviu14-Mar-13 21:19 
QuestionMSCOWRKS.DLL ? Pin
ForNow13-Mar-13 3:10
ForNow13-Mar-13 3:10 
AnswerRe: MSCOWRKS.DLL ? Pin
Richard MacCutchan13-Mar-13 3:53
mveRichard MacCutchan13-Mar-13 3:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.