对于aac ld的编码,通常为RAW的数据和每帧长度的记录,而不是通过带adts头来记录数据信息.
而相应的解码信息,通过aacDecoder_ConfigRaw来完成配置.
对于aacDecoder_ConfigRaw的配置,即ASC(audio special configure),分两种情况,拿例子说话
(1) aac eld 44.1kHz 双声道 conf为{ 0xF8, 0xE8, 0x50, 0x00 },转为二进制为:
11111 000111 0100 0010 1 0000 0000 0000
32 + 7 4 2 其他
aot为39,即eld; 4查表为44.1Hz, 2为双声道; 其他设置,参考源代码来解释,前3项正确,基本可以解码.
(2) aac ld 32kHz 单声道 conf为{ 0xBA, 0x88, 0x00, 0x00 },转为为二进制为:
10111 0101 0001 0000 0000 0000 0000 000
23 5 1 其他
aot为23,即ld; 5查表为32Hz, 1为单声道; 其他设置,参考源代码来解释,前3项正确,基本可以解码.
aot的具体含义,可以搜索aot的profile或者规格,有9种,其中aac lc广泛用于mp4中,比较常见,而aac ld用于实时音视频通信中,相对小众.
附表格为
索引 | 采样频率 |
0 | 96k |
1 | 88.2k |
2 | 64k |
3 | 48k |
4 | 44.1k |
5 | 32k |
6 | 24k |
7 | 22.05k |
8 | 16k |
9 | 12k |
a | 11.025k |
b | 8k |
c | 7.35k |
注意(1)(2)两种情况,对于audio of type (aot)的长度不同.以(2)情况的,aac ld进行解码,测试代码如下:
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include "aacdecoder_lib.h"
#include <iostream>
using namespace std;
int main() {
HANDLE_AACDECODER handle;
handle = aacDecoder_Open(TT_MP4_RAW , 1);
int conceal_method=2;//0 muting 1 noise 2 interpolation
//UCHAR eld_conf[] = { 0xF8, 0xE8, 0x50, 0x00 };//ste eld 44.1k
UCHAR ld_conf[] = { 0xBA, 0x88, 0x00, 0x00 };//mono ld 32k
UCHAR *conf[] = { ld_conf };
static UINT conf_len = sizeof(ld_conf);
AAC_DECODER_ERROR err = aacDecoder_ConfigRaw(handle, conf, &conf_len);
if(err>0)
cout<<"conf err:"<<err<<endl;
aacDecoder_SetParam(handle, AAC_CONCEAL_METHOD,conceal_method);
aacDecoder_SetParam(handle, AAC_PCM_MAX_OUTPUT_CHANNELS,1); //MONO:1
aacDecoder_SetParam(handle, AAC_PCM_MIN_OUTPUT_CHANNELS,1); //MONO:1
const char *lengthfile,*aacfile,*pcmfile;
lengthfile="length.txt";
aacfile="encode.aac";
pcmfile="decoder.pcm";
unsigned int size=1024;
unsigned int valid;
FILE* lengthHandle;
FILE* aacHandle;
FILE* pcmHandle;
lengthHandle = fopen(lengthfile, "rb");
aacHandle = fopen(aacfile, "rb");
pcmHandle = fopen(pcmfile, "wb");
unsigned char* data=(unsigned char*)malloc(size);
unsigned int decsize=8* 2048 * sizeof(INT_PCM);
unsigned char* decdata=(unsigned char*)malloc(decsize);
int frameCnt=0;
do{
int ll = fread(&size, 1,2, lengthHandle);
if(ll <1)
break;
printf("size %d\n",size);
fread(data, 1,size, aacHandle);
valid=size;
err=aacDecoder_Fill(handle, &data, &size, &valid);
if(err > 0)
cout<<"fill err:"<<err<<endl;
// aacDecoder_SetParam(handle, AAC_TPDEC_CLEAR_BUFFER, 1);
err = aacDecoder_DecodeFrame(handle, (INT_PCM *)decdata,decsize / sizeof(INT_PCM), 0);
if(err> 0)
cout<<"dec err:"<<err<<endl;
if(err != 0)
break;
CStreamInfo *info = aacDecoder_GetStreamInfo(handle);
/* cout<<"channels"<<info->numChannels<<endl;
cout<<"sampleRate"<<info->sampleRate<<endl;
cout<<"frameSize"<<info->frameSize<<endl;
cout<<"decsize"<<decsize<<endl;
cout<<"decdata"<<decdata[0]<<endl;*/
fwrite(decdata,1,info->frameSize*2,pcmHandle);
frameCnt++;
}while(true);
cout<<"frame count:"<<frameCnt<<endl;
fflush(pcmHandle);
fclose(lengthHandle);
fclose(aacHandle);
fclose(pcmHandle);
aacDecoder_Close(handle);
return 0;
}
读入的是encode.aac的文件,文件格式是RAW, 32Khz采样,单声道.
length.txt为每一帧的长度信息,用来辅助解码,在产品环境下,可以通过rtp的负载长度,进行区分.
对于AAC_CONCEAL_METHOD,我认为选插值的方式(设置为2)比较合理.
解码后得到decoder.pcm,为原始的PCM流.