轉載
原文地址:https://www.jianshu.com/p/5452165f98b0
定義
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; }