gpt4 book ai didi

cocoa-touch - iOS 中的准确计时

转载 作者:IT王子 更新时间:2023-10-29 08:18:20 25 4
gpt4 key购买 nike

我正在查看来自 iOS SDK ( http://developer.apple.com/library/ios/#samplecode/Metronome/Introduction/Intro.html ) 的“节拍器”示例代码。我正在以 60 BPM 的速度运行节拍器,这意味着每秒滴答一次。当我查看外部 watch (PC 的 watch )时,我发现节拍器运行得太慢了 - 它每分钟错过大约一个节拍,这是应用程序。 15 毫秒的一致错误。相关代码是:

- (void)startDriverTimer:(id)info {    
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// Give the sound thread high priority to keep the timing steady.
[NSThread setThreadPriority:1.0];
BOOL continuePlaying = YES;

while (continuePlaying) { // Loop until cancelled.
// An autorelease pool to prevent the build-up of temporary objects.
NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
[self playSound];

[self performSelectorOnMainThread:@selector(animateArmToOppositeExtreme) withObject:nil waitUntilDone:NO];
NSDate *curtainTime = [[NSDate alloc] initWithTimeIntervalSinceNow:self.duration];
NSDate *currentTime = [[NSDate alloc] init];
// Wake up periodically to see if we've been cancelled.
while (continuePlaying && ([currentTime compare:curtainTime] != NSOrderedDescending)) {
if ([soundPlayerThread isCancelled] == YES) {
continuePlaying = NO;
}
[NSThread sleepForTimeInterval:0.01];
[currentTime release];
currentTime = [[NSDate alloc] init];
}

[curtainTime release];
[currentTime release];
[loopPool drain];
}
[pool drain];
}

在哪里

self.duration

在 60 BPM 的情况下为 1.0 秒。我想知道这个错误是从哪里来的,我怎样才能做一个更准确的计时器/间隔计数器。

编辑:当我将 sleep 时间更改为更小的值(例如 .001)时,问题也存在。

EDIT2(更新):当我使用 CFAbsoluteTimeGetCurrent() 方法进行计时时,问题也存在。当我使用相同的方法测量按钮点击事件之间的时间时,时间似乎是准确的——我每秒点击一次(同时看 watch ),测得的速率是 60 BPM(平均)。所以我想这一定是 NSThread (?) 的问题。另一件事是,在设备 (iPod) 上,问题似乎比在模拟器上更严重。

最佳答案

好的,经过更多测试后我有了一些答案,所以我将与任何感兴趣的人分享。

我在 play 方法(实际发送 play 消息到 AVAudioPlayer< 的方法中放置了一个变量来测量滴答之间的时间间隔 对象),正如我简单的与外部 watch 比较实验所示,60 BPM 太慢了——我得到了这些时间间隔(以秒为单位):

1.004915
1.009982
1.010014
1.010013
1.010028
1.010105
1.010095
1.010105

我的结论是,在计算每 1 秒的间隔后会消耗一些额外时间,并且额外的时间(大约 10 毫秒)会在几十秒后累积到可观的数量——这对节拍器来说非常糟糕。因此,我决定不测量之间 调用的时间间隔,而是测量从第一次调用开始的 时间间隔,这样错误就不会累积。换句话说,我已经替换了这个条件:

while (continuePlaying && ((currentTime0 + [duration doubleValue]) >= currentTime1)

在这种情况下:

while (continuePlaying && ((_currentTime0 + _cnt * [duration doubleValue]) >= currentTime1 ))

现在 _currentTime0_cnt 是类成员(对不起,如果这是 c++ 行话,我对 Obj-C 很陌生),前者持有时间戳第一次调用该方法,后者是一个 int 计数滴答数(==函数调用)。这导致了以下测量时间间隔:

1.003942
0.999754
0.999959
1.000213
0.999974
0.999451
1.000581
0.999470
1.000370
0.999723
1.000244
1.000222
0.999869

很明显,即使不计算平均值,这些值也会在 1.0 秒左右波动(平均值接近 1.0,精度至少为一毫秒)。

我很乐意听到更多有关导致额外时间流逝的原因的见解 - 10 毫秒对于现代 CPU 来说听起来像是永恒 - 尽管我不熟悉 iPod CPU 的规范(它是 iPod 4G,维基百科说CUP 是 PowerVR SGX GPU 535 @ 200 MHz)

关于cocoa-touch - iOS 中的准确计时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4485072/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com