# 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 额外数据)。最终设置得权衡质量、包体和内存及性能。