使用fdk-aac完成aac ld解码

    对于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用于实时音视频通信中,相对小众.

附表格为

索引采样频率
096k
188.2k
264k
348k
444.1k
532k
624k
722.05k
816k
912k
a11.025k
b8k
c7.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流.

 

 

fdk-aac是一个开源的AAC音频解码器库,它支持高效率的AAC解码。一个fdk-aac解码示例通常包括以下几个步骤: 1. 初始化解码器:在开始解码之前,需要对解码器进行初始化操作,这可能涉及到设置解码器的配置参数、分配必要的资源等。 2. 解码操作:通过调用解码器提供的API,将包含AAC编码数据的输入缓冲区传递给解码器,解码器将处理这些数据,并将解码后的音频数据存放到输出缓冲区中。 3. 清理和释放资源:解码操作完成后,需要清理解码器并释放分配的资源,确保不会发生内存泄漏。 下面是一个简化的fdk-aac解码过程的伪代码示例: ```c #include "fdk-aac/fix_aacdec_lib.h" // 初始化解码aacDecoderStruct* decoder = aacDecoder_Open(DecoderMode_AAC); // 设置解码器参数(如果需要) aacDecoder_SetParam(decoder, AAP_DECODER_PARAM_SET蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊蘊 // 解码AAC数据 // inputBuffer是包含AAC编码数据的缓冲区 // inputSize是缓冲区中AAC数据的大小 // outputBuffer是解码后的PCM数据存放的缓冲区 // outputSize是输出缓冲区的大小,通常由解码器自动计算 aacDecoder_Error err = aacDecoder_Fill(decoder, inputBuffer, inputSize, outputBuffer, &outputSize); if (err == AACDEC_OK) { // 解码成功,处理outputBuffer中的PCM数据 } else { // 解码出错,处理错误 } // 清理和释放解码器资源 aacDecoder_Close(decoder); ``` 需要注意的是,这只是一个大致的流程和代码结构,实际应用中可能需要根据具体的库函数和API进行相应的调整。而且,示例中并未包含错误处理和资源管理的完整代码,实际开发中应该添加必要的异常处理逻辑,确保程序的健壮性。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值