Как дождаться окончания текущего звука для воспроизведения следующего звука?

Я работаю с cocos2d. Как дождаться окончания текущего звука для воспроизведения следующего звука? Я не могу сделать это с SimpleAudioEngine.


person Sveta    schedule 03.03.2011    source источник
comment
Вы спрашиваете о звуковом эффекте или фоновой музыке?   -  person Andrew    schedule 03.03.2011


Ответы (2)


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

используйте CDAudioEngine. У него есть метод, который вы хотите. Кстати, SimpleAudioEngine использует CDAudioEngine для воспроизведения звуков.

ИЗМЕНИТЬ

Когда ваша кнопка нажата в первый раз - воспроизведите звук и сохраните интервал звука в какой-то из ваших переменных. Затем в следующем щелчке используйте эту переменную, чтобы определить «достаточный интервал». Или просто используйте какой-то максимум.

EDIT 2 Если вы посмотрите на реализацию SimpleAudioEngine, то заметите, что она использует CDSoundEngine для воспроизведения звуков. Вот метод инициализации 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;
}

Таким образом, мы также можем получить доступ к CDSoundEngine:

CDSoundEngine *engine = [CDAudioManager sharedManager].soundEngine;

При вызове метода playEffect на SimpleAudioEngine (при нажатии кнопки) сохраните возвращаемый идентификатор звука.

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

Теперь мы можем получить интервал, используя наш CDSoundEngine:

float seconds = [engine bufferDurationInSeconds:soundId];

Это ответ!

Кстати, вы также можете остановить звук с помощью CDSoundEngine, если знаете идентификатор звука.

От 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

Я использую cocos2D 0.99.5.

реализация:

-(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;
    }   
}
person Andrew    schedule 03.03.2011
comment
Нет, я имею в виду, что при воспроизведении какого-то звука и при нажатии кнопки этот звук не должен воспроизводиться снова. Теперь у меня есть то, что когда я нажимаю кнопку, воспроизводится звук, а когда я снова быстро нажимаю кнопку, этот звук воспроизводится с незавершенным звуком. - person Sveta; 04.03.2011
comment
Создайте переменную NSDate в своем классе. Когда кнопка нажата, пересоздайте переменную, используя метод +data. Затем, когда ваша кнопка снова нажата, проверьте, сколько миллисекунд прошло. Если интервала достаточно - воспроизвести звук. Воссоздайте данные на текущий момент снова - person Andrew; 04.03.2011
comment
Я не могу установить достаточный интервал, потому что у меня более 100 звуков с разными интервалами. - person Sveta; 04.03.2011
comment
Можете ли вы помочь мне, как я могу получить интервал звука? - person Sveta; 04.03.2011
comment
@Andrew Эндрю, CDSoundEngine не имеет метода bufferDurationInSeconds. - person Sveta; 04.03.2011
comment
Я понимаю! Вы не представляете, в cocos2D 0.99.4 нет этой замечательной функции! :))) - person Sveta; 04.03.2011
comment
@Sveta: я добавила реализацию этой функции в свой ответ. Попробуйте добавить эту функцию в вашу версию. Но лучше обновить cocos2D - person Andrew; 04.03.2011
comment
как это вообще работает? aluint, возвращаемый playEffect, полностью отличается от того, что используется в bufferDurationInSeconds. - person devmiles.com; 20.06.2013
comment
@devmiles.com: вы используете кокосы 0.99.5? - person Andrew; 20.06.2013
comment
я использую 2.0, но это не имеет значения, потому что это все равно не сработает, и вы, очевидно, никогда не пытались запустить свой код. Вот правильный способ найти длину звука: stackoverflow.com/questions/15581225/ - person devmiles.com; 20.06.2013
comment
@devmiles.com: Мне все равно, проголосуете ли вы за или против ответа, но неразумно говорить, что это неправильно, если вы используете другую (на самом деле гораздо более высокую) версию библиотеки. - person Andrew; 20.06.2013
comment
эй, это тоже не способ воспринимать критику. он не работает в 0.99 или где-то еще, потому что это противоречит основам звукового движка Apple. - person devmiles.com; 20.06.2013

// Проиграть звук Aluint soundID = [[SimpleAudioEngine sharedEngine] playEffect:@"sound.mp3"];

// чтобы остановить звук, вам нужно использовать тот же soundID при его воспроизведении [[SimpleAudioEngine sharedEngine] stopEffect:soundID];

person Emmy    schedule 12.03.2011
comment
Я знаю этот метод. По-моему я не могу его использовать. - person Sveta; 14.03.2011