首页 > 代码库 > 使用FAAC转换PCM为AAC

使用FAAC转换PCM为AAC

关于FAAC

FAAC是一个MPEG-4和MPEG-2的AAC编码器,其特性是:可移植性好,快速,支持LC/Main/LTP,通过Dream支持DRM,代码小相对于FFMPEG的AAC转码,FAAC实在是微乎其微,而且可以直接把代码加到工程里面编译,也可使用静态库,而没有巨大的动态库的烦恼。


下载安装

  • 直接按照官方文档所示,编译静态库以供我们程序使用。(我没这么做,个中曲折错误不细数)
  • 把FAAC的代码抠出来,直接加到我们的工程中去,或者抠出来编译一个静态库,简单暴力有效,需要的代码是libfaac和include两个目录下的所有文件(不包括子目录文件)。 目录文件列表如下所示:
    aacquant.c
    aacquant.h
    backpred.c
    backpred.h
    bitstream.c
    bitstream.h
    channels.c
    channels.h
    coder.h
    faac.h
    faaccfg.h
    fft.c
    fft.h
    filtbank.c
    filtbank.h
    frame.c
    frame.h
    huffman.c
    huffman.h
    hufftab.h
    ltp.c
    ltp.h
    midside.c
    midside.h
    psych.h
    psychkni.c
    tns.c
    tns.h
    util.c
    util.h
    version.h
    强烈推荐使用第二种方法

主要的函数介绍

faacEncHandle FAACAPI faacEncOpen(unsigned long sampleRate,
	unsigned int numChannels,
	unsigned long *inputSamples,
	unsigned long *maxOutputBytes);
//	描述 : 打开并初始化编码器
//	sampleRate : 编码输入信息的采样率
//	numChannels : 编码输入信息的通道数量,1-单声道 2-立体声
//	inputSamples : 编码后的数据长度
//	maxOutputBytes : 编码后的信息最大长度
int FAACAPI faacEncClose(faacEncHandle hEncoder);
//	描述:关闭编码器
//	hEncoder : faacEncOpen返回的编码器句柄
faacEncConfigurationPtr FAACAPI faacEncGetCurrentConfiguration(faacEncHandle hEncoder);
//	描述 :获取当前编码器的配置信息
//	hEncoder : faacEncOpen返回的编码器句柄
int FAACAPI faacEncSetConfiguration(faacEncHandle hEncoder, faacEncConfigurationPtr config);
//	描述 : 配置解码器的参数
//	hEncoder : faacEncOpen返回的编码器句柄
//	config : 编码器的配置信息
int FAACAPI faacEncEncode(faacEncHandle hEncoder, 
	int32_t * inputBuffer, 
	unsigned int samplesInput,
	unsigned char *outputBuffer,
	unsigned int bufferSize);
//	描述 : 编码一桢信息
//	hEncoder : faacEncOpen返回的编码器句柄
//	inputBuffer : 输入信息缓冲区
//	samplesInput : faacEncOpen编码后的数据长度,即缓冲区长度
//	outputBuffer : 编码后输出信息缓冲区
//	bufferSize : 输出信息长度
int FAACAPI faacEncGetVersion(char **faac_id_string, char **faac_copyright_string);
//	描述 : 获取FAAC的版本信息,用以参考作用,非必须API
//	faac_id_string : faac的版本号
//	faac_copyright_string : 版权信息

代码示例

代码的工作流程是:
  1. 打开输入输出文件
  2. 使用faacEncOpen打开编码器引擎
  3. 使用faacEncGetCurrentConfiguratio获取编码器配置
  4. 配置编码器参数
  5. 使用faacEncSetConfiguration设置编码器配置
  6. 读取一桢输入数据
  7. 使用faacEncEncode编码帧数据
  8. 写入编码数据到输出文件
  9. 使用faacEncClose关闭编码引擎
//  
//  faac example code
//  PCM to ACC  
//  
//  Created by arbboter on 15/1/26.  
//  Copyright (c) 2015年 arbboter. All rights reserved.  
// 
#include "faac.h"
#include <stdio.h>

int main()
{
	// 定义别名
	typedef unsigned char   BYTE;

	unsigned long	nSampleRate = 44100;
	unsigned int	nChannels = 2;
	unsigned int	nPCMBitSize = 16;
	unsigned long	nInputSamples = 0;
	unsigned long	nMaxOutputBytes = 0;
	faacEncHandle	hEncoder = {0};

	// 设置输入输出文件
	FILE* fpIn = fopen("Beyond.pcm", "rb");
	FILE* fpOut = fopen("Beyond.aac", "wb");

	if(fpIn==NULL || fpOut==NULL)
	{
		printf("打开文件失败!\n");
		return -1;
	}

	// 打开faac编码器引擎
	hEncoder = faacEncOpen(nSampleRate, nChannels, &nInputSamples, &nMaxOutputBytes);
	if(hEncoder == NULL)
	{
		printf("打开faac编码器引擎失败!\n");
		return -1;
	}

	// 分配内存信息
	int		nPCMBufferSize = nInputSamples*nPCMBitSize/8;
	BYTE*	pbPCMBuffer = new BYTE[nPCMBufferSize];
	BYTE*	pbAACBuffer = new BYTE[nMaxOutputBytes];

	// 获取当前编码器信息
	faacEncConfigurationPtr pConfiguration = {0};
	pConfiguration = faacEncGetCurrentConfiguration(hEncoder);

	// 设置编码配置信息
	/*
		PCM Sample Input Format
		0	FAAC_INPUT_NULL			invalid, signifies a misconfigured config
		1	FAAC_INPUT_16BIT		native endian 16bit
		2	FAAC_INPUT_24BIT		native endian 24bit in 24 bits		(not implemented)
		3	FAAC_INPUT_32BIT		native endian 24bit in 32 bits		(DEFAULT)
		4	FAAC_INPUT_FLOAT		32bit floating point
    */
	pConfiguration->inputFormat = FAAC_INPUT_16BIT;

	// 0 = Raw; 1 = ADTS
	pConfiguration->outputFormat = 1;

	// AAC object types 
	//#define MAIN 1
	//#define LOW  2
	//#define SSR  3
	//#define LTP  4
	pConfiguration->aacObjectType = LOW;
	pConfiguration->allowMidside = 0;
	pConfiguration->useLfe = 0;
	pConfiguration->bitRate = 48000;
	pConfiguration->bandWidth = 32000;

	// 其他的参数不知道怎么配置,毕竟对音频不熟
	// 不过当前的设置可以实现转换,不过声音好像有一丢丢怪异
	// 这一块的配置信息很重要,错了会导致转码失败,然后你以为代码其他地方错了

	// 重置编码器的配置信息
	faacEncSetConfiguration(hEncoder, pConfiguration);

	size_t nRet = 0;

	printf("数据转换中:        ");
	int i = 0;
	while( (nRet = fread(pbPCMBuffer, 1, nPCMBufferSize, fpIn)) > 0)
	{
		printf("\b\b\b\b\b\b\b\b%-8d", ++i);
		nInputSamples = nRet / (nPCMBitSize/8);

		// 编码
		nRet = faacEncEncode(hEncoder, (int*) pbPCMBuffer, nInputSamples, pbAACBuffer, nMaxOutputBytes);

		// 写入转码后的数据
		fwrite(pbAACBuffer, 1, nRet, fpOut);
	}

	// 扫尾工作
	faacEncClose(hEncoder);
	fclose(fpOut);
	fclose(fpIn);

	delete[] pbAACBuffer;
	delete[] pbPCMBuffer;
	
	return 0;
}

编码器的参数设置,可以找正确的解码例子照例修改或者问专业人士吧,如果出错了的话。

使用FAAC转换PCM为AAC