文章目录
- AAC是一种音频压缩技术,是有损压缩(线性pcm是无损)
- AAC压缩比通常为18:1,也有资料说为20:1,远胜mp3
- AAC可以支持多达48个音轨,15个低频(LFE)音轨,5.1多声道支持;
- 更高的采样率,最高可达96kHz,音频CD为44.1kHz;
- 更高的采样精度,支持8bit、16bit、24bit、32bit,音频CD为16bit;
- 以及有多种语言的兼容能力,更高的解码效率,
- 一般来说,AAC可以在比MP3文件缩小30%的前提下提供更好的音质AAC规格与编解码器
目前听到用的比较多的应该是 LC-AAC、HE-AAC、Main(主规格)、SSR(可变采样率)等规格
常见的AAC编解码有: NERO AAC
, QuikTime AAC
, FAAC
format
AAC编码的扩展名有: .aac .mp4
aac
:使用ADTS容器(ADIF不常见,必须从开头开始解码,用在磁盘文件中),也是faac默认的封装格式
mp4
:使用3gpp(MPEG4-Part14)进行封装,Nero AAC 编码器使用该封装格式
m4a
:苹果公司使用的封装格式,等同于 MP4封装格式,可以直接改动扩展名
FAAC
faac
是免费的编解码器它包括:faac(encode),faad2(decode)
支持 LC, Main, HE 等解码规格
支持 ADTS AAC, raw AAC, MP4 等文件格式
对应的两个库接口是 libfaac
,libfaad
FAAD 解码中最小的音频流大小为768B,而8K单声道的音频流为384B
解码中一次最少也应该为768B所以某些情况下可能要求拼凑
LC-AAC
Low Complexity
,低复杂度AAC规格
这种规格在"中等码率"(96kbps-192kbps)的编码效率以及音质方面,都能找到平衡点。
HE-AAC
high efficiency
,高效,HE 使用了 SBR 技术和 PS 技术(V2):
encoding
// 获取FAAC版本信息
char *faac_id_string;
char *faac_copyright_string
if (faacEncGetVersion(&faac_id_string, &faac_copyright_string) == FAAC_CFG_VERSION)
fprintf(stderr, "FAAC Version: %s\n\n", faac_id_string);
else {
fprintf(stderr, __FILE__"(%d): wrong lib faac version", __LINE__);
return 1;
}
// 打开FAAC编码器
unsigned long samplesInput, maxBytesOutput;
faacEncHandle hEncoder = faacEncOpen(44100, 1, &samplesInput, &maxBytesOutput);
// 设置FAAC编码器属性
faacEncConfiguration* myFormat = faacEncGetCurrentConfiguration(hEncoder);
myFormat.aacObjectType = LOW;
myFormat.mpegVersion = MPEG2;
myFormat.allowMidside = 0;
myFormat.useLfe = 0
myFormat.useTns = 0;
myFormat.shortctrl = SHORTCTL_NORMAL;
myFormat.bitRate = 44100 / 1; // bitrate/channels
myFormat.quantqual = 0;
myFormat.outputFormat = 1; // 0,RAW; 1,ADTS(音频数据传送流)
myFormat.inputFormat = 1; // FAAC_INPUT_16BIT
if (!faacEncSetConfiguration(hEncoder, myFormat)) {
fprintf(stderr, "Unsupported output format!\n");
faacEncClose(hEncoder);
}
// 真实的编解码
unsigned char* pOutBuf = (unsigned char*) malloc(maxBytesOutput *sizeof( unsigned char ));
while (1) {
int bytesEncoded;
memset(pOutBuf, 0, maxBytesOutput);
bytesEncoded = faacEncEncode(hEncoder,(short*)pInputBuf, samplesInput, pOutBuf, maxBytesOutput);
if (!bytesEncoded || !samplesInput)
break;
if (bytesEncoded < 0) {
fprintf(stderr, "faacEncEncode() failed\n");
break;
}
/* write bitstream to aac file */
fwrite(bitbuf, 1, bytesEncoded, outfile);
}
// 关闭编码器
faacEncClose(hEncoder);
decoding
unsigned long cap = faacDecGetCapabilities();
if (cap & FIXED_POINT_CAP) fprintf(stderr, "error");
faacDecHandle hAacDec = faacDecOpen();
faacDecConfiguration* pAacCfg = faacGetCurrentConfiguration(hAacDec);
faacDecSetConfiguration(hAacDec, pAacCfg);
// 初始化
unsigned char* pInitBuf = (unsigned char*)malloc(pInitBuf, FAAD_MIN_STREAMSIZE*MAX_CHANNELS);
// 填进去一些压缩的音频数据调用
unsigned long sampleRate;
unsigned char channels;
int temp = faacDecInit(hAacDec, pInitBuf, FAAD_MIN_STREAMSIZE*MAX_CHANNELS, &sampleRate, &channels);
if (temp < 0) {
// faacDecClose(hAacDec);
}
unsigned char* pInputBuf = (unsigned char*)malloc(pInputBuf, FAAD_MIN_STREAMSIZE*MAX_CHANNELS);
faacDecFrameInfo frameInfo;
do {
/** 向pInputBuf放入 src Data 解码 **/
void* sample_buffer = faacDecDecode(hDecoder, &frameInfo, pInputBuf, FAAD_MIN_STREAMSIZE*MAX_CHANNELS);
if ((frameInfo.error == 0) && (frameInfo.samples > 0)) {
// fwrite返回实际写入的字节数当出错时文件指针就混乱了
fwrite(sample_buffer, 1, frameInfo.samples, FILE*);
}
if (frameInfo.error > 0)
fprintf(stderr, "warning: %s", faacDecGetErrorMessage(frameInfo.error));
} while (sample_buffer != NULL);
faacDecClose(hAacDec);