2013-04-06 100 views
6

我想在Spotify啓用的應用程序中從一條曲目交叉淡入到下一條曲目。這兩條曲目都是Spotify曲目,並且由於Spotify一次只能有一個數據流,所以我懷疑我需要在第一首曲目的最後幾秒緩衝(我想我可以提前讀取1.5倍的播放速度),然後開始播放流對於第二首曲目,使用AudioUnit淡入淡出。如何使用cocoalibspotify音頻交叉淡入淡出?

我查看示例應用程序: 萬歲 - https://github.com/iKenndac/Viva SimplePlayer與EQ - https://github.com/iKenndac/SimplePlayer-with-EQ並試圖讓我的腦海裏圍繞SPCircularBuffer,但我仍然需要幫助。有人能指點我另一個例子嗎?或者幫助子彈點軌道交叉淡入淡出遊戲計劃?

更新:感謝iKenndac,我在那裏95%左右。我會後我到目前爲止有:

在SPPlaybackManager.m

:initWithPlaybackSession:(SPSession *)aSession {

補充說:

self.audioController2 = [[SPCoreAudioController alloc] init]; 
self.audioController2.delegate = self; 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 

... 


self.audioController.audioOutputEnabled = self.playbackSession.isPlaying; 

// for crossfade, add 

self.audioController2.audioOutputEnabled = self.playbackSession.isPlaying; 

和添加了基於playTrack的新方法

-(void)crossfadeTrack:(SPTrack *)aTrack callback:(SPErrorableOperationCallback)block { 
// switch audiocontroller from current to other 
if (self.playbackSession.audioDeliveryDelegate == self.audioController) 
{ 
    self.playbackSession.audioDeliveryDelegate = self.audioController2; 
    self.audioController2.delegate = self; 
    self.audioController.delegate = nil; 
} 
else 
{ 

    self.playbackSession.audioDeliveryDelegate = self.audioController; 
    self.audioController.delegate = self; 
    self.audioController2.delegate = nil; 
} 

if (aTrack.availability != SP_TRACK_AVAILABILITY_AVAILABLE) { 
    if (block) block([NSError spotifyErrorWithCode:SP_ERROR_TRACK_NOT_PLAYABLE]); 
    self.currentTrack = nil; 
} 

self.currentTrack = aTrack; 
self.trackPosition = 0.0; 

[self.playbackSession playTrack:self.currentTrack callback:^(NSError *error) { 

    if (!error) 
     self.playbackSession.playing = YES; 
    else 
     self.currentTrack = nil; 

    if (block) { 
     block(error); 
    } 
}]; 
} 

此開始用於淡入淡出

crossfadeTimer = [的NSTimer scheduledTimerWithTimeInterval:0.5 目標:自 選擇器:@selector(crossfadeCountdown) USERINFO:無 重複:YES]定時器;

而且爲了保持第一播放曲目的數據SPCoreAudioController.m加載之後我改變了目標緩衝區長度:

static NSTimeInterval const kTargetBufferLength = 20; 

和SPSession.m:音軌結尾(sp_session *會話){

我除去

// sess.playing = NO; 

我請preloadTrackForPlayback:軌道的端部約15秒之前,然後crossfadeTrack:在之前10秒。

然後設置crossfadeCountdownTime = [您想要交叉淡入淡出多少秒] * 2;

我褪色與成交量較crosssfade:

- (void) crossfadeCountdown 
    { 

     [UIAppDelegate.playbackSPManager setVolume:(1- (((float)crossfadeCountdownTime/  (thisCrossfadeSeconds*2.0)) *0.2))]; 
    crossfadeCountdownTime -= 0.5; 


    if (crossfadeCountdownTime == 1.0) 
    { 
    NSLog(@"Crossfade countdown done"); 
    crossfadeCountdownTime = 0; 
    [crossfadeTimer invalidate]; 
    crossfadeTimer = nil; 
    [UIAppDelegate.playbackSPManager setVolume:1.0]; 

    } 
} 

我會繼續做這個工作,和更新,如果我可以做的更好。再次感謝iKenndac提供的幫助!

+0

我試圖在CocoaLibSpotify中實現交叉淡入淡出功能,目前我堅持最後一步,淡入淡出音頻控制器的音量。你能否詳細說明你是如何做到的? – 2015-01-01 17:09:44

回答

4

沒有預先編寫的交叉淡化示例,我知道它使用CocoaLibSpotify。然而,一個(也許不是理想的)遊戲計劃是:

  • 製作兩個獨立的音頻隊列。 SPCoreAudioController是一個音頻隊列的封裝,所以你應該能夠實例化它們中的兩個。

  • 正常播放音樂到一個隊列。當您接近曲目末尾時,請撥打SPSessionpreloadTrackForPlayback:callback:方法,並準備下一首曲目。

  • 當播放曲目的所有音頻數據已發送時,SPSession將發出音頻委託方法sessionDidEndPlayback:。這意味着所有音頻數據都已傳送。但是,由於CocoaLibSpotify緩衝了來自libspotify的音頻,音頻停止前還有一段時間。

  • 此時,開始播放新曲目但將音頻數據轉移到第二個音頻隊列。開始減少第一個隊列的音量,同時增加下一個音量。這應該讓人滿意的交叉淡入淡出。

幾個要點:

  • SPCoreAudioController.m,你會發現下面的線,它定義了多少音頻CocoaLibSpotify緩衝區,以秒計。如果你想要一個更大的交叉淡入淡出,你需要增加它。

    static NSTimeInterval const kTargetBufferLength = 0.5; 
    
  • 既然你以最大1.5倍的實際播放速度的獲得音頻數據,注意不要做,例如,當用戶剛跳過靠近軌道的末端5秒交叉淡入淡出。您可能沒有足夠的音頻數據可用於將其關閉。

  • 看看SPPlaybackManager.m。這個類是CocoaLibSpotify和Core Audio之間的接口。這不是太複雜,理解它會讓你走很長的路。 SPCoreAudioControllerSPCircularBuffer幾乎是將音頻轉換爲Core Audio的實現細節,您不需要了解它們的實現以實現您想要的效果。

  • 此外,請確保您瞭解各種代表SPSession有。音頻傳送代表只有一項工作 - 接收音頻數據。回放委託可以獲得所有其他回放事件 - 音頻完成傳遞到音頻傳遞代理時等。沒有任何事物可以阻止一個類同時存在,但在當前實現中,SPPlaybackManager是回放委託,它創建了一個SPCoreAudioController的實例成爲音頻傳送代表。如果您修改SPPlaybackManager以擁有兩個核心音頻控制器並替換哪一個是音頻傳送代表,則應該是黃金版。

+0

謝謝,iKenndac。我在原帖中發佈了你幫助我的工作。在交叉淡入淡出之後暫停音頻的一個小問題。有任何想法嗎? – 2013-04-08 01:29:52

+0

在'SPPlaybackManager'中,KVO觀察者中有一行會在播放暫停時停止核心音頻控制器的音頻輸出,否則將繼續耗盡其緩衝區。確保您將該呼叫重定向到您的第二個核心音頻控制器。尋找'self.audioController.audioOutputEnabled = self.playbackSession.isPlaying;' – iKenndac 2013-04-08 07:59:19

+0

你對我太好了!就是這樣。太感謝了。我將盡快更新原始文章中的代碼,以指示您的手工。 – 2013-04-08 10:30:54