我有一个音乐文件,其中包含一个介绍(0:00-0:10)和一个循环部分(0:10-0:30)。有很多库和简单的解决方案可以从end-gt;开始循环一个音轨,但是我很难找到一种从end->循环开始循环音轨的方法。实现这一目标的最佳方法是什么?
这是我目前使用的代码,基于以下评论。它在循环时仍然会产生一个小的差距:
_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];
答案 0 :(得分:1)
如果您可以从AVAudioPlayer切换到AVPlayer,则可以使用addBoundaryObserverForTimes:
。
来自docs:
遍历指定时间时请求调用块 在正常播放期间。
“AV基础编程指南”解释了如何使用此方法的代码示例:Tracking Time
答案 1 :(得分: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];
}