faad2解码aac到pcm

原创 2017年01月03日 16:51:26
//解码AAC音频为PCM数据

#pragma once
#include "libfaad2/include/faad.h"

//aac数据状态
typedef enum AccDataStatus
{
	AccDataStatus_NotKnown			=		0x00,			//未知
	AccDataStatus_InValid			=		0x01,			//非法
	AccDataStatus_Valid				=		0x02,			//合法
};


class AAC2PCM
{
public:
	AAC2PCM(void);
	virtual ~AAC2PCM(void);

/**
 * fetch one ADTS frame
 */
int get_one_ADTS_frame(unsigned char* buffer, size_t buf_size, unsigned char* data ,size_t* data_size);

//初始化
int init(unsigned char defObjectType=2,unsigned long defSampleRate = 8000);

//反初始化
int uninit();

//检测数据是否合法
int detectFirstPackageData(unsigned char* bufferAAC, size_t buf_sizeAAC);

//获取第一数据包状态
int getFirstPackageAccDataStatus();
//重置第一数据包状态
void clearFirstPackageAccDataStatus(int nAccDataStatus);

//转换
int convert(unsigned char* bufferAAC, size_t buf_sizeAAC,unsigned char* bufferPCM, size_t & buf_sizePCM);
int convert2(unsigned char* bufferAAC, size_t buf_sizeAAC, unsigned char* bufferPCM, size_t & buf_sizePCM);

protected:
	unsigned long samplerate;
	unsigned char channels;
	NeAACDecHandle decoder;
	NeAACDecFrameInfo frame_info;
	int m_nFirstPackageAccDataStatus;		//第一数据包状态
	bool m_bNeAACDecInit;
};


#include "AAC2PCM.h"
#include <stdio.h>
#include <memory.h>
#include "libsamplerate/samplerate.h"
#pragma comment(lib,"libfaad2/lib/libfaad2.lib")
#pragma comment(lib,"libsamplerate/libsamplerate.lib")
#define FRAME_MAX_LEN 1024*5 
#define BUFFER_MAX_LEN 1024*1024

static unsigned char frame[FRAME_MAX_LEN] = {0};
unsigned int framesize = FRAME_MAX_LEN;
//static unsigned char buffer[BUFFER_MAX_LEN] = {0};

AAC2PCM::AAC2PCM(void)
{
	samplerate = 1;
	channels = 1;
	decoder = 0;
	m_nFirstPackageAccDataStatus = AccDataStatus_NotKnown;
}

AAC2PCM::~AAC2PCM(void)
{
}

/**
 * fetch one ADTS frame
 */
int AAC2PCM::get_one_ADTS_frame(unsigned char* buffer, size_t buf_size, unsigned char* data ,size_t* data_size)
{
    size_t size = 0;

    if(!buffer || !data || !data_size )
    {
        return -1;
    }

    while(1)
    {
        if(buf_size  < 7 )
        {
            return -1;
        }

		if ((buffer[0] == 0xff) && ((buffer[1] & 0xf0) == 0xf0))
		{
			// profile; 2 uimsbf
			// sampling_frequency_index; 4 uimsbf
			// private_bit; 1 bslbf
			// channel_configuration; 3 uimsbf
			// original/copy; 1 bslbf
			// home; 1 bslbf
			// copyright_identification_bit; 1 bslbf
			// copyright_identification_start; 1 bslbf
			// frame_length; 13 bslbf

			size |= (((buffer[3] & 0x03)) << 11);//high 2 bit
			size |= (buffer[4] << 3);//middle 8 bit
			size |= ((buffer[5] & 0xe0) >> 5);//low 3bit

			printf("len1=%x\n", (buffer[3] & 0x03));
			printf("len2=%x\n", buffer[4]);
			printf("len3=%x\n", (buffer[5] & 0xe0) >> 5);
			printf("size=%d\r\n", (int)size);
			break;
		}
        --buf_size;
        ++buffer;
    }

    if(buf_size < size)
    {
        return -1;
    }

    memcpy(data, buffer, size);
    *data_size = size;
    
    return 0;
}

//初始化
int AAC2PCM::init(unsigned char defObjectType,unsigned long defSampleRate)
{
	m_nFirstPackageAccDataStatus = AccDataStatus_NotKnown;
	//open decoder
	decoder = NeAACDecOpen();
	NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);
	/*conf->defObjectType = defObjectType;
	conf->defSampleRate = defSampleRate;
	conf->outputFormat = FAAD_FMT_16BIT ; //
	*/
	conf->defObjectType = LC;
	conf->defSampleRate = 8000; //real samplerate/2
	conf->outputFormat = FAAD_FMT_16BIT; //
	conf->dontUpSampleImplicitSBR = 1;
	unsigned char nRet = NeAACDecSetConfiguration(decoder, conf);
	m_bNeAACDecInit = false;

	return 0;
}

//反初始化
int AAC2PCM::uninit()
{
	NeAACDecClose(decoder);
	return 0;
}

//检测数据是否合法
int AAC2PCM::detectFirstPackageData(unsigned char* bufferAAC, size_t buf_sizeAAC)
{
	size_t size = 0;
	if(get_one_ADTS_frame(bufferAAC, buf_sizeAAC, frame, &size) < 0)
	{
		m_nFirstPackageAccDataStatus = AccDataStatus_InValid;
		return -1;
	}
	m_nFirstPackageAccDataStatus  = AccDataStatus_Valid;
	return 0;
}

//获取第一数据包状态
int AAC2PCM::getFirstPackageAccDataStatus()
{
	return m_nFirstPackageAccDataStatus;
}
//重置第一数据包状态
void AAC2PCM::clearFirstPackageAccDataStatus(int nAccDataStatus)
{
	m_nFirstPackageAccDataStatus = nAccDataStatus;
}

//转换
int AAC2PCM::convert(unsigned char* bufferAAC, size_t buf_sizeAAC,unsigned char* bufferPCM, size_t & buf_sizePCM)
{
	if (m_nFirstPackageAccDataStatus != AccDataStatus_Valid)
		return -1;

	size_t size = 0;
	unsigned char* pcm_data = NULL;
	while(get_one_ADTS_frame(bufferAAC, buf_sizeAAC, frame, &size) == 0)
	{
		// printf("frame size %d\n", size);
		//decode ADTS frame
		pcm_data = (unsigned char*)NeAACDecDecode(decoder, &frame_info, frame, size);

		if(frame_info.error > 0)
		{
			printf("%s\n",NeAACDecGetErrorMessage(frame_info.error));            
			return -1;
		}
		else if(pcm_data && frame_info.samples > 0)
		{
			printf("frame info: bytesconsumed %d, channels %d, header_type %d\
				   object_type %d, samples %d, samplerate %d\n", 
				   frame_info.bytesconsumed, 
				   frame_info.channels, frame_info.header_type, 
				   frame_info.object_type, frame_info.samples, 
				   frame_info.samplerate);

			buf_sizePCM = frame_info.samples * frame_info.channels;
			/*
			//从双声道的数据中提取单通道  
			for (int i = 0, j = 0; i<4096 && j<2048; i += 4, j += 2)
			{
				bufferPCM[j] = pcm_data[i];
				bufferPCM[j + 1] = pcm_data[i + 1];
			}
			*/
			memcpy(bufferPCM,pcm_data,buf_sizePCM);
		}        
		bufferAAC -= size;
		buf_sizeAAC += size;
	}

	return 0;
}

int AAC2PCM::convert2(unsigned char* bufferAAC, size_t buf_sizeAAC, unsigned char* bufferPCM, size_t & buf_sizePCM)
{
	unsigned char* pcm_data = NULL;
	if (!m_bNeAACDecInit)
	{
		//initialize decoder
		NeAACDecInit(decoder, bufferAAC, buf_sizeAAC, &samplerate, &channels);
		printf("samplerate %d, channels %d\n", samplerate, channels);
		m_bNeAACDecInit = true;
	}
	//decode ADTS frame
	pcm_data = (unsigned char*)NeAACDecDecode(decoder, &frame_info, bufferAAC, buf_sizeAAC);

	if (frame_info.error > 0)
	{
		printf("%s\n", NeAACDecGetErrorMessage(frame_info.error));
		return -1;
	}
	else if (pcm_data && frame_info.samples > 0)
	{
		printf("frame info: bytesconsumed %d, channels %d, header_type %d\
			   				   object_type %d, samples %d, samplerate %d\n",
							   frame_info.bytesconsumed,
							   frame_info.channels, frame_info.header_type,
							   frame_info.object_type, frame_info.samples,
							   frame_info.samplerate);

		buf_sizePCM = frame_info.samples * frame_info.channels;
		/*
		//从双声道的数据中提取单通道  
		for (int i = 0, j = 0; i<4096 && i<buf_sizePCM && j<2048; i += 4, j += 2)
		{
			bufferPCM[j] = pcm_data[i];
			bufferPCM[j + 1] = pcm_data[i + 1];
		}
		*/
		memcpy(bufferPCM,pcm_data,buf_sizePCM);
		/*
		float in[4096] = { 0 };
		float out[4096] = { 0 };
		for (int j = 0; j < 4096 && j < buf_sizePCM; j++)
		{
			in[j] = pcm_data[j];
		}
		SRC_DATA dataResample;
		dataResample.data_in = in;
		dataResample.data_out = out;
		dataResample.input_frames = frame_info.samples;
		dataResample.output_frames = frame_info.samples;
		dataResample.src_ratio =  8000.0/frame_info.samplerate;
		int nRetResample = src_simple(&dataResample, SRC_SINC_FASTEST, 2);
		buf_sizePCM = dataResample.output_frames_gen * frame_info.channels;
		memcpy(bufferPCM, dataResample.data_out, buf_sizePCM);
		*/

		return 0;
	}

	return -1;
}

注意事项:

1,解码aac-解决采样频率和通道数不对的问题。

//防止采样频率加倍
NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);
conf->dontUpSampleImplicitSBR = 1;
NeAACDecSetConfiguration(decoder, conf);



//从双声道的数据中提取单通道  
for(i=0,j=0; i<4096 && j<2048; i+=4, j+=2)

{
frame_mono[j]=pcm_data[i];
frame_mono[j+1]=pcm_data[i+1];
}  

2,采样率转换,使用libsamplerate

FAAC和FAAD的下载地址  http://www.audiocoding.com/downloads.html

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

使用FAAD库解码AAC实例及 及 faad解码后的通道数不正确的问题

用FAAD解码时,在NeAACDecInit的时候,是先在之前编码好的aac数据(ADTS头封装的)上往buffer中写入一帧的含ADTS头的数据,然后传入到NeAACDecInit()中初始化解码器...
  • machh
  • machh
  • 2015-07-30 17:38
  • 2914

使用FAAD库解码AAC实例

使用FAAD解码AAC音频为PCM数据流程可以参考下面的文章 http://blog.csdn.net/gavinr/article/details/6959198#reply ...

aac的格式, 以及faad解码raw数据解码

一. ADTS 格式 ADTS全称是(AudioData Transport Stream),是AAC的一种十分常见的传输格式。 一般的AAC解码器都需要把AAC的ES流打包成ADTS的格式,一般...

AAC规格(LC,HE,HEv2)及性能对比

现如今常见的 AAC规格有三种:LC-AAC,HE-AAC(AACPlus v1),HE-AAC v2(AACPlus v2)。他们三个的关系如下图所示: HE:“High Efficiency”...

libfaac使用实例

本文对采集的未压缩声音装换为aac格式 对应录制篇:http://blog.163.com/zhujiatc@126/blog/static/183463820130208928612/ ...

用faad解码AAC(ADTS封装)

一个小程序,使用faad解码AAC音频,只能解码ADTS封装的帧。编译好的程序可以从这里下载:http://download.csdn.net/detail/gavinr/3782154 /**...
  • gavinr
  • gavinr
  • 2011-11-11 11:47
  • 12499

faad2解码aac-解决采样频率和通道数不对的问题

关键代码如下: //防止采样频率加倍 NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder); ...

移植、验证AAC解码库FAAD2到android详解必看

aac是针对音频 进行压缩的一种算法 该编码优点很多。音质好 支持的采样率 声道都很多。在Android上使用非常常见 之前使用ffmepeg 1.1的decode_audio4这个函数 解...

faad2解码aac到pcm (采样频率和通道数问题)

调试成功并导入项目的faad2解码aac示例 包括Test.c和封装好的接口,解决解码后采样频率和通道数问题 下载链接:http://download.csdn.net/detail/yuanch...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)