手机游戏音频压缩

每个游戏里都会有很多音效和背景音乐,优化包体积时音频文件是一个很容易收效而且容易被忽略的点。

一、概念解释

下面几个概念是在处理音频的时候经常遇到的,而且理解上有很多误区,搞清楚这些概念是十分必要的。

文件格式 & 编码格式

首先需要解释一个概念,大家往往认为媒体文件文件的扩展名就是其编码格式,对图片文件来说是成立的,但是音频和视频文件就不大正确了。文件扩展名一般代表的是媒体文件的文件格式,或者叫容器格式。一种容器格式可以支持很多编码格式,也可能只支持特定的编码格式,有以下3种情况:

  1. 容器格式支持只支持特定编码格式,比如RealMedia文件格式(rm/rmvb)只支持RealMediad编码。ASF容器和WMA、WMV编码的关系也是如此。
  2. 容器格式支持很多不同的编码格式,比如MP4容器支持MPEG-1/MPEG-2/MPEG-4等视频编码格式,AAC、MP3、MP2、MP1等音频编码格式。类似的还有MKV、3GP。
  3. 容器格式支持不同的编码,但是现实里绝大多数情况只和特定的编码格式组合。比如WAV虽然支持使用不同的压缩编码,但是绝大多数WAV文件都是无压缩的PCM(LPCM)编码。OGG容器一般也只有Vorbis编码会用。

注:WAV、AVI的文件格式其实都是RIFF格式,扩展名只是指明了媒体类型。

我们关心的是编码格式,因为编码格式决定了音频的大小、质量,找到合适的编码格式后,很容易就能确定用什么容器去装它。常见的音频容器格式有WAV、AIFF、CAF、MP4(m4a),从平台支持的和容器中选择能容纳所选编码格式的就行了。

采样率 & 采样精度 & 比特率

采样率指的是将声音的波形数字化时,采样的频率,或者说是每秒钟内采样点的个数。
采样精度指的是每个采样点占用的位数,采样精度为8bit时,可以把波形分成256级不同的信号(对应视频里的概念,采样率相当于帧率,采样精度相当于分辨率)
比特率指的是音频文件每秒占用的bit数

比特率(bit/s) = 采样率(Hz) <span>* 采样精度(bit) *</span> 声道数 <span>* 压缩率 *</span> 1s

比如最常见的wav文件,采样率是44.1KHz,采样精度16bit,双声道,没有压缩,那么它的比特率:

比特率 = 44100 <span>* 16 *</span> 2 * 1 = 1411200 bps = 1411.2 kbps

二、编码格式比较

我们选择音频格式的时候希望在保证一定音频质量的前提下,压缩率尽可能高。目前主流的有损压缩编码为MP3、AAC、HE-AAC、Vorbis。从技术上来说AAC和Vorbis远远领先于MP3,尤其是在较低比特率(<=96kbps)下,相同比特率的AAC和Vorbis音质要远远好于MP3。

MP3目前仍然非常流行,原因一是MP3的Codec太普及,二是大多数的用户没有追求高压缩率的需求,一般用户使用的mp3歌曲的比特率为192kbps,在这种比较高的比特率下,各种编码格式的质量区别并不明显。

编码器试听测试列表这个wiki里有很多试听测试结果,可以反映音频格式+Codec的质量。所谓试听测试,就是准备好一些不同特点的源音频,然后用各个待测编码器编码,找一批试听者在不知道音频文件的编码的情况下,根据试听感觉给每个编码后的音频打分。我们选出低比特率,并且包含AAC和Vorbis的测试:

测试的结论基本一致 AAC(Apple Codec)>= Vorbis。

AAC编码

AAC编码有9种很多不同的规格Profile,其中AAC-LC(低复杂度规格)是最常见的规格,AAC-HE(高效率规格)是压缩比最高的规格,是我们优化音频大小的主力编码。AAC-HE有分为HE-ACC v1和HE-AAC v2两个版本,使用了SBR(频段复制)和PS(参量立体声)的两种音频编码技术,达到了非常高的压缩比。感兴趣的话可以看这篇文档,其中详细介绍了SBR和PS的工作原理。

Android & iOS 上的情况

Android可以使用的编码格式为MP3、AAC、HE-AAC、Vorbis、AMR、Linear PCM、ALAC
iOS可以使用的编码格式为MP3、AAC、HE-AAC、IMA4、iLBC、Linear PCM、FLAC

其中iLBC和AMR是为Speech设计的,也就是专门用于存储人声录音;LPCM、ALAC、FLAC是无损格式;AAC、MP3、HE-AAC、Vorbis是有损压缩。

iOS Tips

摘自Apple官方文档——Using Audio

音频格式 硬解码 软解码
AAC Yes Yes, starting in iOS 3.0
ALAC Yes Yes, starting in iOS 3.0
HE-AAC Yes No
iLBC No Yes
iMA4 No Yes
Linear PCM No Yes
MP3 Yes Yes, starting in iOS 3.0
µ-law / a-law No Yes

硬解码相对于软解码的优势在于非常低的CPU消耗,也就意味着低耗电、低发热。

Linear PCM和iMA4虽然没有硬解,但是同时播放多个Linear PCM和iMA4不会造成高CPU消耗,因为LPCM没有被压缩而iMAC4(ADPCM)的压缩算法非常简单。

AAC、HE-AAC、ALAC和MP3硬解码使用相同的硬件路径,并且该解码器不支持同时解码多个音频,所以当这几种格式的音频同时播放时,只有一个音频使用硬解码,其他都是软解码。HE-AAC格式由于不能软解码,同时只能有一个HE-AAC音频实例在播放。

Other Tips

  • Android和iOS可以使用不同的音频格式,用工具转换;
  • 音乐、音效可以使用不同的格式;
  • 要考虑设备系统兼容性,Android >= 2.3,iOS >= 5.0,不同版本的系统环境中必须都有所选格式decoder;
  • 压缩格式音频文件解码可能会占用可观的CPU资源,尤其是多个同时播放的音效,可以在首次游戏加载的时候将它们解码成非压缩格式(Linear PCM);
  • 编码器和解码器(Codec)的实现会影响音频的质量,相同的编码格式不同的编码器产生的音频文件质量可能相差很远(从前面的几个测试结果可以看出,同样的HE-AAC编码,FAAC的质量要比Apple AAC差得多)。

三、我们使用的方案

我们几乎所有的项目中都使用了这个方案:iOS和Android分别转码成HE AAC v1和HE AAC v2,体积缩小到原来的1/2、1/3。先将所有的音频转成HE AAC v2,然后将其中高频失真比较明显的换成HE AAC v1。

Codec 优化前 优化后
HE AAC 150k(128kbps mp3) 87k(65kbps HE AAC v1, FDK AAC)
HE AAC v2 150k(128kbps mp3) 45k(33Kbps HE AAC v2, Apple AAC)

转化工具

Codec使用的是iTunes里的HE AAC v2 Codec,这个Codec的效果比我试过的所有的HE AAC v2 Codec(包括)都要好非常多。网上有一个封装好直接可以用的可执行文件enhAacPlusEncenhAacPlusEnc,配合下面的脚本即可完成转换:

#!/bin/bash

ROOTDIR="$( cd "$( dirname "$0" )" && pwd )"
cd $ROOTDIR/..

rm -rf ../tmp
mkdir -p tmp/raw
mkdir -p tmp/aac

cd song_new;

for mp3 in *.MP3; do
    #mp3="../tmp/raw/${mp3/MP3/mp3}"
    wav="../tmp/raw/${mp3/%MP3/wav}"
    aac="../tmp/aac/${mp3/MP3/aac}"
    m4a="../song_android/${mp3/MP3/m4a}"
    m4a2="../song_ios/${mp3/MP3/m4a}"

    # decode mp3 to wav
    ffmpeg -y -i "$mp3" "$wav" 

    #For Android: encode wav in he-aac-v2 using Apple AAC codec
    ../tools/enhAacPlusEnc "$wav" "$aac" 32000 s
    # warp raw adts aac into mp4 container for android 2 compatibility
    mp4box -add "$aac" "$m4a"

    #For iOS: encode wav in he-aac-v1 using FDK AAC codec
    ffmpeg -i "$wav" -c:a libfdk_aac -profile:a aac_he -b:a 64k "$m4a2";
done 

#rm -rf ../tmp
This entry was posted in 技术学习 and tagged , , , . Bookmark the permalink.

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据