Yes basically the timing will drift even with mach_time. There are threading overheads, plus a priority 1 thread is not hard real-time. There are probably other things that will cause the timing to drift by small amounts. Simply not being a hard real-time thread will be enough to ensure that the kernel is not scheduling accurately.
The only really accurate timers available are either from the CoreAudio renderProc or from the frame buffer vsync (CADisplayLink / CVDisplayLink). My suggestion would be to use either of those and then ensure that your callback does not block, take up too much time, do any memory allocations, or delay the renderProc in any way. If you can live with a slightly less accurate timer I would suggest using GCD dispatch_after, it effectively does the same as your code From: "Mazzaroth M." <[email protected]<mailto:[email protected]>> Date: Tuesday, 9 December 2014 1:08 pm To: coreaudio-api <[email protected]<mailto:[email protected]>> Subject: Re: precise timing -- mach_wait_until `drifts` I should also mention there is a github project here: https://github.com/mazzaroth/highres-timer with an iOS demo app. On Mon, Dec 8, 2014 at 9:07 PM, Mazzaroth M. <[email protected]<mailto:[email protected]>> wrote: Hi all, I wrote a class that attempts to do precise timing by utilizing mach_wait_until() I keep track of the absolute next_fire_date but despite that I've found that on each iteration it drifts. Is it my implementation or is it something else? I pass-in the interval, convert it to microseconds, determine the absolute start time, and iterate in a loop. For each loop I increment the next_fire_date by multiplying it by the loop iteration. - (void)run { [[NSThread currentThread] setThreadPriority:1.0]; self.running = YES; self.abs_start_date = mach_absolute_time(); uint64_t time_to_wait = nanos_to_abs(self.interval * NANOS_PER_MILLISEC); uint64_t i = 1; uint64_t next_fire_date = self.abs_start_date + (time_to_wait * i); NSLog(@"next_fire_date: %llu", next_fire_date); while (self.running) { if (mach_absolute_time() >= next_fire_date) { if (self.delegate != nil && [self.delegate respondsToSelector:@selector(highResolutionTimerDidFire)]) { [self.delegate highResolutionTimerDidFire]; i++; next_fire_date = self.abs_start_date + (time_to_wait * i); uint64_t mat = mach_absolute_time(); NSLog(@"next_fire_date - mach_absolute_time = %llu - %llu = %llu | drift: %llu", next_fire_date, mat, next_fire_date - mat, time_to_wait - (next_fire_date - mat)); mach_wait_until(next_fire_date); } } } } I can generate precise intervals(next_fire_date), and I mach_wait_until the next_fire_date(last line). But I've noticed that there is a discrepancy that is always decrementing the accuracy, or drift, from the actual time it should fire. here is a sample of a log where I fire exactly every second, or every 100000000 nanoseconds. If you look at the timestamp, the beat drifts from .436 to .434 after about a minute. The drift value shows how many nanoseconds were lost on that iteration: 2014-12-08 20:48:35.436 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5263339022368 - 5262339058321 = 999964047 | drift: 35953 2014-12-08 20:48:36.437 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5264339022368 - 5263340106379 = 998915989 | drift: 1084011 2014-12-08 20:48:37.437 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5265339022368 - 5264340106729 = 998915639 | drift: 1084361 2014-12-08 20:48:38.437 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5266339022368 - 5265340106385 = 998915983 | drift: 1084017 2014-12-08 20:48:39.437 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5267339022368 - 5266340101173 = 998921195 | drift: 1078805 2014-12-08 20:48:40.437 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5268339022368 - 5267340052154 = 998970214 | drift: 1029786 ... 2014-12-08 20:49:42.434 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5330339022368 - 5329339997208 = 999025160 | drift: 974840 2014-12-08 20:49:43.434 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5331339022368 - 5330340058567 = 998963801 | drift: 1036199 2014-12-08 20:49:44.434 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5332339022368 - 5331340107270 = 998915098 | drift: 1084902 2014-12-08 20:49:45.434 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5333339022368 - 5332340104089 = 998918279 | drift: 1081721 2014-12-08 20:49:46.434 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5334339022368 - 5333340046114 = 998976254 | drift: 1023746 2014-12-08 20:49:47.434 highres-timer[6485:146173] next_fire_date - mach_absolute_time = 5335339022368 - 5334340050894 = 998971474 | drift: 1028526 Hopefully this is a clear explanation. Any suggestions?
_______________________________________________ Do not post admin requests to the list. They will be ignored. Coreaudio-api mailing list ([email protected]) Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/coreaudio-api/archive%40mail-archive.com This email sent to [email protected]
