AAC與PCM轉化--libfaac及libfdk-aac使用

1、AAC的兩種編碼格式

《1》、ADTS格式

  ADTS頭包含了AAC文件的採樣率、通道數、幀數據長度等信息,分爲固定頭信息和可變頭信息兩部分。
ADTS頭一般是7個字節(28bit+28bit)/8,若ADTS頭的 protection_absent字段值爲0時則爲9個字節。
在這裏插入圖片描述
固定頭部信息結構體說明如下:
在這裏插入圖片描述

  profile的值等於 Audio Object Type的值減1,即是profile=Audio Object Type - 1;
在這裏插入圖片描述
示例如下:
在這裏插入圖片描述

0xfff 幀開始標誌syncword
0x01(0001) --- [0--MPEG4, 00--layer , 0--protection_absent]
0x4c803a61c8(0100 1100 1000 0000 0011 1010 0110 0001 1100 1000) 
 ---- [ 01--AAC LC, 0011--48 KHZ, 0--private_bit, 010--雙通道 , 0--original_copy, 0--home
      0--copyright_identification_bit, 0--copyright_identification_start, 
     0000 1110 1001 1 ---aac幀長度, 0000 1110 010--adts_buffer_fullness,
       00--number_of_raw_data_blocks_in_frame
    ]

《2》ADIF格式

  ADIF只有一個統一的頭,所以必須得到所有的數據後才能進行解碼,一般用於磁盤文件中,實時流協議中不使用。
在這裏插入圖片描述

2、PCM存儲格式

在這裏插入圖片描述

3、libfdk-aac使用

使用libfdk-aac並無太多注意的地方。有一點值得注意的是在進行編碼之前需要根據PCM的數據格式將輸入的buffer進行數據轉化(8bit採樣位數的不需要)

//ret = 輸入數據大小(Byte)
//input_buf,輸出PCM數據的緩存區
//convert_buf, 轉化的結果
//該轉化將PCM數據的高低位合併起來
for (i = 0; i < ret / 2; i++)
{
    const char* in = &input_buf[2*i];
    convert_buf[i] = in[0] | (in[1] << 8);
}

  當輸入樣本的數量不等於調用下面算出的input_size時,調用aacEncEncode進行轉化會沒有輸出,直到輸入累積到input_size纔會有輸出。

aacEncInfo(aacEncHandle, &info);
int input_size       = channel * 2 * info.frameLength;

4、libaac使用

《1》pcm到aac命令

faac 225.18.1.2.pcm -o test.aac -C 2 -R 8000 -B 16 --mpeg-vers 4 -X

《2》、ffmpeg aac轉PCM

ffmpeg.exe -i audio_chn0.aac -f s16le -ar 8000 -ac 2 -acodec pcm_s16le -y pcm8k.pcm

-acodec pcm_s16le:輸出pcm格式,採用signed 16編碼,字節序爲小尾端(大尾端爲be);
-ar 8000: 採樣率爲8000
-ac 1: 聲道數爲2

  當調用faacEncEncode函數時,其參數中的輸入樣本數量必須等於調用faacEncOpen函數返回的輸入樣本數量,否則轉換結果是錯的!
這裏和libfdk-aac是有差異的,libfdk-aac若輸入樣本不足不會輸出錯誤結果而是等到有足夠樣本時輸出。

5、對比

  網上這篇 博文 說libfdk-aac的轉化效果好,但我實際對比後發現還是libaac的音質好很多,libfdk-aac的設置也是按照它源碼demo來設置的。
速度的話是libfdk_aac比libaac快上不少。

6、demo

demo是在centos6.9上實現的。

7、參考

《1》、ADTS頭部參考
《2》、faac參考
《3》、libfdk-aac參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章