aac语音格式详解

aac帧分为adts头和aac编码数据
一 adts头结构
adts头主要包含profile类型,采样率,声道数,帧长度,是可变码率还是固定码率等信息。
adts_fixed_header(){
    syncword; 12 0xfff
    ID; 1 
    layer;2  (always 00)
    protection_absent;1 
    profile;2  LC RC
    sampling_frequency_index;4 uimsbf
    private_bit;1 bslbf
    channel_configuration;3 uimsbf
    original_copy;1 bslbf
    home;1 bslbf
}

syncword:always 0xfff
ID:MPEG Version: 0 for MPEG-4, 1 for MPEG-2
Layer:always: '00'


profile:AAC编码级别
    0:Main profile
    1:Low Complexity profile(LC)
    2:Scalable sampling Rate Profile(SSR)
    3:Reserved
sampling_frequency_index:采样率,对应关系如下
   0: 96000 Hz
    1: 88200 Hz
    2: 64000 Hz
    3: 48000 Hz
    4: 44100 Hz
    5: 32000 Hz
    6: 24000 Hz
    7: 22050 Hz
    8: 16000 Hz
    9: 12000 Hz
    10: 11025 Hz
    11: 8000 Hz
    12: 7350 Hz
    13: Reserved
    14: Reserved
    15: frequency is written explictly
channel_configuration:声道
    0: Defined in AOT Specifc Config
    1: 1 channel: front-center
    2: 2 channels: front-left, front-right
    3: 3 channels: front-center, front-left, front-right
    4: 4 channels: front-center, front-left, front-right, back-center
    5: 5 channels: front-center, front-left, front-right, back-left, back-right
    6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
    7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel
    8-15: Reserved转
frame_length:包括adts长度和aac原始数据流长度
adts_buffer_fullness:0x7FF 说明是码率可变的码流




二 aac数据体
aac数据体就是将pcm数据经过aac压缩后的数据。

AAC,全称Advanced Audio Coding,是一种专为声音数据设计的文件压缩格式。与MP3不同,它采用了全新的算法进行编码,更加高效,具有更高的“性价比”。利用AAC格式,可使人感觉声音质量没有明显降低的前提下,更加小巧。苹果ipod、诺基亚手机支持AAC格式的音频文件。
优点:相对于mp3,AAC格式的音质更佳,文件更小。
不足:AAC属于有损压缩的格式,与时下流行的APE、FLAC等无损格式相比音质存在“本质上”的差距。加之,传输速度更快的USB3.0和16G以上大容量MP3正在加速普及,也使得AAC头上“小巧”的光环不复存在。
以上这些都能从百度百科搜索到,就不赘述。


三 aac文件解析
下面贴一下我实现的aac文件解析代码。(从aac文件中提取一帧一帧的aac语音数据)

#ifndef _AAC_JITTER_H__
#define _AAC_JITTER_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#pragma pack(1)
struct ADTS_Head
{
unsigned char syncword1;


unsigned char protection_absent:1;
unsigned char layer:2;
unsigned char ID:1;
unsigned char syncword2:4;

unsigned char channel_conf1:1;
unsigned char private_bit:1;
unsigned char sample_freq_index:4;
unsigned char profile:2;

unsigned char aac_frame_lenght1:2;
unsigned char copyright_identify_start:1;
unsigned char copyright_identif_bit:1;
unsigned char home:1;
unsigned char origin_copy:1;
unsigned char channel_conf2:2;


unsigned char aac_frame_lenght2;

unsigned char adts_buffer_fullness1:5;
unsigned char aac_frame_lenght3:3;

unsigned char number_of_raw_data:2;
unsigned char adts_buffer_fullness2:6;


void DUMP()
{
printf("synword#### %d %d\n",syncword1,syncword2);
printf("id#### %d\n",ID);
printf("layer#### %d\n",layer);
printf("protection_absent#### %d\n",protection_absent);
printf("profile#### %d\n",profile);
printf("sampleing_freq_index#### %d\n",sample_freq_index);
printf("private_bit#### %d\n",private_bit);
printf("channel_configure#### %d %d\n",channel_conf1,channel_conf2);
printf("origin_copy#### %d\n",origin_copy);
printf("home#### %d\n",home);
printf("identify_bit#### %d\n",copyright_identify_start);
printf("identify_start#### %d\n",copyright_identif_bit);
printf("frame_len#### %d %d %d\n",aac_frame_lenght1,aac_frame_lenght2,aac_frame_lenght3);
printf("buffer_fullness#### %d %d\n",adts_buffer_fullness1,adts_buffer_fullness2);
printf("raw_data_block#### %d\n",number_of_raw_data);
}
};


#define MAX_AAC_JITTER_SIZE (10240)
#define AAC_JITTER_NOT_FULL (0)
#define MAX_FRAME_COUNT (10000)


struct FrameInfo
{
char *offset;
int len;
};
class AACJitter
{
public:
AACJitter();

~AACJitter();


bool Init();

int AddAACDataToJitter(char *buf,int len);


char *GotOneFrame(int &len);


bool GetFrameHead(char *buf,int inlen,int &offset_len);

private:
char *jitter_mem_;
int data_len_;
FrameInfo frame_info_[MAX_FRAME_COUNT];
int frame_count_;
int frame_get_index_;
};
#endif


#include "aac_jitter.h"


AACJitter::AACJitter()
{
    jitter_mem_ = NULL;
    data_len_ = 0;
    memset(frame_info_,0x0,sizeof(FrameInfo)*MAX_FRAME_COUNT);
    Init();
}


AACJitter::~AACJitter()
{
    if(jitter_mem_)
    {
        free(jitter_mem_);
        jitter_mem_ = NULL;
    }
}


bool AACJitter::Init()
{
    if(jitter_mem_ != NULL)
    {
        return false;
    }


    jitter_mem_ = (char*)malloc(MAX_AAC_JITTER_SIZE*MAX_FRAME_COUNT);
    if(jitter_mem_ == NULL)
    {
        return false;
    }
    return true;
}


int AACJitter::AddAACDataToJitter(char *buf,int len)
{
    if(data_len_ + len > MAX_AAC_JITTER_SIZE*MAX_FRAME_COUNT)
    {
        return -1;
    }


    memcpy(jitter_mem_ + data_len_,buf,len);
    data_len_ += len;


    int parse_offset = 0;
    char *parse_buffer = NULL;
    int frame_len = 0;
    int parse_index = 0;
    int offset_len = 0;
    while(GetFrameHead(jitter_mem_ + parse_offset,data_len_ - parse_offset,offset_len))
    {
        parse_offset += offset_len;
        parse_buffer = jitter_mem_ + parse_offset;
        ADTS_Head *head = (ADTS_Head*)parse_buffer;
        frame_len = head->aac_frame_lenght2 * 8 + head->aac_frame_lenght3;
        if(frame_len > 1024)
        {
            parse_offset += 2;
        }
        
        frame_info_[parse_index].offset = parse_buffer;
        frame_info_[parse_index ++].len = frame_len;
        parse_offset += frame_len;
        if(parse_index >= MAX_FRAME_COUNT - 1)
        {
            break;
        }
    }
    frame_get_index_ = 0;
    frame_count_ = parse_index;
    return parse_index;
}


char *AACJitter::GotOneFrame(int &len)
{
    if(frame_get_index_ >= frame_count_)
    {
        frame_get_index_ = 0;
        //return NULL;
    }
    len = frame_info_[frame_get_index_].len;  
    return frame_info_[frame_get_index_ ++].offset;
}


bool AACJitter::GetFrameHead(char *buf,int inlen,int &offset_len)
{
    for(int i = 0;i<inlen;i++)
    {        
        if(buf[i]&0xff == 0xff) 
        {
            if(buf[i + 1]&0xf0 == 0xf0)
            {
                offset_len = i;
                return true;
            }
        }
    }
    return false;
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值