IPhone - launch multiple instances of AVAudioPlayer simultaneously

I use multiple instances of AVAudioPlayer to play multiple audio files simultaneously. I run a loop to start playing audio files (prepareToPlay is called in advance, and the loop only calls a call to the playback method)

But invariably one of the players does not play synchronously. How can I guarantee that all 4 players will start playing sound simultaneously?

Thanks.

+4
source share
4 answers

Sorry, you can’t. AVAudioPlayer does not provide any mechanism for precise control of the start time. The currentTime property sets a point in the file for reading, this does not guarantee that the AVAudioPlayer instance will start playing at system time, which is what you need to synchronize several audio streams.

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

EDIT

Note that with iOS 4 you can sync multiple instances of AVAudioPlayer using playAtTime:

+2
source

Apple docs talk about how you can "Simultaneously play multiple sounds on the same audio player with accurate synchronization." You might need to call playAtTime: for example. [myAudioPlayer playAtTime: myAudioPlayer.deviceCurrentTime + playbackDelay];

In fact, 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 at the same time (provided that you select a sufficiently large value for shortStartDelay - not so soon that this happens before this thread returns or something else).

+3
source

This code segment allows you to do this until you need to do it instantly. You can go to targetTime as a timestamp when you want to hear sounds. The trick is to use timestamps and NSObject delay functions. In addition, he uses the fact that it takes less time to change the volume of the player than to change the current time. It should work almost perfectly.

 - (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]; } 
+1
source

Try setting the value of the currentTime property for each AVAudioPlayer object.

0
source

All Articles