# 0x01 前言
之前虽然有用过,但是并没有对其做个人的整理与总结,只大概知道哪个选项会造成什么情况,此处进行一次详尽的实际测试并总结。
# 0x02 工具
- Unity2021.3.6f1
- UnityProfiler
- 音效:
# 0x03 设置选项
# 1. LoadType
分为三个选项,这个选择比较重要:直接决定音效在内存中的大小。
# 1). 加载即解压 (Decompress On Load)
性能最好,不过会占用更多内存。
在内存中的大小至少是选择 PCM 压缩格式在 ImportedSize 的预览大小 —— 因为在选择 Vorbis 后,再选择解压到内存会多一些。
分别查看设置对应压缩格式后,Imported Size 以及利用 Profiler 查看运行时内存大小。
对比如下:
- PCM:
Imported Size:306KB
运行时内存:309.6KB (+3.6KB) - ADPCM:
Imported Size:86.2KB
运行时内存:310.1KB (+4KB) - Vorbis (1% 质量):
Imported Size:13.9KB
运行时内存:343.2KB (+37.2KB) - Vorbis (70% 质量):
Imported Size:16.6KB
运行时内存:345.7KB (+39.7KB) - Vorbis (100% 质量):
Imported Size:22.9KB
运行时内存:348.1KB (+42KB)
采样率设置为 22050Hz:
- PCM:
Imported Size:153.1KB
运行时内存:156.7KB (+3.6KB) - ADPCM:
Imported Size:43.1KB
运行时内存:157.1KB (+4KB) - Vorbis (1% 质量):
Imported Size:7.6KB
运行时内存:192.9KB (+40KB) - Vorbis (70% 质量):
Imported Size:9.5KB
运行时内存:192.9KB (+40KB) - Vorbis (100% 质量):
Imported Size:12KB
运行时内存:192.9KB (+40KB)
Decompress On Load 模式下,在内存中的音效大小与 PCM 的 ImportedSize 显示的大小差不多,其中 PCM 和 ADPCM 在这个基础上多了几 KB,可能是其它数据。
而当 Vorbis 压缩格式采用 Decompress On Load 则会导致更多的额外内存消耗,平均 40KB 左右。且会随着质量设置越高而增加。,见下方『注 1』,推测为音效源文件 44100Hz 有不一致的地方,手动设置为更低采样率后保存一致。
# 2). 压缩格式存放在内存 (Compressed In Memory)
播放时会额外消耗 CPU 解压,内存情况测试如下:
Original Size:32.8KB
- PCM:
Imported Size:306KB
运行时内存:309.7KB (+3.7KB) - ADPCM:
Imported Size:86.2KB
运行时内存:90.7KB (+4.5KB) - Vorbis (1% 质量):
Imported Size:13.9KB
运行时内存:39.1KB (+25.2KB) - Vorbis (70% 质量):
Imported Size:16.6KB
运行时内存:44.1KB (+27.5KB) - Vorbis (100% 质量):
Imported Size:22.9KB
运行时内存:52.9KB (+30KB)
采样率设置为 22050Hz:
- PCM:
Imported Size:306KB
运行时内存:309.7KB (+3.7KB) - ADPCM:
Imported Size:86.2KB
运行时内存:90.7KB (+4.5KB) - Vorbis (1% 质量):
Imported Size:7.6KB
运行时内存:35.3KB (+27.7KB) - Vorbis (70% 质量):
Imported Size:9.5KB
运行时内存:37.3KB (+27.7KB) - Vorbis (100% 质量):
Imported Size:12KB
运行时内存:39.8KB (+27.7KB)
通过测试可以看出:
Compressed In Memory 模式下,PCM 和 ADPCM 下内存占用情况为预览面板的 ImportedSize + 几 KB,总体上差不多。
Vorbis 压缩模式会额外占用更多内存 (大概多了 30KB 左右)。且会随着质量设置越高而增加。,见下方『注 1』,推测为音效源文件 44100Hz 有不一致的地方,手动设置为更低采样率后保存一致。
# 3). 流式播放 (Streaming)
流式播放占用内存相对整个文件来说比较少 —— 前提是音效文件本身大于 200KB,根据官方文档介绍,就算小于 200KB 的音效,采用流式播放也会产生 200KB 左右的缓存消耗。
坏处是播放的时候对 IO、CPU 都会有额外开销。
以上述两个音效文件为例,当设置一致 (SampleRateSetting 为 PreserveSampleRate [44100Hz]),并采用流式播放时结果如下:
- PCM:197.7KB
- ADPCM:198KB
- Vorbis (1% 质量):231.3KB
- Vorbis (70% 质量):233.8KB
- Vorbis (100% 质量):236.2KB
Vorbis 下会多 30KB 左右,且受质量设置影响 (比较小)
质量影响量太小了,尝试手动设置一下 Sample Rate 为 44100Hz:
- PCM:197.7KB
- ADPCM:198KB
- Vorbis (1% 质量):231.3KB
- Vorbis (70% 质量):233.8KB
- Vorbis (100% 质量):236.2KB
发现同一采样率下,缓存内存占用量没有变化,另外选择 Optimiz SampleRate 也是同样的内存占用结果。
依然以上述两个音效为例,将 Sample Rate 手动设置为 22050Hz:
- PCM:163.7KB
- ADPCM:164KB
- Vorbis (1% 质量):199.9KB
- Vorbis (70% 质量):199.9KB
- Vorbis (100% 质量):199.9KB
可以看到,Vorbis 下依然会多 30KB 左右,但是质量选择已经没有影响了。
接着缓存 8000Hz 的 Sample Rate:
- PCM:141.7KB
- ADPCM:142KB
- Vorbis (1% 质量):167.9KB
- Vorbis (70% 质量):167.9KB
- Vorbis (100% 质量):167.9KB
可以得出结论:Streaming 播放音效时,至少会产生 140KB (最低 8000Hz 采样率) 左右的内存缓存,Vorbis 压缩格式下会额外增加 30KB 左右的消耗。
采样率 (越低内存占用越低)、强制单声道也会统一影响到三种设置在流式的缓存占用),
注 1:上述 44100Hz 采样率时,Vorbis 压缩下内存占用会有微小差异,同样适用于 Decompress On Load、Compressed In Memory,推测是音效源文件的采样率部分不一致导致,因为手动设置为更低采样率后就保持一致了。
# 2. Compression Format (压缩格式)
- PCM:不压缩,效果最好文件最大,试过甚至比导入音效本身文件都还大
- ADPCM:有一定压缩效果,压缩率视情况音效源文件而定,经过测试一般在 50%~80% 浮动,也可能比源文件大小更大。
- Vorbis/Mp3:压缩率最高的方式,唯一确定一定能压缩大小的选项,该选项还可以额外设置 Quality,值越小,压缩越厉害,大小也越小
# 3. Force To Mono
强制单声道,例如下图:
这个音效就包含了 ch1、ch2 两个声道,若勾选该项,两个声道将会合并为一个,并减少一部分大小。
测试结果:
文件 1:
- PCM:153.1KB->76.6KB(50%)
- ADPCM:43.1KB->21.6KB(50%)
- Vorbis(1%):7.6KB->6.4KB(15%)
- Vorbis(100%):12KB->9.8KB(18%)
文件 2:
- PCM:9.6MB->4.8MB(50%)
- ADPCM:2.7MB->1.4MB(50%)
- Vorbis(1%):0.6MB->426.3KB(30%)
- Vorbis(100%):2.8MB->0.6MB(80%)
通过对两个音效文件:一个大文件及一个小文件对比,可以得出结论:
强制单声道选项中,PCM 和 ADPCM 的格式可以减少 50% 大小,Vorbis 视压缩质量及音效本身大小而定 —— 这个应该跟音效本身两个通道数据量有关,文件 2 实测双通道声音会有更大的差异。
注:单声道并不是说只有一个喇叭会播放声音,而是两个喇叭播放同样的声音。
# 4. Sample Rate
采样率,在不影响效果的情况,还可以考虑设置统一的更低的采样率,也会影响大小。
对于影响效果,测试结果如下:
- PCM(44100Hz):306KB->153.1KB(22050Hz)->76.6KB(11025Hz)->55.6KB(8000Hz)
- ADPCM(44100Hz):86.2KB->43.1KB(22050Hz)->21.6KB(11025Hz)->15.7KB(8000Hz)
- Vorbis(1%)(44100Hz):13.9KB->7.6KB(22050Hz)->8.7KB(11025Hz)->6.1KB(8000Hz)
- Vorbis(100%)(44100Hz):22.9KB->12KB(22050Hz)->11.8KB(11025Hz)->8.8KB(8000Hz)
从上述测试结果可以看出,采样率对内存占用影响成比例关系:减少多少采样率,相对就减少多少空间。
我们游戏音效导入默认是 44100Hz ,就是统一将其设置为 22050Hz,相比初始默认的 44100Hz,减少一半占用,Vorbis 压缩有部分浮动,不过也大体符合规则。
# 5. Preload Audio Data
根据说明,是会在场景加载时预先加载,默认开启的,适用于那种直接拖到 GameObject 上的音效,过多估计会影响场景加载速度。
一般最好关了,因为我们都是代码动态加载播放,场景不会直接挂。所以这个选项实际上没用。
# 6. Load In Background
在单独线程延迟加载,不卡主线程,但是这个选项或许会造成音画不同步。
# 0x04 总体资源消耗测试
上面在单项设置中,分别对比过各自会在内存中的占用量,此处将对 内存、CPU 消耗作一个总体对比。
对于如何测试 CPU 性能的消耗,由于单个音效的播放时很不明显,因此我在测试时采用 20 份播放同一个音效的 AudioSource,并对比总消耗、使用 Profiler 检查每个设置对 CPU 消耗造成的影响,取平均出现最多的值。
同时为了减少内存误差,测试文件更换了一个更大的音效,OriginalSize 为 2.8MB。
其默认测试设置如下:
# 1) 压缩格式:Vorbis (1% 质量)
从左自右 LoadType 分别为: Decompress On Load、Compress In Memery、Streaming
CPU 消耗:1%->2.5%->2.8%
内存消耗:7.3MB->2.8MB->5.9MB
# 2) 压缩格式:Vorbis (100% 质量)
从左自右 LoadType 分别为: Decompress On Load、Compress In Memery、Streaming
CPU 消耗:1%->4.9%->5%
内存消耗:7.3MB->3.7MB->5.9MB
# 3) 压缩格式:ADPCM
从左自右 LoadType 分别为: Decompress On Load、Compress In Memery、Streaming
CPU 消耗:1%->1.8%->2.1%
内存消耗:7.2MB->3.8MB->5.6MB
# 4) 压缩格式:PCM
从左自右 LoadType 分别为: Decompress On Load、Compress In Memery、Streaming
CPU 消耗:1%->1.1%->1.4%
内存消耗:7.2MB->7.2MB->5.6MB
# 5) 总结
上述测试结果中,感觉其中 Streaming Vorbis 内存占用与预计的有点不符,于是使用单 AudioSource 额外进行测试:
Streaming 播放模式,从左自右分别为:Vorbis (100% 质量)->Vorbis (1% 质量)->ADPCM->PCM
CPU 消耗:0.5%->0.5%->0.4%->0.3%
内存消耗:2.6MB->2.6MB->2.5MB->2.5MB
Vorbis 压缩格式,在 Streaming 下 Taotal Audio Memery 消耗多了 100KB 的样子,而在上面使用 Take Sample 单个查看时只额外多了 30KB 内存占用。
这里只能推测两个原因:
- 要么 Taotal Audio Memery 还计算了其它数据
- 要么由于统计没有显示具体 KB 消耗值导致的误认 (例如 PCM 原本为 2.57MB 一类,加上 30KB 左右就到 2.6MB 了)。
另外需要注意的是,Streaming 播放模式下,会随着通同一个文件的反复加载,而叠加文件流及解码内存消耗 —— 例如上述单个播放为 124KB->20 个 = 124KBx20=2.4MB
# 总体内存消耗:
Decompress On Load:Vorbis 额外 30KB 左右内存消耗,总体差不多
Compress In Memery:PCM->ADPCM->Vorbis (100% 质量)->Vorbis (1% 质量)
Streaming:Vorbis 额外几十 KB 内存消耗,总体差不多
# 总体 CPU 消耗:
Decompress On Load:CPU 消耗基本一致
Compress In Memery:Vorbis (100% 质量)->Vorbis (1% 质量)->ADPCM->PCM
Streaming:Vorbis (100% 质量)->Vorbis (1% 质量)->ADPCM->PCM
# 疑问
对于总体内存消耗,或许会有疑问(比如说我自己):在测试单个音效播放时,Profiler Audio 面板中的 Total Audio Memery 的内存数值,比 Profiler Memery 面板中 Take Sample 获取到的单个音效内存占用更大,这个是每个音效实际都比 TakeSample 大些,还是说仅仅因为 Total Audio Memery 计算了其它额外内存?
于是进行测试,首先是空场景 Audio 信息统计:
接着使用三个不同大小的音效,使用 PCM (Decompress On Load) 格式进行播放,查看 Total Audio Memery 数值:
可以发现 Total Audio Memery 数值是根据 PCM Imported Size 大小增加的,Sample Sound Memery (Decompress On Load 解压内存占用量) 亦是按照实际大小跟随递增。
# 补充 PCM (Compressed In Memory) 模式:
DSP CPU:项目在加载类型为 Compressed In Memory 的非流式声音的混音、音频效果和解压缩中使用的 CPU 量。
Sample Sound Memory:加载类型为 Decompress On Load 的音频文件用于所有已解压缩样本数据的内存量。
也就是可以得出结论:
- Total Audio Memery 是所有内存总量,确实是计算了额外消耗内存的。
- Profiler Memery 面板中 Take Sample 获取到的单个音效内存就是实际占用量,与总消耗内存可以表现出一种递增的对应关系。
- PCM 虽然是无压缩格式,但若是选择 Compressed In Memory ,虽然单个音效内存跟选择与否没有变化,但对总体内存也会有一定影响 (测试表现是增加了一点)。
# 0x05 压缩格式对最终 AssetBunle 资源影响
# 1) 默认设置、SampleRate 22050Hz、PCM 格式:
# 2) 默认设置、SampleRate 22050Hz、ADPCM 格式:
# 3) 默认设置、SampleRate 22050Hz、Vorbis 压缩,质量 70%:
可以看出,跟图片压缩一样,压缩格式对最终出包的 AssetBunle 资源大小也会有影响,除压缩方式选择外,Vorbis 压缩质量数值也会影响。
最终 AssetBundle 包大小基本与音效面板上的 ImportedSize 差不多 (+ 部分 AssetBundle 额外数据)。
# 0x06 总结
测试结果有些与之前预想的一致,也有部分预想被『推翻』。
在内存占用量上,对于 Decompress On Load、Compressed In Memory、Streaming 三种 LoadType 方式:
- Decompress On Load 是以 PCM 格式下 ImportedSize 大小为基准,PCM、ADPCM 格式下在内存解压后占用量基本一致,Vorbis 多占用 40KB 左右
- Compressed In Memory:压缩模式存放内存,Vorbis 压缩会比 自身 ImportedSize 大 30KB 左右
- Streaming 以 200KB 缓存为基准,Vorbis 压缩后加载相比另外两种会额外占用 30KB 左右的内存。
注 1:关于内存占用比较基准,需要注意的是比较基准对象是不同的,这篇文章写完了,我脑袋就混乱了几天才反应过来
注 2:大的音效也满足该标准,上述 OriginalSize 为 2.8MB、32.8KB 的音效 Profiler 表现基本一致
在 CPU 资源消耗上,对于 Decompress On Load、Compressed In Memory、Streaming 三种 LoadType 方式:
- Decompress On Load:CPU 消耗差不多
- Compressed In Memory:压缩存放内存时,以 PCM->ADPCM->Vorbis (质量越高消耗越多)
- Streaming:流式播放时,以 PCM->ADPCM->Vorbis (质量越高消耗越多)
在音效质量上:
- 主要受压缩格式影响。PCM 不压缩效果最好,ADPCM 其次,Vorbis 最后。
- 对此可以在预览面板看出,更换压缩格式后,振幅会有轻微变动 —— 不过从实际听起来的效果看,PCM、ADPCM 和 Vorbis 高质量压缩下的效果差不多,至少个人没听出太大差别。
- 经过测试,如果源音效质量就不大行,PCM 和 Vorbis 效果是一样,修改该项音效振幅不会发生任何改动 —— 甚至 Vorbis 1%~100% 质量都没有差别,比如测试所用的 『lvbu』 音效。
另外 Force To Mono、Sample Rate 统一影响上述表现 (CPU、内存消耗、表现质量)
经过上面的测试,可以发现音效设置主要是质量换效率、或者空间换时间、或者时间换空间,总有一定取舍。
因此最后再说一下个人总结:
- 可以使用 PCM 模式下的 Imported Size 预估实际解压消耗内存量
- 没有绝对的最好设置,这个设置可能需要平衡 包体、内存、CPU 消耗得出结论,前期可以选择一个合适的格式统一设置,后续完整了再进行具体优化
- 以 PCM ImportedSize 为基准,一两百 KB、比较频繁使用的小音效,例如按钮声音、战斗中的技能音效,可以考虑使用 ADPCM 压缩格式
普通小音效选择 Compress In Memery、非常频繁的音效选择 Decompress On Load - 大一点或者比较少用的音效,不至于常影响到 CPU,采用 Vorbis 压缩,LoadType 采用 Compress In Memery。
- 采用 Vorbis 压缩可以调节质量滑块减少内存及 CPU 消耗 (当然这样音效质量也会受到影响)
- 音效内存消耗至少超过 250KB 再考虑是否要使用流式播放,另外采用流式播放最好采用 ADPCM 或 PCM 格式了 (不在意包体的话),省一些播放时的 CPU 解压消耗。
注 1:Streaming 播放模式下,会随着通同一个文件的反复加载,而叠加文件流及解码内存消耗
注 2:采样率 (越低内存占用越低)、强制单声道也会统一影响到三种设置在流式的缓存占用 - 另外在可以接受的情况下, Sample Rate 可以设置为 22050Hz,比 44100Hz 减少一半的占用
- Force To Mono 在小音效上应该也可以勾上,例如按钮点击音效总不能也是真的立体声吧,也可以省下一半资源。不过在音效源文件本身就是纯单通道的时候,勾选与否都没有影响
在我们游戏中,都是采用前两种 LoadType+Vorbis 压缩方式,质量 70%、压缩模式存放 (Compressed In Memory)、SampleRate 22050Hz。
注:选择压缩同时也会影响打包资源大小,最终 AssetBundle 包大小基本与音效面板上的 ImportedSize 差不多 (+ 部分 AssetBundle 额外数据)。最终设置得权衡质量、包体和内存及性能。