4

I'm working with cocos2d. How to wait finish current audio for playing next audio? I can't make it with SimpleAudioEngine.

Guru
  • 21,652
  • 10
  • 63
  • 102
Sveta
  • 1,270
  • 3
  • 16
  • 33

2 Answers2

3

http://www.cocos2d-iphone.org/api-ref/0.99.0/interface_c_d_sound_engine.html

use CDAudioEngine. It have the method you want. By the way SimpleAudioEngine is using CDAudioEngine to play sounds.

EDIT

When your button is clicked first time - play the sound and save the sound's interval to some of your lass variable. Then in next click use this variable to determine the "enough interval". Or just use some maximum.

EDIT 2 If you'll take a look at SimpleAudioEngine implementation you will notice that it's using CDSoundEngine to play sounds. Here is the init method of SimpleAudioEngine:

static SimpleAudioEngine *sharedEngine = nil;
static CDSoundEngine* soundEngine = nil;
static CDAudioManager *am = nil;
static CDBufferManager *bufferManager = nil;


-(id) init
{
    if((self=[super init])) {
        am = [CDAudioManager sharedManager];
        soundEngine = am.soundEngine;
        bufferManager = [[CDBufferManager alloc] initWithEngine:soundEngine];
        mute_ = NO;
        enabled_ = YES;
    }
    return self;
}

So we can also access to CDSoundEngine:

CDSoundEngine *engine = [CDAudioManager sharedManager].soundEngine;

When calling playEffect method on SimpleAudioEngine (when your button is clicked) save the returned sound id.

ALuint soundId = [[SimpleAudioEngine sharedEngine] playEffect:...];

Now we can get the interval using our CDSoundEngine:

float seconds = [engine bufferDurationInSeconds:soundId];

That's the answer!

By the way you can also stop a sound with CDSoundEngine if you know the sound id.

From CocosDenshion.h

@class CDSoundSource;
@interface CDSoundEngine : NSObject <CDAudioInterruptProtocol> {

    bufferInfo      *_buffers;
    sourceInfo      *_sources;
    sourceGroup     *_sourceGroups;
    ALCcontext      *context;
    int             _sourceGroupTotal;
    UInt32          _audioSessionCategory;
    BOOL            _handleAudioSession;
    BOOL            mute_;
    BOOL            enabled_;
    ALfloat         _preMuteGain;

    ALenum          lastErrorCode_;
    BOOL            functioning_;
    float           asynchLoadProgress_;
    BOOL            getGainWorks_;

    //For managing dynamic allocation of sources and buffers
    int sourceTotal_;
    int bufferTotal;

}

@property (readwrite, nonatomic) ALfloat masterGain;
@property (readonly)  ALenum lastErrorCode;//Last OpenAL error code that was generated
@property (readonly)  BOOL functioning;//Is the sound engine functioning
@property (readwrite) float asynchLoadProgress;
@property (readonly)  BOOL getGainWorks;//Does getting the gain for a source work
/** Total number of sources available */
@property (readonly) int sourceTotal;
/** Total number of source groups that have been defined */
@property (readonly) int sourceGroupTotal;

/** Sets the sample rate for the audio mixer. For best performance this should match the sample rate of your audio content */
+(void) setMixerSampleRate:(Float32) sampleRate;

/** Initializes the engine with a group definition and a total number of groups */
-(id)init;

/** Plays a sound in a channel group with a pitch, pan and gain. The sound could played looped or not */
-(ALuint) playSound:(int) soundId sourceGroupId:(int)sourceGroupId pitch:(float) pitch pan:(float) pan gain:(float) gain loop:(BOOL) loop;

/** Creates and returns a sound source object for the specified sound within the specified source group.
 */
-(CDSoundSource *) soundSourceForSound:(int) soundId sourceGroupId:(int) sourceGroupId;

/** Stops playing a sound */
- (void) stopSound:(ALuint) sourceId;
/** Stops playing a source group */
- (void) stopSourceGroup:(int) sourceGroupId;
/** Stops all playing sounds */
-(void) stopAllSounds;
-(void) defineSourceGroups:(NSArray*) sourceGroupDefinitions;
-(void) defineSourceGroups:(int[]) sourceGroupDefinitions total:(int) total;
-(void) setSourceGroupNonInterruptible:(int) sourceGroupId isNonInterruptible:(BOOL) isNonInterruptible;
-(void) setSourceGroupEnabled:(int) sourceGroupId enabled:(BOOL) enabled;
-(BOOL) sourceGroupEnabled:(int) sourceGroupId;
-(BOOL) loadBufferFromData:(int) soundId soundData:(ALvoid*) soundData format:(ALenum) format size:(ALsizei) size freq:(ALsizei) freq;
-(BOOL) loadBuffer:(int) soundId filePath:(NSString*) filePath;
-(void) loadBuffersAsynchronously:(NSArray *) loadRequests;
-(BOOL) unloadBuffer:(int) soundId;
-(ALCcontext *) openALContext;

/** Returns the duration of the buffer in seconds or a negative value if the buffer id is invalid */
-(float) bufferDurationInSeconds:(int) soundId;
/** Returns the size of the buffer in bytes or a negative value if the buffer id is invalid */
-(ALsizei) bufferSizeInBytes:(int) soundId;
/** Returns the sampling frequency of the buffer in hertz or a negative value if the buffer id is invalid */
-(ALsizei) bufferFrequencyInHertz:(int) soundId;

/** Used internally, never call unless you know what you are doing */
-(void) _soundSourcePreRelease:(CDSoundSource *) soundSource;

@end

I'm using cocos2D 0.99.5

implementation:

-(float) bufferDurationInSeconds:(int) soundId {
    if ([self validateBufferId:soundId]) {
        float factor = 0.0f;
        switch (_buffers[soundId].format) {
            case AL_FORMAT_MONO8:
                factor = 1.0f;
                break;
            case AL_FORMAT_MONO16:
                factor = 0.5f;
                break;
            case AL_FORMAT_STEREO8:
                factor = 0.5f;
                break;
            case AL_FORMAT_STEREO16:
                factor = 0.25f;
                break;
        }   
        return (float)_buffers[soundId].sizeInBytes/(float)_buffers[soundId].frequencyInHertz * factor;
    } else {
        return -1.0f;
    }   
}
Andrew
  • 24,218
  • 13
  • 61
  • 90
  • No, I mean that while play some sound and when I press button, this sound must not play again. Now I have that when I press button, sound is playing and when I press button again fastly, this sound playing with unfinished this sound. – Sveta Mar 04 '11 at 06:19
  • Create a NSDate variable in your class. When the button is pressed recreate the variable using +data method. Then when your button is pressed again check how many milliseconds elapsed. If the interval is enough - play sound. Recreate the data to current moment again – Andrew Mar 04 '11 at 08:06
  • I can't set enough interval, because I have more than 100 sounds with different interval. – Sveta Mar 04 '11 at 08:34
  • Can you help me how can I get sound's interval? – Sveta Mar 04 '11 at 08:39
  • @Andrew, CDSoundEngine doesn't have method bufferDurationInSeconds. – Sveta Mar 04 '11 at 09:17
  • I see! You can't amagine, there is no this great function in cocos2D 0.99.4! :))) – Sveta Mar 04 '11 at 09:41
  • @Sveta: I've added the implementation of this function to my asnwer. Try to add this function to your version. But better update cocos2D – Andrew Mar 04 '11 at 09:46
  • how this even works? aluint returned by playEffect is totally different from what's used in bufferDurationInSeconds – devmiles.com Jun 20 '13 at 12:40
  • @devmiles.com: do you use cocos 0.99.5 ? – Andrew Jun 20 '13 at 12:50
  • i'm using 2.0 but it doesn't matter because it wouldn't work anyway and you obviously never tried to run your code. Here's a proper way to find sound length: http://stackoverflow.com/questions/15581225/how-to-detect-when-sound-effect-finish-playing – devmiles.com Jun 20 '13 at 13:03
  • @devmiles.com: I don't care if you up or downvote the answer, but it is not smart to say its wrong if you use different (much higher actually) version of the library. – Andrew Jun 20 '13 at 13:19
  • hey, that's not the way to take criticism either. it's not working in 0.99 or anything else, because it contradicts with apple sound engine foundations. – devmiles.com Jun 20 '13 at 14:39
0

// to Play the sound Aluint soundID = [[SimpleAudioEngine sharedEngine] playEffect:@"sound.mp3"];

// to stop the sound you need to use the same soundID when you play it [[SimpleAudioEngine sharedEngine] stopEffect:soundID];

Emmy
  • 1