您的位置:首页 > 其它

AAC音频格式分析与解码

2015-11-19 15:54 288 查看
转自: http://www.cnblogs.com/caosiyang/archive/2012/07/16/2594029.html

关于AAC音频格式基本情况,可参考维基百科http://en.wikipedia.org/wiki/Advanced_Audio_Coding
 
AAC音频格式分析
AAC音频格式有ADIF和ADTS:
ADIF:AudioDataInterchangeFormat音频数据交换格式。这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即它的解码必须在明确定义的开始处进行。故这种格式常用在磁盘文件中。
ADTS:AudioDataTransportStream音频数据传输流。这种格式的特征是它是一个有同步字的比特流,解码可以在这个流中任何位置开始。它的特征类似于mp3数据流格式。
简单说,ADTS可以在任意帧解码,也就是说它每一帧都有头信息。ADIF只有一个统一的头,所以必须得到所有的数据后解码。且这两种的header的格式也是不同的,目前一般编码后的和抽取出的都是ADTS格式的音频流。
语音系统对实时性要求较高,基本是这样一个流程,采集音频数据,本地编码,数据上传,服务器处理,数据下发,本地解码
ADTS是帧序列,本身具备流特征,在音频流的传输与处理方面更加合适。
 

ADTS帧结构:
header
body
ADTS帧首部结构:
序号长度(bits)说明
1Syncword12allbits must be1
2MPEGversion10forMPEG-4,1forMPEG-2
3Layer2always0
4ProtectionAbsent1etto1ifthereisnoCRCand0ifthereisCRC
5Profile2the MPEG-4AudioObjectType minus1
6MPEG-4SamplingFrequencyIndex4MPEG-4SamplingFrequencyIndex (15isforbidden)
7PrivateStream1setto0whenencoding,ignorewhendecoding
8MPEG-4ChannelConfiguration3MPEG-4ChannelConfiguration (inthecaseof0,thechannelconfigurationissentviaaninbandPCE)
9Originality1setto0whenencoding,ignorewhendecoding
10Home1setto0whenencoding,ignorewhendecoding
11CopyrightedStream1setto0whenencoding,ignorewhendecoding
12CopyrightedStart1setto0whenencoding,ignorewhendecoding
13FrameLength13thisvaluemustinclude7or9bytesofheaderlength:FrameLength=(ProtectionAbsent==1?7:9)+size(AACFrame)
14BufferFullness11bufferfullness
15NumberofAACFrames2numberofAACframes(RDBs)inADTSframe minus1,formaximumcompatibilityalwaysuse1AACframeperADTSframe
16CRC16CRCif protectionabsent is0
 
 
AAC解码
在解码方面,使用了开源的FAAD,http://www.audiocoding.com/faad2.html
sdk解压缩后,docs目录有详细的api说明文档,主要用到的有以下几个:
NeAACDecHandleNEAACAPINeAACDecOpen(void);
创建解码环境并返回一个句柄
voidNEAACAPINeAACDecClose(NeAACDecHandlehDecoder);
关闭解码环境
NeAACDecConfigurationPtrNEAACAPINeAACDecGetCurrentConfiguration(NeAACDecHandlehDecoder);
获取当前解码器库的配置
unsignedcharNEAACAPINeAACDecSetConfiguration(NeAACDecHandlehDecoder,NeAACDecConfigurationPtrconfig);
为解码器库设置一个配置结构
longNEAACAPINeAACDecInit(NeAACDecHandlehDecoder,unsignedchar*buffer,unsignedlongbuffer_size,unsignedlong*samplerate,unsignedchar*channels);
初始化解码器库
void*NEAACAPINeAACDecDecode(NeAACDecHandlehDecoder,NeAACDecFrameInfo*hInfo,unsignedchar*buffer,unsignedlongbuffer_size);
解码AAC数据

 
 
对以上api做了简单封装,写了一个解码类,涵盖了FAAD库的基本用法,感兴趣的朋友可以看看
MyAACDecoder.h:

/**

*

*filename:MyAACDecoder.h

*summary:convertaactowave

*author:caosiyang

*email:csy3228@gmail.com

*

*/

#ifndef__MYAACDECODER_H__

#define__MYAACDECODER_H__



#include"Buffer.h"

#include"mytools.h"

#include"WaveFormat.h"

#include"faad.h"

#include<iostream>

usingnamespacestd;



classMyAACDecoder{

public:

MyAACDecoder();

~MyAACDecoder();


int32_tDecode(char*aacbuf,uint32_taacbuflen);


constchar*WavBodyData()const{

return_mybuffer.Data();

}


uint32_tWavBodyLength()const{

return_mybuffer.Length();

}


constchar*WavHeaderData()const{

return_wave_format.getHeaderData();


}


uint32_tWavHeaderLength()const{

return_wave_format.getHeaderLength();

}


private:

MyAACDecoder(constMyAACDecoder&dec);

MyAACDecoder&operator=(constMyAACDecoder&rhs);


//initAACdecoder

int32_t_init_aac_decoder(char*aacbuf,int32_taacbuflen);


//destroyaacdecoder

void_destroy_aac_decoder();


//parseAACADTSheader,getframelength

uint32_t_get_frame_length(constchar*aac_header)const;


//AACdecoderproperties

NeAACDecHandle_handle;

unsignedlong_samplerate;

unsignedchar_channel;


Buffer_mybuffer;

WaveFormat_wave_format;

};



#endif/*__MYAACDECODER_H__*/


 
MyAACDecoder.cpp:

#include"MyAACDecoder.h"



MyAACDecoder::MyAACDecoder():_handle(NULL),_samplerate(44100),_channel(2),_mybuffer(4096,4096){

}



MyAACDecoder::~MyAACDecoder(){

_destroy_aac_decoder();

}



int32_tMyAACDecoder::Decode(char*aacbuf,uint32_taacbuflen){

int32_tres=0;

if(!_handle){

if(_init_aac_decoder(aacbuf,aacbuflen)!=0){

ERR1("::::initaacdecoderfailed::::");

return-1;

}

}


//clean_mybuffer

_mybuffer.Clean();


uint32_tdonelen=0;

uint32_twav_data_len=0;

while(donelen<aacbuflen){

uint32_tframelen=_get_frame_length(aacbuf+donelen);


if(donelen+framelen>aacbuflen){

break;

}


//decode

NeAACDecFrameInfoinfo;

void*buf=NeAACDecDecode(_handle,&info,(unsignedchar*)aacbuf+donelen,framelen);

if(buf&&info.error==0){

if(info.samplerate==44100){

//44100Hz

//src:2048samples,4096bytes

//dst:2048samples,4096bytes

uint32_ttmplen=info.samples*16/8;

_mybuffer.Fill((constchar*)buf,tmplen);

wav_data_len+=tmplen;

}elseif(info.samplerate==22050){

//22050Hz

//src:1024samples,2048bytes

//dst:2048samples,4096bytes

short*ori=(short*)buf;

shorttmpbuf[info.samples*2];

uint32_ttmplen=info.samples*16/8*2;

for(int32_ti=0,j=0;i<info.samples;i+=2){

tmpbuf[j++]=ori[i];

tmpbuf[j++]=ori[i+1];

tmpbuf[j++]=ori[i];

tmpbuf[j++]=ori[i+1];

}

_mybuffer.Fill((constchar*)tmpbuf,tmplen);

wav_data_len+=tmplen;

}

}else{

ERR1("NeAACDecDecode()failed");

}


donelen+=framelen;

}


//generateWaveheader

_wave_format.setSampleRate(_samplerate);

_wave_format.setChannel(_channel);

_wave_format.setSampleBit(16);

_wave_format.setBandWidth(_samplerate*16*_channel/8);

_wave_format.setDataLength(wav_data_len);

_wave_format.setTotalLength(wav_data_len+44);

_wave_format.GenerateHeader();


return0;

}



uint32_tMyAACDecoder::_get_frame_length(constchar*aac_header)const{

uint32_tlen=*(uint32_t*)(aac_header+3);

len=ntohl(len);//LittleEndian

len=len<<6;

len=len>>19;

returnlen;

}



int32_tMyAACDecoder::_init_aac_decoder(char*aacbuf,int32_taacbuflen){

unsignedlongcap=NeAACDecGetCapabilities();

_handle=NeAACDecOpen();

if(!_handle){

ERR1("NeAACDecOpen()failed");

_destroy_aac_decoder();

return-1;

}


NeAACDecConfigurationPtrconf=NeAACDecGetCurrentConfiguration(_handle);

if(!conf){

ERR1("NeAACDecGetCurrentConfiguration()failed");

_destroy_aac_decoder();

return-1;

}

NeAACDecSetConfiguration(_handle,conf);


longres=NeAACDecInit(_handle,(unsignedchar*)aacbuf,aacbuflen,&_samplerate,&_channel);

if(res<0){

ERR1("NeAACDecInit()failed");

_destroy_aac_decoder();

return-1;

}

//fprintf(stdout,"SampleRate=%d\n",_samplerate);

//fprintf(stdout,"Channel=%d\n",_channel);

//fprintf(stdout,"::::initaacdecoderdone::::\n");


return0;

}



voidMyAACDecoder::_destroy_aac_decoder(){

if(_handle){

NeAACDecClose(_handle);

_handle=NULL;

}

}


Fromhttp://www.cnblogs.com/caosiyang/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: