cocos2dx 3.x audioEngine 发现的播放声音的几个bug

背景描述:
我们的游戏采用cocos2dx2.2.2版本开发,ios端 ,声音引擎是simple那个,发生了诡异的问题,比如切后台,再回来,背景音乐得等一段时间才有声音,或者音效没声音了,找了半天无解,看到3.x以后采用了新的AudioEngine,于是拿cocos2dx3.8版本声音引擎做了替换。并进行了简单的修改(3.x和2.x中类型名字不同等),解决编译问题和引入c++11。(我们的音效,背景音乐,都使用的caf格式)
我这里有个自己实现的外部播放管理类,来进行音乐,音效关于是不是可以覆盖,可以循环加以控制。

发现bug描述:
1.在ios端,采用新引擎,确实解决了之前simple引擎遇到的诡异问题,但是在播放背景音乐时候(AudioEngine都是用的一个播放机制,这里区分背景音乐与音效是用音频的长短,我们的音效大概<=1s,音乐30s~1min),并且这个音乐播放时候设置为可以循环的,有很大几率在播放完成一次的时候循环这个声音,没有声音了,但是看代码,AudioPlayer::rotateBufferThread,中,这个线程依然一直存在,播放短的音频,却可以一直循环出声,未解
我使用了一种方式,规避了这个bug,不采用引擎中的循环,在上一个背景音乐播完之后,在外部自己写逻辑中重新播这个文件。

2.在android端,比如类似,点按钮,或者游戏中逻辑相关的需要同时或者可能同时播放多个音效,会出现线程锁死的问题,整个游戏都卡住了,

04-13 19:41:39.978 11842-14678/com.anansimobile.pnk.base E/libOpenSLES: frameworks/wilhelm/src/android/AudioPlayer_to_android.cpp:412: pthread_mutex_lock_timeout_np returned 110
04-13 19:41:40.078 11842-14678/com.anansimobile.pnk.base E/libOpenSLES: frameworks/wilhelm/src/android/AudioPlayer_to_android.cpp:412: pthread_mutex_lock_timeout_np returned 110
ios上是cocos2dx中实现的多线程,然后用openal播声音,android上是直接用opensles,里面自己多线程吗,
尝试找相关问题,https://github.com/cocos2d/cocos2d-x/pull/11762,这里的解决方案,跟github上最新的代码是一致的,我把它导过来了,依然是会有几率出现锁死。并没有解决。

3.在android端,同样是同时播放多个声音,有比较大几率会出现AudioEngine 中_audioIDInfoMap.size() 这个map的数量会被加上去,但是没有减回来(使用的是github上最新的说是解决了死锁问题的代码),在 AudioEngineImpl::update 中,_audioPlayers 的数量也没有减下来,并且一直存在的那几个,他们的状态一直也没有变成_playOver , 一直在update里循环着。。。。在外部有个与这个map逻辑数量相对应的链表,跟它的数量一样,这样就会导致,过一会,_audioIDInfoMap.size()就会超过24个,新的声音就不会再播放了,。
和ios上比外部代码都一样,但是ios就不会出现这个问题。这个问题我觉得可能也是其他人说的播声音播着播着越来越卡,内存没释放外加opensl里起了多个线程?

上传个附件,是我在外面写的控制具体播放逻辑的代码,大概意思是,区分音乐和音效,都是可以delay一段时间播放,也可以马上播放,音效区分同一个音乐文件同时播放时是覆盖还是不覆盖,如果覆盖的话,将之前已经播放的声音stop掉(很有可能是这个逻辑导致的线程死锁?),里面用的数组是对应的音频文件的名字

最后ios上遇到的问题,通过规避的方式,没有出现其他问题了。
但是android上这个实在没法规避,也没google到合适的解决方案。自己调查也是能力有限,只能先分析成这样,希望有遇到同样问题解决了的船友帮忙看下。。我们的小船不能说翻就翻啊~~~~~~~

出现问题的测试机器,Nexus6   , Android 6.0

问题2 是多次停止某循环音效引起的,在停止前setLoop false,能避免游戏卡死

有简单的必现方法吗?

UIScrollView在滑动的时候也有bug,会导致按钮点击错误的,我写了一个帖子有解决办法

@q270274978 我看了一下代码,为了解决OpenSL ES Destroy() 卡死的问题,所以引擎使用了update来延迟释放player,现在的设置是0.5秒。延迟释放只能是缓解卡死问题,应该是无法根本解决,但是也没有别的办法。

这个从逻辑来看是不会的,因为_audioIDInfoMap在stop时是直接清除的,只是内部的AudioPlayer没有释放,所以会导致无法播放。问题也是因为上面的延迟释放导致的。

我搜索了这个问题,得到的答案应该是说后续的Android版本解决了Destroy卡死的问题,但是还没有找到具体的版本。因为引擎需要支持的版本是2.3+,所以估计也只能是对不同版本做不同处理了。