2013-04-06 8 views
6

Ich möchte in einer Spotify-fähigen App von einer Spur zur nächsten überblenden. Beide Tracks sind Spotify-Tracks, und da immer nur ein Datenstrom von Spotify kommen kann, vermute ich, dass ich die letzten paar Sekunden des ersten Tracks puffern muss (ich denke, ich kann 1,5 x Wiedergabegeschwindigkeit vorauslesen), starte den Stream für Spur zwei, blenden Sie eine aus und blenden Sie zwei mit einer AudioUnit ein.Wie überspiele ich Audio mit Cocoalibspotify?

Ich habe überprüft Beispielanwendungen: Viva - https://github.com/iKenndac/Viva SimplePlayer mit EQ - https://github.com/iKenndac/SimplePlayer-with-EQ und versuchte, meinen Kopf um die SPCircularBuffer zu bekommen, aber ich brauche noch Hilfe. Könnte mich jemand auf ein anderes Beispiel hinweisen oder helfen, einen Track Crossfade-Spielplan aufzuschreiben?

Update: Dank iKenndac bin ich etwa 95% dort. Ich werde schreiben, was ich habe, so weit:

in SPPlaybackManager.m: initWithPlaybackSession: (SPSession *) session {

hinzugefügt:

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

und in

- (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; 

und eine neue Methode basierend auf playTrack hinzugefügt

-(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); 
    } 
}]; 
} 

Dies startet einen Zeitgeber für die Überblendung

crossfadeTimer = [NSTimer scheduledTimerWithTimeInterval: 0,5 Ziel: Selbst selector: @selector (crossfadeCountdown) userinfo: nil repeats: JA];

Und um den ersten Titel zu spielen, nachdem seine Daten in SPCoreAudioController.m geladen ist zu halten, änderte ich Zielpufferlänge:

static NSTimeInterval const kTargetBufferLength = 20; 

und in SPSession.m: End_of_Track (sp_session * Sitzung) {

I entfernt

// sess.playing = NO; 

ich nenne preloadTrackForPlayback: etwa 15 Sekunden vor dem Ende der Spur, dann crossfadeTrack: 10 Sekunden vor an.

Dann setzen Sie crossfadeCountdownTime = [wie viele Sekunden möchten Sie die Überblendung] * 2;

ich verblassen Volumen über die crosssfade mit:

- (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]; 

    } 
} 

ich daran halten werde arbeiten, und zu aktualisieren, wenn ich es besser machen kann. Vielen Dank nochmal an iKenndac für seine immer aktuelle Hilfe!

+0

Ich versuche, die Crossfade-Funktionalität in CocoaLibSpotify zu implementieren und bin derzeit im letzten Schritt stecken, verblasst die Lautstärke beider AudioController. Könnten Sie näher erläutern, wie Sie das geschafft haben? –

Antwort

4

Es gibt kein bereits geschriebenes Crossfade-Beispiel, das CocoaLibSpotify verwendet. Ein (möglicherweise nicht idealer) Spielplan wäre jedoch:

  • Erstellen Sie zwei separate Audiowarteschlangen. SPCoreAudioController ist eine Verkapselung einer Audio-Warteschlange, Sie sollten also nur zwei von ihnen instanziieren können.

  • Musik als normal für eine Warteschlange wiedergeben. Wenn Sie sich dem Ende des Tracks nähern, rufen Sie die SPSessionpreloadTrackForPlayback:callback: Methode mit dem nächsten Track auf, um es fertig zu machen.

  • Wenn alle Audiodaten für den abgespielten Track zugestellt wurden, wird SPSession die Audio-Delegate-Methode sessionDidEndPlayback: auslösen. Dies bedeutet, dass alle Audiodaten geliefert wurden. Da CocoaLibSpotify jedoch den Ton von libspotify puffert, bleibt noch etwas Zeit, bis der Ton stoppt.

  • Beginnen Sie an diesem Punkt mit der Wiedergabe des neuen Tracks, aber leiten Sie die Audiodaten in die zweite Audio-Warteschlange um. Starten Sie das Volumen der ersten Warteschlange, während Sie das Volumen der nächsten Warteschlange hochfahren. Dies sollte eine angenehme Überblendung ergeben.

  • Ein paar Hinweise:

    • In SPCoreAudioController.m, werden Sie die folgende Zeile finden, die, wie viel Audio CocoaLibSpotify Puffer definiert, in Sekunden. Wenn Sie eine größere Überblendung möchten, müssen Sie sie erhöhen.

      static NSTimeInterval const kTargetBufferLength = 0.5; 
      
    • Da Sie Audiodaten auf maximal 1,5x tatsächlichen Wiedergabegeschwindigkeit zu erhalten, darauf achten, nicht zu tun, beispielsweise ein 5 Sekunden Blendung, wenn der Benutzer gerade übersprungen nahe dem Ende der Spur. Sie haben möglicherweise nicht genügend Audiodaten zur Verfügung, um es abzurufen.

    • Werfen Sie einen Blick auf SPPlaybackManager.m. Diese Klasse ist die Schnittstelle zwischen CocoaLibSpotify und Core Audio. Es ist nicht zu kompliziert, und es zu verstehen, wird dich sehr weit bringen. SPCoreAudioController und SPCircularBuffer sind ziemlich viele Implementierungsdetails, um das Audio in Core Audio zu bekommen, und Sie sollten ihre Implementierungen nicht verstehen müssen, um zu erreichen, was Sie wollen.

    • Auch stellen Sie sicher, dass Sie die verschiedenen Delegierten verstehen SPSession hat. Der Audio Delivery Delegate hat nur einen Job - um Audiodaten zu empfangen. Der Wiedergabe-Delegat erhält alle anderen Wiedergabeereignisse - wenn die Audioausgabe an den Audio Delivery-Delegaten usw. übergeben wurde. Es gibt keine Möglichkeit, eine Klasse zu deaktivieren. In der aktuellen Implementierung ist SPPlaybackManager der Playback-Delegat, der eine Instanz von SPCoreAudioController erstellt der Audio Delivery-Delegat sein. Wenn Sie SPPlaybackManager ändern, um zwei Core Audio-Controller zu haben, und abwechselnd den Audio Delivery-Delegaten wählen, sollten Sie golden sein.

    +0

    Danke, iKenndac. Ich habe die Arbeit, mit der du mir geholfen hast, im ursprünglichen Beitrag gepostet. Nur ein kleines Problem mit dem Pausieren der Audio nach der Überblendung. Irgendwelche Ideen? –

    +0

    In 'SPPlaybackManager' gibt es eine Zeile in einem KVO-Observer, die die Audioausgabe des Audio-Controllers stoppt, wenn die Wiedergabe angehalten wird. Andernfalls wird der Puffer weiter aufgebraucht. Stellen Sie sicher, dass Sie diesen Anruf auch an Ihren zweiten Core Audio Controller umleiten. Suchen Sie nach "self.audioController.audioOutputEnabled = self.playbackSession.isPlaying;' – iKenndac

    +0

    Sie sind so gut zu mir! Das war's. Tausend Dank. Ich werde den Code im ursprünglichen Post bald aktualisieren, um Ihre Handarbeit anzuzeigen. –