我如何使用cocoalibspotify的音频交叉褪色



我想在Spotify启用的应用程序中从一个轨道交叉淡出到下一个轨道。两个轨道都是Spotify轨道,并且由于一次只有一个数据流可以来自Spotify,我怀疑我需要缓冲(我认为我可以提前读取1.5倍播放速度)第一个轨道的最后几秒钟,开始流为轨道二,淡出一个和淡出两个使用AudioUnit。

我已经审查了示例应用程序:万岁- https://github.com/iKenndac/Viva SimplePlayer与EQ - https://github.com/iKenndac/SimplePlayer-with-EQ并试图让我的头脑围绕SPCircularBuffer,但我仍然需要帮助。谁能给我举个例子,或者帮我说明一下轨迹交叉游戏计划?

更新:感谢iKenndac,我大约有95%的人在那里。我将把我到目前为止的内容贴出来:

在SPPlaybackManager

。m: initWithPlaybackSession:(SPSession *) session {

补充道:

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

为crossfade启动一个计时器

crossfadeTimer = [NSTimer scheduledTimerWithTimeInterval: 0.5 .目标:自我选择器:@selector (crossfadecoundown)用户信息:零重复:是的,

为了在SPCoreAudioController中加载数据后保持第一轨播放。我更改了目标缓冲区长度:

static NSTimeInterval const kTargetBufferLength = 20;

和在SPSession。M: end_of_track(sp_session *session) {

我删除

// sess.playing = NO;

我在轨道结束前大约15秒调用preloadTrackForPlayback,然后在轨道结束前10秒调用crossfadeTrack。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

我使用:

  - (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的准确帮助!

据我所知,没有一个预先编写的crossfade示例使用了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有两个核心音频控制器,并选择其中一个是音频传递委托,你应该是黄金。

相关内容

  • 没有找到相关文章

最新更新