faad2是AAC音频解码的lib,支持MPEG2和MPEG4格式的audio解码。代码下载网址:https://www.linuxfromscratch.org/blfs/view/svn/multimedia/faad2.html。
解压:
tar xvzf faad2-2_10_0.tar.gz
cd faad2-2_10_0/
./configure --host=mips-linux-gnu CC=mips-linux-uclibc-gnu-gcc --enable-shared --prefix=$(pwd)/install
make
这里会出现一个错误,audio.c文件中没有frexp。这个函数是math.h中的函数,已经包含了这个头文件,还是提示错误, 估计指定编译器为uclibc。包含库不完整导致的。
注释掉 frexp函数相关语句可以通过编译。
make install
faad2库使用方法如下:
void *RX_Audio_Decode_Play_Thread(void *argv)
{
VRbuf_s *RxAudioBuf;
static unsigned char frame[FRAME_MAX_LEN];
unsigned long samplerate;
unsigned char channels;
NeAACDecHandle decoder = 0;
size_t size = 0;
NeAACDecFrameInfo frame_info;
unsigned char* pcm_data = NULL;
//open decoder
decoder = NeAACDecOpen();
RxAudioBuf= GetRxAudioStream();//从缓冲区中接收音频数据
if(get_one_ADTS_frame(RxAudioBuf->buf, RxAudioBuf->len, frame, &size) < 0)
{
printf("get_one_ADTS_frame file");
return -1;
}
/************************************************
get_one_ADTS_frame这里获取一帧数据是为了下面
NeAACDecInit做准备。NeAACDecInit要输入一个size。
************************************************/
//initialize decoder
NeAACDecInit(decoder, frame, size, &samplerate, &channels);
printf("samplerate %d, channels %d\n", samplerate, channels);
Audio_Play_Initial();
while(1)
{
RxAudioBuf= GetRxAudioStream();
if(get_one_ADTS_frame(RxAudioBuf->buf, RxAudioBuf->len, frame, &size) == 0)
{
pcm_data = (unsigned char*)NeAACDecDecode(decoder, &frame_info, frame, size);
if(frame_info.error > 0)
{
printf("%s\n",NeAACDecGetErrorMessage(frame_info.error));
}
else if(pcm_data && frame_info.samples > 0)
{
Audio_Play_Start(pcm_data,frame_info.samples * frame_info.channels);
}
}
DeleteAudioSream_List(RxAudioBuf);//删除这缓冲区
}
NeAACDecClose(decoder);
Audio_Play_DeInitial();
}
下面来源网络。
faad2解码aac到pcm_深之JohnChen的专栏-CSDN博客_faad2
#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];
}
————————————————
版权声明:本文为CSDN博主「byxdaz」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/byxdaz/article/details/53995837
本文介绍了AAC音频解码库faad2的使用方法,包括编译步骤、代码示例以及如何处理编译时遇到的`frexp`函数缺失问题。通过示例代码展示了如何解码AAC音频数据到PCM格式,并提供了转换和播放的流程。此外,还提到了防止采样频率加倍和从双声道数据中提取单声道的处理方式。

1917

被折叠的 条评论
为什么被折叠?



