AAC(Advanced Audio Coding),中文名:高级音频编码,出现于1997年,基于MPEG-2的音频编码技术。由Fraunhofer IIS、杜比实验室、AT&T、Sony等公司共同开发,目的是取代MP3格式。2000年,MPEG-4标准出现后,AAC重新集成了其特性,加入了SBR技术和PS技术,为了区别于传统的MPEG-2 AAC又称为MPEG-4 AAC。
定义
AAC,全称Advanced Audio Coding,是一种专为声音数据设计的文件压缩格式。与MP3不同,它采用了全新的算法进行编码,更加高效,具有更高的“性价比”。利用AAC格式,可使人感觉声音质量没有明显降低的前提下,更加小巧。苹果ipod、诺基亚手机支持AAC格式的音频文件。
优点:相对于mp3,AAC格式的音质更佳,文件更小。
不足:AAC属于有损压缩的格式,与时下流行的APE、FLAC等无损格式相比音质存在“本质上”的差距。加之,传输速度更快的USB3.0和16G以上大容量MP3正在加速普及,也使得AAC头上“小巧”的光环不复存在。
特点
①提升的压缩率:可以以更小的文件大小获得更高的音质;
②支持多声道:可提供最多48个全音域声道;
③更高的解析度:最高支持96KHz的采样频率;
④提升的解码效率:解码播放所占的资源更少;
杜比实验室的结论
①128Kbps的AAC立体声音乐被专家认为不易察觉到与原来未压缩音源的区别;
②AAC格式在96Kbps码率的表现超过了128Kbps的MP3格式;
③同样是128Kbps,AAC格式的音质明显好于MP3;
④AAC是唯一一个,能够在所有的EBU试听测试项目的获得“优秀”的网络广播格式。
总的来讲,AAC可以说是极为全面的编码方式,一方面,多声道和高采样率的特点使得它非常适合未来的DVD-Audio;另一方面,低码率下的高音质则使它也适合移动通讯、网络电话、在线广播等领域,真是全能的编码方式。
AAC 规格介绍
AAC共有9种规格,以适应不同的场合的需要:
- MPEG-2 AAC LC 低复杂度规格(Low Complexity)--比较简单,没有增益控制,但提高了编码效率,在中等码率的编码效率以及音质方面,都能找到平衡点
- MPEG-2 AAC Main 主规格
- MPEG-2 AAC SSR 可变采样率规格(Scaleable Sample Rate)
- MPEG-4 AAC LC 低复杂度规格(Low Complexity)------现在的手机比较常见的MP4文件中
- 的音频部份就包括了该规格音频文件
- 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)-----这种规格适合用于低码率编码,有Nero ACC 编码器支持
AAC音频文件格式
AAC的音频文件格式有ADIF & ADTS:
-
ADIF:Audio Data Interchange Format 音频数据交换格式。这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即它的解码必须在明确定义的开始处进行。故这种格式常用在磁盘文件中。
-
ADTS:Audio Data Transport Stream 音频数据传输流。这种格式的特征是它是一个有同步字的比特流,解码可以在这个流中任何位置开始。它的特征类似于mp3数据流格式。
简单说,ADTS可以在任意帧解码,也就是说它每一帧都有头信息。ADIF只有一个统一的头,所以必须得到所有的数据后解码。且这两种的header的格式也是不同的,目前一般编码后的和抽取出的都是ADTS格式的音频流。两者具体的组织结构如下所示:
AAC的ADIF格式见下图:
AAC的ADTS的一般格式见下图:
ADTS 文件格式
AAC音频文件的每一帧由ADTS Header和AAC Audio Data组成。
而ADTS的 Header部分分成两部分,固定部分和可变部分
固定部分 adts_fixed_header
- yncword :总是0xFFF, 代表一个ADTS帧的开始, 用于同步.
解码器可通过0xFFF确定每个ADTS的开始位置.
因为它的存在,解码可以在这个流中任何位置开始, 即可以在任意帧解码。 - ID:MPEG 版本: 0 代表 MPEG-4,1 代表 MPEG-2
- Layer:总是: '00'
- protection_absent:设置0,进行crc校验,1不进行crc校验,进行crc校验导致固定部分边长成28+16 = 44bits
- profile:表示使用哪个级别的AAC
如01 Low Complexity(LC) -- AAC LC。
注意 profile的值等于 Audio Object Type的值减1.
profile = MPEG-4 Audio Object Type - 1
-
sampling_frequency_index:采样率的下标
- channel_configuration:声道数,比如2表示立体声双声道
这里注意,声道数量这里有3个bits表示
其他没有介绍的位都是0,保留
可变部分adts_variable_header
- aac_frame_length 一个ADTS帧的长度包括ADTS头和AAC原始流。就是该帧的总长度。
aac_frame_length = (protection_absent == 1 ? 7 : 9) + size(AACFrame) - adts_buffer_fullness:0x7FF 说明是码率可变的码流。
- number_of_raw_data_blocks_in_frame:表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧。
所以说number_of_raw_data_blocks_in_frame == 0 表示说ADTS帧中有一个AAC数据块。
这里需要注意的是每一个AAC原始帧包含一段时间内1024个采样及相关数据
总体结构
AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM MMMMMMMM MMMOOOOO OOOOOOPP (QQQQQQQQ QQQQQQQQ)
头部分是7字节或者9字节(有crc就是9字节没有就是7字节)
Letter | Length (bits) | Description |
---|---|---|
A | 12 | syncword 0xFFF, 所有位数都是1 |
B | 1 | MPEG 版本: 0 代表 MPEG-4, 1 代表 MPEG-2 |
C | 2 | Layer: 总是 0 |
D | 1 | protection absent, 1 代表不用crc,0代表用crc |
E | 2 | profile, MPEG-4 Audio Object Type 减去 1 |
F | 4 | MPEG-4 Sampling Frequency Index |
G | 1 | 私有位置,不会被mpeg适用,编码时候设置0,解码忽略 |
H | 3 | MPEG-4 Channel Configuration (在0的情况下,通过带内的PCE发送通道配置) |
I | 1 | originality, 编码设置0,解码忽略 |
J | 1 | home, 编码设置0,解码忽略 |
K | 1 | copyrighted id bit,编码时候设置0,解码忽略 |
L | 1 | copyright id start, 编码时候设置0,解码忽略 |
M | 13 | frame length,帧长度,该值保护7或者9个字节的头 FrameLength =(ProtectionAbsent == 1?7:9)+ size(AACFrame) |
O | 11 | Buffer fullness ,缓冲充满度 |
P | 2 | ADTS 帧中的AAC帧数-1 为了实现最大的兼容性,每个ADTS帧始终使用一个AAC 也就是说改为始终是0 |
Q | 16 | protection absent 是0, 就有q的位置,是1,就没有q的位置 |
这段代码写的很清楚可惜不是oc写的
int ff_adts_write_frame_header(ADTSContext *ctx,
uint8_t *buf, int size, int pce_size)
{
PutBitContext pb;
init_put_bits(&pb, buf, ADTS_HEADER_SIZE);
/* 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 */
/* adts_variable_header */
put_bits(&pb, 1, 0); /* copyright_identification_bit */
put_bits(&pb, 1, 0); /* copyright_identification_start */
put_bits(&pb, 13, ADTS_HEADER_SIZE + size + pce_size); /* aac_frame_length */
put_bits(&pb, 11, 0x7ff); /* adts_buffer_fullness */
put_bits(&pb, 2, 0); /* number_of_raw_data_blocks_in_frame */
flush_put_bits(&pb);
return 0;
}
这里是LFLiveKit中的代码封装。
- (NSData *)adtsData:(NSInteger)channel rawDataLength:(NSInteger)rawDataLength {
int adtsLength = 7;
char *packet = malloc(sizeof(char) * adtsLength);
// Variables Recycled by addADTStoPacket
int profile = 2; //AAC LC
//39=MediaCodecInfo.CodecProfileLevel.AACObjectELD;
NSInteger freqIdx = [self sampleRateIndex:self.configuration.audioSampleRate]; //44.1KHz
int chanCfg = (int)channel; //MPEG-4 Audio Channel Configuration. 1 Channel front-center
NSUInteger fullLength = adtsLength + rawDataLength;
// fill in ADTS data
packet[0] = (char)0xFF; // 11111111 = syncword
packet[1] = (char)0xF9; // 1111 1 00 1 = syncword MPEG-2 Layer CRC
packet[2] = (char)(((profile-1)<<6) + (freqIdx<<2) +(chanCfg>>2));
packet[3] = (char)(((chanCfg&3)<<6) + (fullLength>>11));
packet[4] = (char)((fullLength&0x7FF) >> 3);
packet[5] = (char)(((fullLength&7)<<5) + 0x1F);
packet[6] = (char)0xFC;
NSData *data = [NSData dataWithBytesNoCopy:packet length:adtsLength freeWhenDone:YES];
return data;
}
网友评论