我正在使用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值更改时通知它。但这会导致发送很多通知,我认为这对性能来说非常糟糕。

非常感谢任何帮助!

有帮助吗?

解决方案

好的,这是我的解决方案:我找到了一个开源应用程序,它的应用程序应该做的几乎相同,这对我帮助很大。 我将坚持使用我已经拥有的代码,稍加修改它应该足够精确以满足我的目的。这是:

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条件中,重要的变化是从==到<!> lt; =。当它异步并且错过了myArray的元素时,错误会在接下来的百分之一秒内得到纠正。那太好了。

感谢您的帮助!

其他提示

可能是定时器合理地同步,但是你的代码只需要很长时间来执行(即:超过1秒)。

难道你不能只使用音乐播放器的计时器,并且每次发生事件时都会产生一个线程吗?通过这种方式,计时器可以保持不间断,并且您的线程将完成它需要做的事情(让我们说重要的东西)。

如果你需要两个计时器,我猜你可以创建一个后台线程来保持这两个计时器同步,但我认为你在那里遇到麻烦..

真实世界与音乐的同步是非常困难的,因为用户可以注意到十分之一秒或更短的错误同步。您可能会发现AVAudioPlayer非常简单,可以满足您的需求。您可能需要使用 AudioQueueServices ,以便您可以将音乐同步到代码而不是相反。您可以看到启动代码的时间,然后在音乐实际播放之前启动方法。巧妙地完成这将在大多数时间同步音乐。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top