2009-10-26 80 views
0

我使用AVAudioPlayer在我的iPhone應用程序中播放音樂。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值發生更改時收到通知。但是這會導致很多通知被髮送,我認爲這對性能來說真的很糟糕。

任何幫助,非常感謝!

回答

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條件。當它異步並錯過myArray的元素時,錯誤在下一百分之一秒被糾正。這很好。

感謝您的幫助!

0

這可能是因爲計時器是相當同步,但你的代碼只是需要長期執行(即:不再那麼1秒)。

你不能只是使用musicplayer的定時器,每應該發生的事件時生成一個線程?這樣計時器保持不間斷,並且你的線程將做它需要做的事情(可以說重的東西)。

如果雷爾Ÿ需要兩個定時器,我想你可以創建,保持這兩個定時器同步後臺線程,但我認爲你是在自找麻煩有..

+0

「難道你不能只使用音樂播放器的計時器」我很樂意!我其實不需要另一個計時器。但我應該怎麼做?我怎麼知道是否該打電話給我的事件方法?什麼時候應該檢查是否([[myArray objectAtIndex:currentIndex] intValue] ==(int)(player.currentTime))? – avf 2009-10-26 12:34:48

0

音樂現實世界同步非常困難,因爲用戶可能會注意到誤差只有十分之一秒或更少。您可能會發現AVAudioPlayer可以簡化您的需求。您可能需要使用AudioQueueServices來控制音樂播放的速率,以便您可以將音樂同步到代碼而不是其他方式。你可以看到時間來開始你的代碼,然後在音樂真正播放之前開始這些方法。熟練地完成這將大部分時間同步音樂。