最近在使用cocos开发小游戏的时候,出现了一个BUG
现象:游戏过程中调用录音机以后,再次调用cc.SimpleAudioEngine:getInstance():playEffect 很大概率出现不能播放,android log日志如下
0-12 18:18:01.724 262-262/? I/SurfaceFlinger: FPS: 56
10-12 18:18:01.849 1138-1161/com.turing.turingwatchgame D/cocos2d-x debug info: [LUA-print] audio/enemy4.mp3
10-12 18:18:01.870 1138-1161/com.turing.turingwatchgame W/AudioTrack: dead IAudioTrack, PCM, creating a new one from start()
10-12 18:18:01.885 1138-1161/com.turing.turingwatchgame E/AudioTrack: detected illegal retrograde motion by the server: mServer advanced by -882
10-12 18:18:01.886 353-5271/? E/AudioPolicyManager: unknown stream type 13
unknown stream type 13
unknown stream type 13
unknown stream type 13
unknown stream type 13
unknown stream type 13
unknown stream type 13
10-12 18:18:01.887 353-5271/? E/AudioPolicyManager: unknown stream type 13
unknown stream type 13
unknown stream type 13
10-12 18:18:01.891 353-858/? D/audio_hw_primary: start_output_stream: enter: stream(0xb83f6cd0)usecase(0: deep-buffer-playback) devices(0x2)
10-12 18:18:01.891 1138-1161/com.turing.turingwatchgame D/cocos2d-x debug info: [LUA-print] ------lua log:ffffffffffffffffffffffffffffffffffffff
10-12 18:18:01.891 353-858/? D/audio_hw_primary: select_devices: out_snd_device(2: speaker) in_snd_device(0: )
10-12 18:18:01.891 353-858/? D/hardware_info: hw_info_append_hw_type : device_name = speaker
10-12 18:18:01.897 353-858/? W/audio_hw_utils: audio_extn_utils_update_stream_app_type_cfg: App type could not be selected. Falling back to default
10-12 18:18:01.897 353-858/? I/audio_hw_primary: select_devices Selected apptype: 69936
10-12 18:18:01.897 353-858/? E/audio_hw_dolby: audio_extn_dolby_ds2_set_endpoint: Dolby set endpint :0x2
10-12 18:18:01.897 353-858/? D/ACDB-LOADER: ACDB -> send_audio_cal, acdb_id = 14, path = 0
ACDB -> send_asm_topology
ACDB -> ACDB_CMD_GET_AUDPROC_STREAM_TOPOLOGY_ID
10-12 18:18:01.898 353-858/? D/ACDB-LOADER: ACDB -> send_adm_topology
ACDB -> ACDB_CMD_GET_AUDPROC_COMMON_TOPOLOGY_ID
ACDB -> send_audtable
ACDB -> ACDB_CMD_GET_AUDPROC_COMMON_TABLE
ACDB -> AUDIO_SET_AUDPROC_CAL
ACDB -> send_audvoltable
ACDB -> ACDB_CMD_GET_AUDPROC_GAIN_DEP_STEP_TABLE
10-12 18:18:01.899 353-858/? D/ACDB-LOADER: ACDB -> AUDIO_SET_AUDPROC_VOL_CAL
ACDB -> send_afe_cal
ACDB -> ACDB_CMD_GET_AFE_COMMON_TABLE
10-12 18:18:01.899 353-858/? E/ACDB-LOADER: Error: ACDB AFE returned = -19
10-12 18:18:01.899 353-858/? D/ACDB-LOADER: ACDB -> AUDIO_SET_AFE_CAL
ACDB -> send_hw_delay : acdb_id = 14 path = 0
10-12 18:18:01.900 353-858/? D/ACDB-LOADER: ACDB -> ACDB_AVSYNC_INFO: ACDB_CMD_GET_DEVICE_PROPERTY
10-12 18:18:01.900 353-858/? I/audio_hw_utils: audio_extn_utils_send_app_type_cfg app_type 69936, acdb_dev_id 14, sample_rate 48000
10-12 18:18:01.901 353-858/? D/audio_hw_primary: select_devices: done
分析过程:
- 查看报错日志出处,查询android 源码android源码搜索,最终看到代码出处:
Modulo<uint32_t> AudioTrack::updateAndGetPosition_l()
2232{
2233 // This is the sole place to read server consumed frames
2234 Modulo<uint32_t> newServer(mProxy->getPosition());
2235 const int32_t delta = (newServer - mServer).signedValue();
2236 // TODO There is controversy about whether there can be "negative jitter" in server position.
2237 // This should be investigated further, and if possible, it should be addressed.
2238 // A more definite failure mode is infrequent polling by client.
2239 // One could call (void)getPosition_l() in releaseBuffer(),
2240 // so mReleased and mPosition are always lock-step as best possible.
2241 // That should ensure delta never goes negative for infrequent polling
2242 // unless the server has more than 2^31 frames in its buffer,
2243 // in which case the use of uint32_t for these counters has bigger issues.
2244 ALOGE_IF(delta < 0,
2245 "detected illegal retrograde motion by the server: mServer advanced by %d",
2246 delta);
2247 mServer = newServer;
2248 if (delta > 0) { // avoid retrograde
2249 mPosition += delta;
2250 }
2251 return mPosition;
2252}
但是为什么是负数,感觉很奇怪啊,很大一个原因就是之前的audio track对象没有释放导致的。
2. 接着就考虑在play之前调用cc.SimpleAudioEngine:getInstance():stopAllEffect()
3. 事实上调用了该方法以后,确实可用了。
后来同事说,如果出现音效需要叠加的需求,就会出问题。虽然可能性不大,但是为了更好的满足需求,还是想想其他的解决方案。最终发现cocos还有另外一个audio播放api,
ccexp.AudioEngine:play2d ,尝试了一下,也可以。( Ĭ ^ Ĭ )
这就是一个问题的完整解决过程,看似短暂,其实耗费了不少的时间,这里总结一下,防止后来人踩坑。