赞 | 9 |
VIP | 0 |
好人卡 | 0 |
积分 | 42 |
经验 | 0 |
最后登录 | 2024-11-20 |
在线时间 | 503 小时 |
Lv3.寻梦者
- 梦石
- 0
- 星屑
- 4164
- 在线时间
- 503 小时
- 注册时间
- 2011-3-26
- 帖子
- 110
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 rfvtgbzxc 于 2024-10-24 15:40 编辑
单独开一个帖子以便更新。
启用该插件后,可以解决一些游戏移植到安卓机上的问题。
修复列表:
1.地图界面/菜单界面出现黑线
2.音频模块内存优化,降低偶现loadError、切换场景时闪退的几率
3.一定程度提高动画播放性能(1.6.0以下版本,1.6.0及以上自带此优化)
关于音频加载BUG,这个BUG看到很多反馈了,也调试了很久,以目前的修复效果,能将音频相关报错限制在较低的水平(大约7、8小时一次),后续有待继续优化。
贴下排查记录:
表现:
1.音频加载有概率出现loadError,点击retry有概率重新播放,但乱序;或者闪退。
2.(安卓端)播放音频时有概率立刻闪退。
3.部分ogg不能正确循环,(1)播放结束后很久以后才开始循环 (2)开始循环的位置和音乐播放的状态不连贯
原因:
1.部分ogg,以及加密ogg不支持边下边播,加载时间超过一秒的音乐会出现解码失败bug。
复现方式:在浏览器测试中,将网络设为弱网环境(3G网速),进入任意播放音乐的场景等待1秒。
会弹出加载失败的报错。
2.Android手机端底层webview在音乐数据解析模块有bug,解析过程中可能出错,可能报错也可能闪退。
复现方式:选择一个下载好的arraybuffer,多次调用
WebAudio._context.decodeAudioData(arrayBuffer.slice())
一般一个arraybuffer调用第三次以上就会报错,连续调用六七次几乎一定会闪退。
(这个是真难试啊,关键只调用一次的话报错概率不高,代码一遍遍地跑分析情况,最后终于能稳定复现了)
3.部分ogg采样率不为44.1khz(22.05khz),但是循环标记的值总是以44.1khz为基准。
rm误将循环标记的值与ogg真实采样率相关联,导致低采样率文件的循环开始位置比预设值更靠后,循环时间长度比预设值更长。
复现方式:选择任意采样率22.05khz的音乐播放即可。
如果使用原生解码器,播放结束会进入对不上节拍的一个开始位置。
如果使用vorbisdecoder解码器,还会发现播放结束以后很久才开始重新播放,开始位置的节拍也同样对不上。
注1:“循环标记的值总是以44.1khz为基准”是一个推测,其依据如下:
ogg循环的教程很少,这是一篇文章:
https://wohlsoft.ru/pgewiki/How_To:_Looping_music_files
其中提到测算循环时间点的软件为Audacity,该软件的测算单位为“采样”时,不论文件采样率如何,其与时间的换算关系总是44.1khz。
除此之外,没有查到其他关于循环的规范,因此推测这个固定的44.1khz的循环时间单位是ogg相关软件约定俗成的。
另一个参考:在线的ogg循环测试程序
https://oggloop.vercel.app/
其源码中,也将以采样为单位的循环时间直接除以44.1k,并获得了符合预期的表现。
注2:循环标记存在于ogg音乐文件的头部,用文本格式打开ogg,会看到LOOPSTART=1136057这样的字样,这就是循环标记。
其中,LOOPSTART是循环开始标记,重复播放时会跳转到该位置开始播放
LOOPLENGTH是循环节的长度,当音乐播放到LOOPSTART+LOOPLENGTH的位置时,就会跳转到LOOPSTART的位置进行循环播放。
解决方式:
1.禁止ogg边下边播
2.解码器不走webview原生,而是走mz提供的vorbisdecoder
3.音乐下载api提供撤销能力,及时清除下载任务,避免内存溢出。
4.锁定循环标记的参考采样率为44.1khz
调试日志更新1:后续测试发现,不是bug,而是解码申请内存时,被系统拒绝了。
一首双声道44.1khz,4分钟的bgm,文件大小为7mb左右,解码为可以输出到设备的音频流时需要占据110mb+,当调用decodeAudioData()时,
一次性申请这么大的内存很容易被安卓的chrome内核拒绝。就算第一次没拒绝,chrome一个渲染进程被允许分配的内存也是相当有限的(测试估计只有不到500mb),
你再decode几次,大概率碰到内存限制而触发报错,这个时候内存也到了很危险的边缘,任何其他会进行内存分配的操作也可能被拒绝,如果错误没有被处理,就可能连报错都没有直接闪退。
在内存快照中,MZ的动画库effekseer占据30mb左右的内存,MZ内部系统也差不多占据30mb(少插件的情况),音频却能占据50~100mb内存。
因此,如果在安卓系统碰到各种报错、闪退,尤其是马上要播放音频时发生的报错,几乎可以肯定是音频这里爆内存了。
使用vorbis decoder可以将解码过程的内存压力减小(voribis会把数据分成约1mb,时长5秒的小块输出),但是MZ音频播放模块自己依然会缓存整个的解码后音频,这导致内存中时刻留着一个50~100mb的,导致闪退的定时炸弹,
在场景切换,音频切换期间,旧内存未回收,新内存存在重复开辟的行为,峰值甚至可能再翻个3倍。
如果能细化算法,播放到哪就解码到哪,将内存开销限制在1mb左右的话,闪退现象会有可以预期的大幅减少。
在PC上不存在这个问题,PC一次性分配500+mb都没事,要是分配小块的,分配4、5个gb都不是问题。
调试日志更新2:有什么是比占据100mb+的bgm更有内存压力的呢?——再加上一个占据50mb+的bgs……
即使bgs文件音频信息重复多,压缩以后可能只有几十kb,但是最后驻留内存的解码后数据是只看时长的,4分钟的bgs解码后内存直逼50mb……
流式解码势在必行。除此之外大图片也可能在解码后轻易占据15mb+的内存/显存,常规解码图片渲染也会产生很高的内存峰值容易击穿内存限制,需要压缩纹理的支持,但这涉及一个工具链的问题,一个小插件不好解决了。
目前最缺乏的还是对崩溃日志的详细解读,以确定内存限制是否是确定的,是在哪被触发的。目前的优化策略偏经验性,这些策略我们实证是有效的,闪退报错已经大幅降低,但缺乏对原理的验证。
流式解码功能后续稳定一些后会更新,提供下载。Tap上面RM游戏差评估计一半都是吐槽闪退报错问题,这插件就当对RM的基础生态做点贡献了。
AndroidFix_v0.9.0.zip
(2.4 KB, 下载次数: 57, 售价: 5 星屑)
|
|