AAC概述
AAC是高级音频编码(Advanced Audio Coding)的缩写,出现于1997年,最初是基于MPEG-2的音频编码技术。由Fraunhofer IIS、Dolby Laboratories、AT&T、Sony等公司共同开发,目的是取代MP3格式。2000年,MPEG-4标准出台,AAC重新集成了其它技术(PS,SBR),为区别于传统的MPEG-2 AAC,故含有SBR或PS特性的AAC又称为MPEG-4 AAC。
AAC是新一代的音频有损压缩技术,它通过一些附加的编码技术(比如PS,SBR等),衍生出了LC-AAC,HE-AAC,HE-AACv2三种主要的编码,LC-AAC就是比较传统的AAC,相对而言,主要用于中高码率(>=80Kbps),HE-AAC(相当于AAC+SBR)主要用于中低码(<=80Kbps),而新近推出的HE-AACv2(相当于AAC+SBR+PS)主要用于低码率(<=48Kbps),事实上大部分编码器设成<=48Kbps自动启用PS技术,而>48Kbps就不加PS,就相当于普通的HE-AAC。
AAC特点
- AAC是一种高压缩比的音频压缩算法,但它的压缩比要远超过较老的音频压缩算法,如AC-3、MP3等。并且其质量可以同未压缩的CD音质相媲美
- AAC也是采用了变换编码算法,但AAC使用了分辨率更高的滤波器组,因此它可以达到更高的压缩比
- AAC使用了临时噪声重整、后向自适应线性预测、联合立体声技术和量化哈夫曼编码等最新技术,这些新技术的使用都使压缩比得到进一步的提高
- AAC支持更多种采样率和比特率、支持1个到48个音轨、支持多达15个低频音轨、具有多种语言的兼容能力、还有多达15个内嵌数据流
- AAC支持更宽的声音频率范围,最高可达到96kHz,最低可达8KHz,远宽于MP3的16KHz-48kHz的范围
- 不同于MP3及WMA,AAC几乎不损失声音频率中的甚高、甚低频率成分,并且比WMA在频谱结构上更接近于原始音频,因而声音的保真度更好
ACC的规格
- MPEG-2 AAC LC:低复杂度规格(Low Complexity)
- MPEG-2 AAC Main:主规格
- MPEG-2 AAC SSR:可变采样率规格(Scaleable Sample Rate)
- MPEG-4 AAC LC:低复杂度规格(Low Complexity)
- MPEG-4 AAC Main:主规格
- MPEG-4 AAC SSR:可变采样率规格(Scaleable Sample Rate)
- MPEG-4 AAC LTP:长时期预测规格(Long Term Predicition)
- MPEG-4 AAC LD:低延迟规格(Low Delay)
- MPEG-4 AAC HE:高效率规格(High Efficiency)
LC到HE发展历程图
LC 适合中等比特率,比如96kbps ~ 192kbps之间
从图中可以了解到MPEG-4 AAC LC 相当于MPEG-2 AAC LC + PNS(PNS 可以提高AAC的编码效率)
PNS(Perceptual Noise Substitution)
HE 存在v1和v2 两个版本,适合低比特率
v1:适合48kbps ~ 64kbps
v2:适合低于32kbps,可在低至32kbps的比特率下提供接近CD品质的声音
MPEG-4 AAC HE v1 相当于MPEG-4 AAC LC + SBR(是一种增强的压缩技术、可以将高频信号存储在少量的SBR data中、解码器可以根据SBR data恢复出高频信号)
MPEG-4 AAC HE v2 相当于MPEG-4 AAC HE v1 + PS(是一种有损的音频压缩算法,可以进一步提高压缩率、以将左右声道信号组合成单声道信号,声道之间的差异信息存储到少量的PS data中(大概占2 ~ 3kbps)、解码器可以根据PS data中恢复出立体声信号)
SBR Spectral Band Replication
PS(Parametric Stereo)
AAC音频文件格式
首先需要了解的是AAC文件格式有ADIF和ADTS两种
- ADIF:Audio Data Interchange Format 音频数据交换格式。这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即它的解码必须在明确定义的开始处进行。故这种格式常用在磁盘文件中。
- ADTS:Audio Data Transport Stream 音频数据传输流。这种格式的特征是它是一个有同步字的比特流,解码可以在这个流中任何位置开始。它的特征类似于mp3数据流格式。
简单说,ADTS可以在任意帧解码,也就是说它每一帧都有头信息。ADIF只有一个统一的头,所以必须得到所有的数据后解码。且这两种的header的格式也是不同的,目前一般编码后的和抽取出的都是ADTS格式的音频,。
目前主流使用的都是ADTS格式,所以这里只介绍ADTS ACC文件格式
AAC音频文件的每一帧都由一个ADTS头和AAC ES(AAC音频数据)组成。
ADTS头包含了AAC文件的采样率、通道数、帧数据长度等信息。ADTS头分为固定头信息和可变头信息两个部分,固定头信息在每个帧中的是一样的,可变头信息在各个帧中并不是固定值。ADTS头一般是7个字节((28+28)/ 8)长度,如果需要对数据进行CRC校验,则会有2个Byte的校验码,所以ADTS头的实际长度是7个字节或9个字节
固定头部信息:adts_fixed_header
/* adts_fixed_header */
put_bits(&pb, 12, 0xfff); /* syncword */
put_bits(&pb, 1, 0); /* ID */
put_bits(&pb, 2, 0); /* layer */
put_bits(&pb, 1, 1); /* protection_absent */
put_bits(&pb, 2, ctx->objecttype); /* profile_objecttype */
put_bits(&pb, 4, ctx->sample_rate_index);
put_bits(&pb, 1, 0); /* private_bit */
put_bits(&pb, 3, ctx->channel_conf); /* channel_configuration */
put_bits(&pb, 1, 0); /* original_copy */
put_bits(&pb, 1, 0); /* home */
- syncword:帧同步标识一个帧的开始,固定为0xFFF
- ID:MPEG 标示符。0表示MPEG-4,1表示MPEG-2
- layer:固定为’00’
- protection_absent:标识是否进行误码校验。0表示有CRC校验,1表示没有CRC校验
- profile:标识使用哪个级别的AAC。1: AAC Main 2:AAC LC (Low Complexity) 3:AAC SSR (Scalable Sample Rate) 4:AAC LTP (Long Term Prediction)
- sampling_frequency_index:标识使用的采样率的下标
- private_bit:私有位,编码时设置为0,解码时忽略
- channel_configuration:标识声道数
- original_copy:编码时设置为0,解码时忽略
- home:编码时设置为0,解码时忽略
sampling_frequency_index
index | Hz |
---|---|
0 | 96000 Hz |
1 | 88200 Hz |
2 | 64000 Hz |
3 | 48000 Hz |
4 | 44100 Hz |
5 | 32000 Hz |
6 | 24000 Hz |
7 | 22050 Hz |
8 | 16000 Hz |
9 | 12000 Hz |
10 | 11025 Hz |
11 | 8000 Hz |
12 | 7350 Hz |
13 | Reserved |
14 | Reserved |
15 | frequency is written explictly |
profile
PROFILE | SAMPLES |
---|---|
HE-AAC v1/v2 | 2048 |
AAC-LC | 1024 |
AAC-LD/AAC-ELD | 480/512 |
Channel Configuration
- 0: Defined in AOT Specifc Config
- 1: 1 channel: front-center
- 2: 2 channels: front-left, front-right
- 3: 3 channels: front-center, front-left, front-right
- 4: 4 channels: front-center, front-left, front-right, back-center
- 5: 5 channels: front-center, front-left, front-right, back-left, back-right
- 6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
- 7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel
- 8-15: Reserved
可变头信息:adts_variable_header()
/* adts_variable_header */
put_bits(&pb, 1, 0); /* copyright_identification_bit */
put_bits(&pb, 1, 0); /* copyright_identification_start */
put_bits(&pb, 13, full_frame_size); /* aac_frame_length */
put_bits(&pb, 11, 0x7ff); /* adts_buffer_fullness */
put_bits(&pb, 2, 0); /* number_of_raw_data_blocks_in_frame */
- copyrighted_id_bit:编码时设置为0,解码时忽略
- copyrighted_id_start:编码时设置为0,解码时忽略
- aac_frame_length:ADTS帧长度包括ADTS长度和AAC声音数据长度的和。即 aac_frame_length = (protection_absent == 0 ? 9 : 7) + audio_data_length
- adts_buffer_fullness:固定为0x7FF。表示是码率可变的码流
- number_of_raw_data_blocks_in_frame:表示当前帧有- number_of_raw_data_blocks_in_frame + 1 个原始帧(一个AAC原始帧包含一段时间内1024个采样及相关数据)。
AAC编解码器
之前说到个音频的一些文件格式,包括WAV,AAC等,如果现在想对PCM数据进行ACC编码压缩的话,我们需要用到ACC编码器,相反如果想对ACC编码后的数据解压出PCM数据,那么久需要用到ACC解码器;
集中常用的ACC编解码器
- Nero AAC
支持LC/HE 规格,目前已经停止维护
- FFmpeg AAC
FFmpeg 官方内置的AAC编解码器,在libavcodec
库中,编解码器名字叫做aac
- FAAC(Freeware Advanced Audio Coder)
- 支持LC规格
- 可以集成到FFmpeg的libavcodec 中,编解码器名字叫做libfaac,2016年后ffmpeg已经移除了对FAAC的支持
移除原因
- Fraunhofer FDK AAC
- 支持LC/HE规格
- 目前质量最高AAC编解码器https://trac.ffmpeg.org/wiki/Encode/AAC
FDK AAC的学习
mac下通过brew 安装的FFmpeg通常是没有集成libfdk_aac的,这个可以在终端通过命令行下检查
songlin@feng-sl /usr/local/Cellar/ffmpeg/4.3.2_4/bin master ± ./ffmpeg -codecs | grep aac
ffmpeg version 4.3.2 Copyright (c) 2000-2021 the FFmpeg developers
built with Apple clang version 12.0.0 (clang-1200.0.32.29)
configuration: --prefix=/usr/local/Cellar/ffmpeg/4.3.2_4 --enable-shared --enable-pthreads --enable-version3 --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox
libavutil 56. 51.100 / 56. 51.100
libavcodec 58. 91.100 / 58. 91.100
libavformat 58. 45.100 / 58. 45.100
libavdevice 58. 10.100 / 58. 10.100
libavfilter 7. 85.100 / 7. 85.100
libavresample 4. 0. 0 / 4. 0. 0
libswscale 5. 7.100 / 5. 7.100
libswresample 3. 7.100 / 3. 7.100
libpostproc 55. 7.100 / 55. 7.100
DEAIL. aac AAC (Advanced Audio Coding) (decoders: aac aac_fixed aac_at ) (encoders: aac aac_at )
D.AIL. aac_latm AAC LATM (Advanced Audio Coding LATM syntax)
从终端的输出结果中,可以发现是没有libfdk_aac的,所以我们需要手动编译FFmpeg源码,让编译后的ffmpeg集成我们需要的功能,至于如何手动编译FFmpeg,可以参考这篇文章