Playing sounds in sequence with SimpleAudioEngine

左心房为你撑大大i 提交于 2019-12-21 20:23:08

问题


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:

  1. Creates a property durationInSeconds on SimpleAudioEngine.h :

    @property (readonly) float durationInSeconds;
    
  2. Synthesize them :

    @synthesize durationInSeconds;
    
  3. 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;
        }
    }
    
  4. As you can see, I inserted durationInSeconds value directly from soundEngine bufferDurationInSeconds from the result of bufferManager.

  5. Now, only ask for the value [SimpleAudioEngine sharedEngine].durationInSeconds and you've got the float duration in seconds of this sound.

  6. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!