开发者

iPhone - start multiple instances of AVAudioPlayer simultaneously

I am using multiple instances of AVAudioPlayer to play multiple audio files simultaneously. I run a loop to start playing 开发者_JAVA百科the audio files (prepareToPlay is called beforehand and the loop only makes a call to the play method)

But invariably, one of the players does not play in sync. How can I ensure that all the 4 players start playing audio simultaneously?

Thanks.


The Apple docs talk about how you can "Play multiple sounds simultaneously, one sound per audio player, with precise synchronization". Perhaps you need to call playAtTime: e.g. [myAudioPlayer playAtTime: myAudioPlayer.deviceCurrentTime + playbackDelay];

In fact, the Apple docs for playAtTime: contain the following code snippet:

NSTimeInterval shortStartDelay = 0.01;            // seconds
NSTimeInterval now = player.deviceCurrentTime;

[player       playAtTime: now + shortStartDelay];
[secondPlayer playAtTime: now + shortStartDelay];

They should play simultaneously (assuming you choose a large enough value for shortStartDelay -- not so soon that it happens before this thread returns or whatever).


Unfortunately, you can't. AVAudioPlayer doesn't provide any mechanism for fine-grained control of start time. The currentTime property sets the point in the file to read from, it doesn't guarantee when the AVAudioPlayer instance will start playing in system time, which is what you need to sync multiple audio streams.

When I need this behavior, I use the RemoteIO Audio Unit + the 3D Mixer Audio Unit + ExtAudioFile.

EDIT

Note that as of iOS 4, you can synchronize multiple AVAudioPlayer instances using playAtTime:


This code segment of mine allows you to do this as long as you don't have to do it instantly. You can pass in the targetTime as a timestamp for when you want to hear the sounds. The trick is to make use of time-stamps and the delay functionality of NSObject. Also, it utilizes the fact that it takes way less time to change the volume of the player than it does to change the current time. Should work almost perfectly precisely.

- (void) moveTrackPlayerTo:(double) timeInSong atTime:(double) targetTime {
 [trackPlayer play];
 trackPlayer.volume = 0;

 double timeOrig = CFAbsoluteTimeGetCurrent();
 double delay = targetTime - CFAbsoluteTimeGetCurrent();
 [self performSelector:@selector(volumeTo:) 
      withObject:[NSNumber numberWithFloat:single.GLTrackVolume] 
      afterDelay:delay];
 trackPlayer.currentTime = timeInSong - delay - (CFAbsoluteTimeGetCurrent() - timeOrig);
}

- (void) volumeTo:(NSNumber *) volNumb {
 trackPlayer.volume = [volNumb floatValue];
}


Try to set same currentTime property value for every AVAudioPlayer object.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜