😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍faac编码库的使用 🍭
⏰发布时间⏰: 2025-03-05 18:47:37
本文未经允许,不得转发!!!
目录
- 🎄一、概述
- 🎄二、下载、编译、交叉编译
- ✨2.1 faac 下载
- ✨2.2 faac 在Ubuntu下编译
- ✨2.3 faac 交叉编译
- 🎄三、faac 编码库使用流程
- 🎄四、faac 编码的例子代码
- 🎄五、总结
🎄一、概述
faac
的全称是 Freeware Advanced Audio (AAC) Coder
,faac 是一个用于将原始音频数据(如 PCM 格式)编码为 AAC 格式的开源库。它实现了 AAC 编码算法,能够对音频信号进行高效的压缩,同时尽可能保留音频的原始质量。FAAC 提供了简单易用的 API,方便开发者在不同的应用程序中集成 AAC 编码功能。
faac 支持多种 AAC 音频格式,包括 LC - AAC(Low Complexity AAC)、HE - AAC(High Efficiency AAC)、HE - AAC v2 、MAIN 、 LTP等。这使得开发者可以根据不同的应用需求选择合适的编码标准,以平衡音频质量和文件大小。例如,在对音频质量要求较高且带宽充足的场景下,可以选择 LC - AAC;而在带宽有限的情况下,HE - AAC 或 HE - AAC v2 则能提供更好的压缩比。
🎄二、下载、编译、交叉编译
✨2.1 faac 下载
faac 的源码在Github托管,下载地址:https://github.com/knik0/faac/tags。本文下载的是倒数第二个版本:faac-1_30.tar.gz
,见下图。如果GitHub访问不了可以点击这个链接下载:https://download.csdn.net/download/wkd_007/90456911
✨2.2 faac 在Ubuntu下编译
这个小节介绍 faac 的源码在 Ubuntu 18.04 系统下编译的步骤:
-
将源码解压缩
tar zxf faac-1_30.tar.gz
-
进入源码目录,执行下面命令生成Makefile:
cd faac-1_30/ ./bootstrap ./configure --prefix=`pwd`/../result_gcc
-
执行make 、make install
make make install
编译成功后,会在源码目录的上一级目录生成一个result_gcc
目录,里面就是我们的编译结果。
✨2.3 faac 交叉编译
这个小节介绍 faac 的源码在 Ubuntu 18.04 系统下使用 aarch64-mix210-linux-gcc
交叉编译的步骤:
- 将源码解压缩
tar zxf faac-1_30.tar.gz
- 进入源码目录,执行下面命令生成Makefile:
cd faac-1_30/ ./bootstrap ./configure --prefix=`pwd`/../result_mix210 --host=aarch64-mix210-linux CC=aarch64-mix210-linux-gcc
- 执行make 、make install
make make install
编译成功后,会在源码目录的上一级目录生成一个result_mix210
目录,里面就是我们的编译结果。
🎄三、faac 编码库使用流程
在 faac 源码里有一个pdf文件,介绍了 faac 库的使用,文件路径:faac-1_30\docs\libfaac.pdf
,文件介绍了faac常用的的API函数和简单使用流程,感兴趣的可以自己去看,下面是我总结的使用流程:
-
1、打开 FAAC 编码器句柄:
faacEncOpen
faacEncHandle pFaacEncHandle = faacEncOpen(u64PcmSampleRate, u32PcmChannels, &u64PcmInSampleCnt, &u64AacOutMaxBytes);
-
2、设置编码器的配置信息
pFaacEncConf = faacEncGetCurrentConfiguration(pFaacEncHandle); ... // 设置编码器的配置信息 faacEncSetConfiguration(pFaacEncHandle, pFaacEncConf);
-
3、调用 faacEncEncode()对数据进行编码
s32EncAacBytes = faacEncEncode(pFaacEncHandle, (int32_t*)pu8PcmInBuf, u32PcmInSampleCnt, pu8AacEncBuf, (unsigned int)u64AacOutMaxBytes);
-
4、关闭 FAAC 编码器句柄
/* 用完了就关闭编码器 */ faacEncClose(pFaacEncHandle);
🎄四、faac 编码的例子代码
下面是根据流程写的例子,保存后,执行 gcc pcm2aac.c -I result_gcc/include/ result_gcc/lib/libfaac.a -lm
编译。
代码来自:音频demo:使用faac将PCM数据编码成aac数据
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>#include "faac.h"//#define DEBUG(fmt, args...)
#define DEBUG(fmt, args...) printf(fmt, ##args)void print_usage(const char *process)
{printf("sample: \n""\t %s -h\n""\t %s --help\n""\t %s -i ./audio/test_8000_16_1.pcm -r 8000 -b 16 -c 1 -o out_8khz_1ch.aac\n""\t %s --input_pcmfile=./audio/test_44100_16_2.pcm --sample_rate=44100 --sample_bits=16 --channels=2 --output_aacfile=out_44.1khz_2ch.aac\n",process, process, process, process);
}int main(int argc, char *argv[])
{/* 输入/输出文件 */FILE *fpPcm = NULL;FILE *fpAac = NULL;char pcmFileName[128] = {0};char aacFileName[128] = {0};/* PCM参数 */unsigned long u64PcmSampleRate = 0; // 采样率unsigned int u32PcmSampleBits = 0; // 采样位数unsigned int u32PcmChannels = 0; // 声道数/* aac编码器相关 */faacEncHandle pFaacEncHandle = NULL;faacEncConfigurationPtr pFaacEncConf = NULL;/* 编码相关参数 */unsigned long u64PcmInSampleCnt = 0; // 打开编码器时传出的参数,编码传入的PCM采样数(不是字节)unsigned long u64AacOutMaxBytes = 0; // 打开编码器时传出的参数,编码传出最大字节数unsigned char *pu8PcmInBuf = NULL; // 读取pcm并传递进去编码的缓存指针,后面根据编码器传出参数malloc分配unsigned char *pu8AacEncBuf = NULL; // 编码得到的aac缓存,后面根据编码器传出参数malloc分配/* 判断输入参数 */if(argc == 1){print_usage(argv[0]);return -1;} /* 解析命令行参数 */char option = 0;int option_index = 0;char *short_options = "hi:r:b:c:o:";struct option long_options[] ={{"help", no_argument, NULL, 'h'},{"input_pcmfile", required_argument, NULL, 'i'},{"sample_rate", required_argument, NULL, 'r'},{"sample_bits", required_argument, NULL, 'b'},{"channels", required_argument, NULL, 'c'},{"output_aacfile",required_argument, NULL, 'o'},{NULL, 0, NULL, 0 },};while((option = getopt_long_only(argc, argv, short_options, long_options, &option_index)) != -1){switch(option){case 'h':print_usage(argv[0]);return 0;case 'i':strncpy(pcmFileName, optarg, 128);break;case 'r':u64PcmSampleRate = atoi(optarg);break;case 'c':u32PcmChannels = atoi(optarg);break;case 'b':u32PcmSampleBits = atoi(optarg);break;case 'o':strncpy(aacFileName, optarg, 128);break;defalut:printf("Unknown argument!\n");break;}}printf("\n**************************************\n""input: \n""\t file name: %s\n""\t sample rate: %lu Hz\n""\t sample bits: %d bits\n""\t channels: %d\n""\t bits per second: %lu bps\n""output: \n""\t file name: %s\n""**************************************\n\n",pcmFileName, u64PcmSampleRate, u32PcmSampleBits, u32PcmChannels,u64PcmSampleRate*u32PcmSampleBits*u32PcmChannels, aacFileName);/* 先打开输入/输出文件 */fpPcm = fopen(pcmFileName, "rb");if(fpPcm == NULL){char errMsg[128] = {0};snprintf(errMsg, 128, "open file(%s) error", pcmFileName);perror(errMsg);return -1;}fpAac = fopen(aacFileName, "wb");if(fpAac == NULL){char errMsg[128] = {0};snprintf(errMsg, 128, "open file(%s) error", aacFileName);perror(errMsg);return -1;}/* AAC编码 1/6:传递参数进去打开编码器 */pFaacEncHandle = faacEncOpen(u64PcmSampleRate, u32PcmChannels, &u64PcmInSampleCnt, &u64AacOutMaxBytes);if(pFaacEncHandle == NULL){printf("faacEncOpen(...) error!\n");goto error_exit;}/* 根据上面打开编码器传出的参数分配对应大小的缓存 */pu8PcmInBuf = (unsigned char*)malloc(u64PcmSampleRate*u32PcmSampleBits/8);pu8AacEncBuf = (unsigned char*)malloc(u64AacOutMaxBytes);/* AAC编码 2/6:设置编码器配置 */// 设置编码器配置 a/c: 先获取当前配置pFaacEncConf = faacEncGetCurrentConfiguration(pFaacEncHandle);// 设置编码器配置 b/c: 填充配置/*PCM Sample Input Format0 FAAC_INPUT_NULL invalid, signifies a misconfigured config1 FAAC_INPUT_16BIT native endian 16bit2 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*/pFaacEncConf->inputFormat = FAAC_INPUT_16BIT;
#if 0/* 下面参数不用设置,保存默认即可 */pFaacEncConf->aacObjectType = LOW; // MAIN:1 LOW:2 SSR:3 LTP:4pFaacEncConf->mpegVersion = MPEG4; // MPEG2:0 MPEG4:1pFaacEncConf->useTns = 1; /* Use Temporal Noise Shaping */pFaacEncConf->shortctl = 0; // SHORTCTL_NORMAL:0 SHORTCTL_NOSHORT:1 SHORTCTL_NOLONG:2pFaacEncConf->allowMidside = 1; /* Allow mid/side coding */pFaacEncConf->quantqual = 0; /* Quantizer quality */pFaacEncConf->outputFormat = 1; // 0:Raw 1:ADTSpFaacEncConf->bandWidth = 32000;//0 /* AAC file frequency bandwidth */pFaacEncConf->bitRate = 48000;//0 /* bitrate / channel of AAC file */
#endif// 设置编码器配置 c/c: 重新设置编码器的配置信息faacEncSetConfiguration(pFaacEncHandle, pFaacEncConf);/* 循环操作 */while(1){unsigned int u32PcmInSampleCnt = 0;int s32ReadPcmBytes = 0;int s32EncAacBytes = 0;/* AAC编码 3/6:从文件里读出指定大小(大小由编码器传出参数决定)PCM数据 */s32ReadPcmBytes = fread(pu8PcmInBuf, 1, u64PcmInSampleCnt*u32PcmSampleBits/8, fpPcm);if(s32ReadPcmBytes <= 0){break;}DEBUG("Read PCM bytes: %d\n", s32ReadPcmBytes);// 编码传递进去的是采样数,不是字节数u32PcmInSampleCnt = s32ReadPcmBytes/(u32PcmSampleBits/8);DEBUG("Encode PCM sample count: %d\n", u32PcmInSampleCnt);/* AAC编码 4/6:将PCM数据(pucPcmInBuf)传进去编码得到aac数据(pucAacEncBuf)传出 */s32EncAacBytes = faacEncEncode(pFaacEncHandle, (int32_t*)pu8PcmInBuf, u32PcmInSampleCnt, pu8AacEncBuf, (unsigned int)u64AacOutMaxBytes);DEBUG("Encode return aac bytes: %d\n", s32EncAacBytes);/* AAC编码 5/6:将解码得到的数据写入到AAC文件中 */fwrite(pu8AacEncBuf, 1, s32EncAacBytes, fpAac);}/* 记得释放内存 */free(pu8PcmInBuf);free(pu8AacEncBuf);/* AAC编码 6/6:用完了就关闭编码器 */faacEncClose(pFaacEncHandle);error_exit:fclose(fpPcm);fclose(fpAac);printf("\n\033[32m%s ==> %s Success!\033[0m\n", pcmFileName, aacFileName);return 0;
}
🎄五、总结
本文介绍了AAC音频编码库 faac ,并介绍了其使用流程,最后给出了使用例子源码.
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁
参考:
音频demo:使用faac将PCM数据编码成aac数据