问题
I'm building an iOS app with cocos2d 2, and I'm using SimpleAudioEngine to play some effects.
Is there a way to sequence multiple sounds to be played after the previous sound is complete?
For example in my code:
[[SimpleAudioEngine sharedEngine] playEffect:@"yay.wav"];
[[SimpleAudioEngine sharedEngine] playEffect:@"youDidIt.wav"];
When this code is run, yay.wav
and youDidIt.wav
play at the exact same time, over each other.
I want yay.wav
to play and once complete, youDidIt.wav
to play.
If not with SimpleAudioEngine, is there a way with AudioToolbox, or something else?
Thank you!
== UPDATE ==
I think I'm going to go with this method using AVFoundation:
AVPlayerItem *sound1 = [[AVPlayerItem alloc] initWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"yay" ofType:@"wav"]]];
AVPlayerItem *sound2 = [[AVPlayerItem alloc] initWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"YouDidIt" ofType:@"wav"]]];
AVQueuePlayer *player = [[AVQueuePlayer alloc] initWithItems: [NSArray arrayWithObjects:sound1, sound2, nil]];
[player play];
回答1:
The easy way would be getting the track duration using -[CDSoundSource durationInSeconds]
and then schedule the second effect playing after a proper delay:
[[SimpleAudioEngine sharedEngine] performSelector:@selector(playEffect:) withObject:@"youDidIt.wav" afterDelay:duration];
An easier way to get the audio duration would be patching SimpleAudioManager and add a method that queries its CDSoundEngine
(a static global) for the audio duration:
- (float)soundDuration {
return [_engine bufferDurationInSeconds:_soundId];
}
The second approach would be polling on the status of the audio engine and wait for it to stop playing.
alGetSourcei(sourceId, AL_SOURCE_STATE, &state);
if (state == AL_PLAYING) {
...
The sourceId
is the ALuint
returned by playEffect
.
回答2:
It's simple, tested with Cocos2D 2.1:
Creates a property durationInSeconds on SimpleAudioEngine.h :
@property (readonly) float durationInSeconds;
Synthesize them :
@synthesize durationInSeconds;
Modify playEffect like this :
-(ALuint) playEffect:(NSString*) filePath pitch:(Float32) pitch pan:(Float32) pan gain:(Float32) gain { int soundId = [bufferManager bufferForFile:filePath create:YES]; if (soundId != kCDNoBuffer) { durationInSeconds = [soundEngine bufferDurationInSeconds:soundId]; return [soundEngine playSound:soundId sourceGroupId:0 pitch:pitch pan:pan gain:gain loop:false]; } else { return CD_MUTE; } }
As you can see, I inserted durationInSeconds value directly from soundEngine bufferDurationInSeconds from the result of bufferManager.
Now, only ask for the value [SimpleAudioEngine sharedEngine].durationInSeconds and you've got the float duration in seconds of this sound.
Put a timer this seconds and after this, play the next iteration of your sound or put the flag OFF or something.
来源:https://stackoverflow.com/questions/14987061/playing-sounds-in-sequence-with-simpleaudioengine