2

我有一个包含简介 (0:00-0:10) 和循环部分 (0:10-0:30) 的音乐文件。有许多库和简单的解决方案可以从 end->beginning 循环曲目,但是我很难找到一种从 end->loop start 循环曲目的方法。实现这一目标的最佳方法是什么?

这是我目前根据以下评论使用的代码。循环时它仍然会产生一个小间隙:

_player = [AVPlayer playerWithURL:url];
Float64 durationSeconds = CMTimeGetSeconds([asset duration]);
CMTime loopStart = CMTimeMakeWithSeconds(19.2, 1);
CMTime loopEnd = CMTimeMakeWithSeconds(durationSeconds, 1);
NSArray *times = @[[NSValue valueWithCMTime:loopEnd]];

__weak typeof(AVPlayer *)weakPlayer = _player;
self.playerObserver = [_player addBoundaryTimeObserverForTimes:times queue:NULL usingBlock:^{
    [weakPlayer seekToTime:loopStart];
}];

[_player play];
4

2 回答 2

1

如果您可以从 AVAudioPlayer 切换到 AVPlayer,则可以使用addBoundaryObserverForTimes:.

文档

在正常播放期间遍历指定时间时请求调用块。

AV Foundation Programming Guide 对如何使用此方法进行了代码示例的说明:Tracking Time

于 2013-08-22T09:18:31.237 回答
0

最后,ObjectAL 有一个演示项目,它使用两个单独的音频文件来播放和介绍,然后循环播放歌曲的主体,而不会出现播放间隙。我已将其修改为使用单个音频文件:

+(ALBuffer *)bufferFromFile:(NSString *)filePath startTime:(float)startTime endTime:(float)endTime
{
    NSURL *url = [OALTools urlForPath:filePath];
    OALAudioFile *file = [[OALAudioFile alloc] initWithUrl:url reduceToMono:NO];

    // Convert the start and end times into frames
    NSInteger startFrame = startTime*file.streamDescription->mSampleRate;
    NSInteger endFrame = (endTime-startTime)*file.streamDescription->mSampleRate;///file.totalFrames-(endTime*file.streamDescription->mSampleRate);

    ALBuffer* buffer = [file bufferNamed:[url description]
                              startFrame:startFrame
                               numFrames:endFrame];
    //as_release(file); // I've commented this out, but I suspect there may be some kind of leak here. Can anyone comment on how to properly release this memory?
    return buffer;
}

-(void)playBackgroundMusic:(NSString *)file withIntroThatLoopsAt:(CGFloat)seconds
{
    // Uses OpenAL for both the intro and the main loop.
    // Uses a callback to start the main loop playing.
    // Note: This only works on iOS 5+.

    _source = [ALSource source];
    _introBuffer= [JAudioEngine bufferFromFile:file startTime:0 endTime:seconds];
    _mainBuffer = [JAudioEngine bufferFromFile:file startTime:seconds endTime:-1];

    [self stop];

    __block typeof(self) blockSelf = self;
    [_source registerNotification:AL_BUFFERS_PROCESSED
                             callback:^(__unused ALSource *source, __unused ALuint notificationID, __unused ALvoid *userData)
                             {
                                 [blockSelf.source play:blockSelf.mainBuffer loop:YES];
                                 [blockSelf.source unregisterAllNotifications];
                             }
                             userData:nil];

    [_source play:_introBuffer];
}

-(void)stop
{
    [_source unregisterAllNotifications];
    [_source stop];
}
于 2013-09-08T03:34:00.070 回答