我正在使用AVAudioPlayer在我的iPhone应用中播放音乐。
在我写的一个类中,我有一个包含随机升序整数的数组。 (2,4,9,17,18,20 ......) 这些整数表示歌曲中应该发生某个事件的时间。因此,如果你采用上面的数组,在播放2秒后,应该调用一些方法。 4秒后,应该调用另一种方法。等等。
我尝试过使用重复的NSTimer:
NSTimer *myTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerTick) userInfo:nil repeats:YES];
每当它触发时,它会检查Audioplayer和当前arrayindex的值是否相同:
- (void) timerTick {
if([[myArray objectAtIndex:currentIndex] intValue] == (int)(player.currentTime)) {
//here the event-method is called
currentIndex++;
}
}
此代码实际上有效,但只有一段时间。但是经过一段时间后,myTimer和控制音乐播放器的计时器不同步。所以它错过了myArray的一个元素,并开始无限循环。我不知道为什么他们不同步,但我认为这可能是因为计时器和播放器没有在同一时间启动,或者可能是因为性能滞后。
我想我必须以完全不同的方式处理这个问题。关键值观察是否有办法实现这一目标?我可以将我的类作为观察者添加到播放器对象中,以便在player.currentTime值更改时得到通知。但这会导致发送很多通知,我认为这对性能来说非常糟糕。
非常感谢任何帮助!
答案 0 :(得分:1)
好的,这是我的解决方案:我找到了一个开源应用程序,它的应用程序应该做的几乎相同,这对我帮助很大。 我将坚持使用我已经拥有的代码,稍加修改它应该足够精确以满足我的目的。这是:
currentIndex = 0;
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(timerTick) userInfo:nil repeats:YES];
- (void) timerTick {
if(timerRunning){
if([[myArray objectAtIndex:currentIndex] intValue] <= (int)(player.currentTime*100)) {
//some event code
currentIndex++;
}
}
}
if-condition中的重要变化是从==到&lt; =。当它异步并且错过了myArray的元素时,错误会在接下来的百分之一秒内得到纠正。那太好了。
感谢您的帮助!
答案 1 :(得分:0)
可能是定时器合理地同步,但是你的代码只需要很长时间来执行(即:超过1秒)。
难道你不能只使用音乐播放器的计时器,并且每次发生事件时都会产生一个线程吗?通过这种方式,计时器可以保持不间断,并且您的线程将执行它需要做的事情(比如说重要的东西)。
如果你需要两个计时器,我猜你可以创建一个后台线程来保持这两个计时器同步,但我认为你在那里遇到麻烦..
答案 2 :(得分:0)
现实世界与音乐的同步非常困难,因为用户可以注意到十分之一秒或更短的错误同步。您可能会发现AVAudioPlayer非常简单,可以满足您的需求。您可能必须使用AudioQueueServices控制音乐播放的速率,以便您可以将音乐同步到代码而不是相反。您可以看到启动代码的时间,然后在音乐实际播放之前启动方法。巧妙地完成这将在大多数时间同步音乐。