前面主要讲了介绍AAC的ADTS格式的原理,接下来用C语言来实现AAC的ADTS格式的解析,从而获取acc文件的相关属属性,比如采样率、每一帧的大小、声道数等。
ADTS头一般是7个字节,主要是由固定头信息:adts_fixed_header()和 可变头信息:adts_variable_header()组成。只需从acc文件开头处读取七个字节,然后结合头信息各个成员所占用的位数进行解析即可。
解析代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>
struct adts_fixed_header
{
unsigned int syncword;
unsigned int sample;
unsigned int channel_configurion;
unsigned short int layer;
unsigned short int profile;
unsigned char ID;
unsigned char protection_absebt;
unsigned char private_bit;
unsigned char original_copy;
unsigned char home;
}adts_fixed_header_st={0};
struct adts_variable_header
{
char copyright_identification_bit;
char copyright_identification_start;
unsigned short int frame_length;
unsigned short int adts_buffer_fullness;
char number_of_raw_data_blocks_in_frame;
}adts_variable_header_st = {0};
int ptint_adts_fixed_header(struct adts_fixed_header adts_header)
{
printf("adts_header.syncword = %x\n",adts_header.syncword);
printf("adts_header.ID = %x\n",adts_header.ID);
printf("adts_header.layer = %x\n",adts_header.layer);
printf("adts_header.protection_absebt = %x\n",adts_header.protection_absebt);
printf("adts_header.profile = %x\n",adts_header.profile);
printf("adts_header.sample = %x\n",adts_header.sample);
printf("adts_header.private_bit = %x\n",adts_header.private_bit);
printf("adts_header.channel_configurion = %x\n",adts_header.channel_configurion);
printf("adts_header.original_copy = %x\n",adts_header.original_copy);
printf("adts_header.home = %x\n",adts_header.home);
return 0;
}
int ptint_adts_variable_header(struct adts_variable_header adts_header)
{
printf("adts_header.copyright_identification_bit = %x\n",adts_header.copyright_identification_bit);
printf("adts_header.copyright_identification_start = %x\n",adts_header.copyright_identification_start);
printf("adts_header.frame_length = %x\n",adts_header.frame_length);
printf("adts_header.adts_buffer_fullness = %x\n",adts_header.adts_buffer_fullness);
printf("adts_header.number_of_raw_data_blocks_in_frame = %x\n",adts_header.number_of_raw_data_blocks_in_frame);
return 0;
}
int get_adts_fixed_header(struct adts_fixed_header* adts_header, const unsigned char *data)
{
if(adts_header == NULL || data == NULL)
{
printf("adts_header or data is NULL!\n");
}
adts_header->syncword = (data[0] << 4) + (data[1] >> 4);
adts_header->ID = (data[1] >> 2) & 0x1;
adts_header->layer = (data[1] >> 1) & 0x3;
adts_header->protection_absebt = data[1] & 0x1;
adts_header->profile = (data[2] >> 6) & 0x3;
adts_header->sample = (data[2] >> 2) & 0xf;
adts_header->private_bit = (data[2] >> 1)&0x1;
adts_header->channel_configurion = ((data[2] & 0x1) << 2) + ((data[3] >> 6) & 0x3);
adts_header->original_copy =(data[3] >> 5) & 0x1;
adts_header->home =(data[3] >> 4) & 0x1;
return 0;
}
int get_adts_variable_header(struct adts_variable_header* adts_header, const unsigned char *data)
{
if(adts_header == NULL || data == NULL)
{
printf("adts_header or data is NULL!\n");
}
adts_header->copyright_identification_bit = (data[3] >> 3) & 0x1;
adts_header->copyright_identification_start = (data[3] >> 2) & 0x1;
adts_header->frame_length = ((data[3] & 0x3) << 11) + (data[4] << 3) + ((data[5] >> 5) & 0x7);
adts_header->adts_buffer_fullness = ((data[5] & 0x1f) << 6) + ((data[6] >> 2) & 0x3f);
adts_header->number_of_raw_data_blocks_in_frame = data[6]& 0x3;
return 0;
}
int main(int argc,char **argv )
{
unsigned char data[7];
char *finename="mp3.aac";
FILE* fp = NULL;
fp = fopen(finename, "r");
if(NULL == fp)
{
printf("open file file failed!");
return -1;
}
else
{
fread(data, 7, 1, fp);
fclose(fp);
}
get_adts_fixed_header(&adts_fixed_header_st,data);
get_adts_variable_header(&adts_variable_header_st,data);
ptint_adts_fixed_header(adts_fixed_header_st);
ptint_adts_variable_header(adts_variable_header_st);
return 0;
}
结果打印信息:
root@chen:/home/chenjg/share/test/audio# ./test
adts_header.syncword = fff
adts_header.ID = 0
adts_header.layer = 0
adts_header.protection_absebt = 1
adts_header.profile = 1
adts_header.sample = 4
adts_header.private_bit = 0
adts_header.channel_configurion = 1
adts_header.original_copy = 0
adts_header.home = 0
adts_header.copyright_identification_bit = 0
adts_header.copyright_identification_start = 0
adts_header.frame_length = 1d
adts_header.adts_buffer_fullness = 7ff
adts_header.number_of_raw_data_blocks_in_frame = 0
通过软件解析acc文件的数据情况如图所示:
源码路径(包含acc文件读取软件)
链接:https://pan.baidu.com/s/1WjHvD2gpUqZ1O7zb_Y37UA
提取码:p667