cocos2dx中播放循环音效问题

第一次写博客,好紧张哦。嘿嘿。欢迎转载与探讨!

言归正传,今天策划提了个音效需要循环播放的需求,cocos2dx引擎本来就支持循环播放音效的,但是发现在播放循环音效之后,继续添加新的音效后,之前的循环音效没声音了。果断的看源码!!跟踪发现,原来CocosDenshion.m文件里面有个_sourceGroups的玩意,它的最大size为32,即同时只能播放32个音效,如果这个时候在加进来一个新的音效怎么办呢?它会直接替换掉当前记录index的下一个index,即如果当前index为31,新的就替换第一个音效,当前index变为0,如果当前index为20,新的特效index取21,当前index也取为21。这样就能理解最开始提出的循环特效为什么播着播着就没声音了。。。


于是怎么办呢?


后来又研究了下源码,发现

CocosDenshion.m文件中,方法-(int) _getSourceIndexForSourceGroup:(int)sourceGroupId 

中有这么一句注释:


while (!complete) {

        //Iterate over sources looking for one that is not locked, first bit indicates if source is locked

        if ((thisSourceGroup->sourceStatuses[thisSourceGroup->currentIndex] & 1) == 0) {

            //This source is not locked


说明每个index中是可以指定是否有没有锁定的,如果该index锁定了,新的音效加进来就不会占用这个index。这样就好办了, 在加入音效的时候,发现如果是循环的音效,就锁定该index,找到添加音效的地方:

- (ALuint)playSound:(int) soundId sourceGroupId:(int)sourceGroupId pitch:(float) pitch pan:(float) pan gain:(float) gain loop:(BOOL) loop {


//....省略无数 找到

if((lastErrorCode_ = alGetError()) == AL_NO_ERROR)

        {

           //加如下2句话即可!!

            [self _lockSource:sourceIndex lock:loop];         

            sourceGroup *thisSourceGroup = &_sourceGroups[sourceGroupId];           

            

            //Everything was okay

            _sources[sourceIndex].attachedBufferId = buffer;

            return source;

        } else {

            if (alcGetCurrentContext() == NULL) {

                CDLOGINFO(@"Denshion::CDSoundEngine - posting bad OpenAL context message");

                [[NSNotificationCenter defaultCenter] postNotificationName:kCDN_BadAlContext object:nil];

            }                

            return CD_NO_SOURCE;

        } 



此时循环的音效便不会被替换了,不过也有新的问题。。如果循环的音效也超过32个了怎么办呢?目前我没去处理,只能说尽量去规避这个问题。


好了,最后还需要做一下移除的处理。即主动移除的时候需要把锁定的index解锁。

如下:

- (void)stopSound:(ALuint) sourceId {

    if (!functioning_) {

        return;

    }    

    alSourceStop(sourceId);

    alGetError();//Clear error in case we stopped any sounds that couldn't be stopped

    //移除之前锁定的index

    sourceGroup *thisSourceGroup = &_sourceGroups[0];

    int size = thisSourceGroup->totalSources-1;    

    while (size>=0)

    {

        if(_sources[size].sourceId == sourceId)

        {

            [self _lockSource:size lock:NO];

            break;

        }

        size--;

    }

    alGetError();//Clear error in case we stopped any sounds that couldn't be stopped

}




同理,停止全部音效时,也需要解锁:

- (void) stopAllSounds {

    for (int i=0; i < sourceTotal_; i++) {

        alSourceStop(_sources[i].sourceId);

        //remove lock

        [self _lockSource:i lock:NO];

    }    

    alGetError();//Clear error in case we stopped any sounds that couldn't be stopped

}    


测试下来后,是可行的,不过是否有其他的隐患还待考证。。。或者有其他更好的办法也说不定,只是我目前也没找到更好的办法。


当然这个只限于mac和iOS的ping平台,安卓平台会怎么样还不知道,没试过。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值