Как сделать аудио crossfade с помощью cocoalibspotify?

Я хотел бы перейти с одного трека на другой в приложении с поддержкой Spotify. Оба трека являются треками Spotify, и поскольку только один поток данных за раз может исходить от Spotify, я подозреваю, что мне нужно буферизировать (я думаю, что могу читать вперед 1.5 x скорость воспроизведения) последние несколько секунд первого трека, запустить поток для второго трека, выцветать один и исчезать в два с помощью AudioUnit.

Я рассмотрел примеры приложений: Вива - https://github.com/iKenndac/Viva SimplePlayer с EQ -https://github.com/iKenndac/SimplePlayer-with-EQ и попытался сосредоточиться на SPCircularBuffer, но мне все еще нужна помощь. Может ли кто-нибудь указать мне на другой пример или помочь bullet-point план игры track crossfade?

обновление: благодаря 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: nil повторяет: Да];

и для того, чтобы первый трек играл после того, как его данные загружены в SPCoreAudioController.m я изменил длину целевого буфера:

static NSTimeInterval const kTargetBufferLength = 20;

и в SPSession.m: end_of_track (sp_session *session) {

Я убрал

// sess.playing = NO;

Я вызываю preloadTrackForPlayback: около 15 секунд до конца трека, затем crossfadeTrack: за 10 секунд до этого.

затем установите crossfadeCountdownTime = [сколько секунд вы хотите crossfade]*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 за его всегда точечную помощь!

1 ответов


нет предварительно написанного примера crossfade, который я знаю, что использует CocoaLibSpotify. Однако (возможно, не идеальный) план игры такой:

  • сделайте две отдельные очереди аудио. SPCoreAudioController является инкапсуляцией аудио очереди, поэтому вы должны просто иметь возможность создавать экземпляры двух из них.

  • воспроизведение музыки в обычном режиме в одну очередь. Когда вы приближаетесь к концу пути, называют SPSession ' s preloadTrackForPlayback:callback: метод со следующей дорожкой к приготовься.

  • когда все аудио данные для воспроизведения трека были доставлены,SPSession запустит метод делегата аудио sessionDidEndPlayback:. Это означает, что все аудиоданные были доставлены. Однако, поскольку CocoaLibSpotify буферизует аудио из libspotify, есть еще некоторое время до остановки звука.

  • на этом этапе начните воспроизведение нового трека, но перенаправьте аудиоданные во вторую очередь аудио. Начать сворачивать объем первая очередь при увеличении громкости следующей. Это должно дать приятный crossfade.

несколько советов:

  • на SPCoreAudioController.m, вы найдете следующую строку, которая определяет, сколько аудио cocoalibspotify буферов, в секундах. Если вы хотите больше crossfade, вам нужно увеличить его.

    static NSTimeInterval const kTargetBufferLength = 0.5;
    
  • поскольку вы получаете звуковые данные с максимальной скоростью воспроизведения 1.5 x, будьте осторожны, чтобы не делать, например, 5-секундный кроссфейд, когда пользователь только что пропустил около конца дорожки. Возможно, у вас недостаточно аудиоданных, чтобы снять его.

  • посмотрите на SPPlaybackManager.m. Этот класс является интерфейсом между CocoaLibSpotify и Core Audio. Это не слишком сложно, и понимание этого поможет вам пройти долгий путь. SPCoreAudioController и SPCircularBuffer в значительной степени детали реализации получения звука в Core Audio, и вам не нужно понять их реализации, чтобы достичь того, чего вы хотите.

  • кроме того, убедитесь, что вы понимаете различные делегатов SPSession есть. Делегат доставки аудио имеет только одно задание-получение аудиоданных. Делегат воспроизведения получает все другие события воспроизведения - когда аудио закончено доставляться делегату доставки звука и т. д. Ничто не мешает одному классу, но в текущей реализации SPPlaybackManager является делегатом воспроизведения, который создает пример SPCoreAudioController быть делегатом доставки аудио. Если вы измените SPPlaybackManager чтобы иметь два основных аудиоконтроллера и чередовать, какой из них является делегатом доставки звука, вы должны быть золотыми.