当前位置:网站首页>Audio codec, using FAAC to implement AAC encoding
Audio codec, using FAAC to implement AAC encoding
2022-08-11 03:26:00 【Audio and video development old man】
这里利用FAAC来实现AAC编码.另外,WAV的数据段是PCM,代码会出现很多PCM缩写.
1 下载安装 FAAC
这里的安装过程是在 Mac 和 Linux 上实现的,Windows可以类似参考.
wget http://downloads.sourceforge.net/faac/faac-1.28.tar.gz
tar zxvf faac-1.28.tar.gz
cd faac-1.28
./configure
make
sudo make install
如果才用默认的 configure 中的 prefix path,那么安装后的 lib 和 .h 文件分别在/usr/local/lib
和/usr/local/include
,后面编译的时候会用到.
2 FAAC API
2.1 Open FAAC engine
Prototype:
faacEncHandle faacEncOpen // 返回一个FAAC的handle
(
unsigned long nSampleRate, // 采样率,单位是bps
unsigned long nChannels, // 声道,1为单声道,2为双声道
unsigned long &nInputSamples, // 传引用,得到每次调用编码时所应接收的原始数据长度
unsigned long &nMaxOutputBytes // 传引用,得到每次调用编码时生成的AAC数据的最大长度
);
本文福利, C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓见下面↓↓文章底部点击领取↓↓
2.2 Get/Set encoding configuration
Prototype:
获取编码器的配置:
faacEncConfigurationPtr faacEncGetCurrentConfiguration // 得到指向当前编码器配置的指针
(
faacEncHandle hEncoder // FAAC的handle
);
设定编码器的配置:
int FAACAPI faacEncSetConfiguration
(
faacDecHandle hDecoder, // 此前得到的FAAC的handle
faacEncConfigurationPtr config // FAAC编码器的配置
);
2.3 Encode
Prototype:
int faacEncEncode
(
faacEncHandle hEncoder, // FAAC的handle
short *inputBuffer, // WAV原始数据
unsigned int samplesInput, // 调用faacEncOpen时得到的nInputSamples值
unsigned char *outputBuffer,// 至少具有调用faacEncOpen时得到的nMaxOutputBytes字节长度的缓冲区
unsigned int bufferSize // outputBuffer缓冲区的实际大小
);
2.4 Close FAAC engine
Prototype
void faacEncClose
(
faacEncHandle hEncoder // 此前得到的FAAC handle
);
3 流程
3.1 做什么准备?
采样率,声道数(双声道还是单声道?),还有你的WAV的单个样本是8位的还是16位的?
3.2 开启FAAC编码器,做编码前的准备
- 调用
faacEncOpen
开启FAAC编码器后,得到了单次输入样本数nInputSamples
和输出数据最大字节数nMaxOutputBytes
; - 根据
nInputSamples
和nMaxOutputBytes
,分别为WAV数据和将要得到的AAC数据创建缓冲区; - 调用
faacEncGetCurrentConfiguration
获取当前配置,修改完配置后,调用faacEncSetConfiguration
设置新配置.
3.3 开始编码
调用faacEncEncode
,该准备的刚才都准备好了,很简单.
3.4 善后
关闭编码器,另外别忘了释放缓冲区,如果使用了文件流,也别忘记了关闭.
4 测试程序
4.1 完整代码
将WAV
格式音频文件/home/michael/Development/testspace/in.wav
转至AAC
格式文件/home/michael/Development/testspace/out.aac
.
#include <faac.h>
#include <stdio.h>
typedef unsigned long ULONG;
typedef unsigned int UINT;
typedef unsigned char BYTE;
typedef char _TCHAR;
int main(int argc, _TCHAR* argv[])
{
ULONG nSampleRate = 11025; // 采样率
UINT nChannels = 1; // 声道数
UINT nPCMBitSize = 16; // 单样本位数
ULONG nInputSamples = 0;
ULONG nMaxOutputBytes = 0;
int nRet;
faacEncHandle hEncoder;
faacEncConfigurationPtr pConfiguration;
int nBytesRead;
int nPCMBufferSize;
BYTE* pbPCMBuffer;
BYTE* pbAACBuffer;
FILE* fpIn; // WAV file for input
FILE* fpOut; // AAC file for output
fpIn = fopen("/home/michael/Development/testspace/in.wav", "rb");
fpOut = fopen("/home/michael/Development/testspace/out.aac", "wb");
// (1) Open FAAC engine
hEncoder = faacEncOpen(nSampleRate, nChannels, &nInputSamples, &nMaxOutputBytes);
if(hEncoder == NULL)
{
printf("[ERROR] Failed to call faacEncOpen()\n");
return -1;
}
nPCMBufferSize = nInputSamples * nPCMBitSize / 8;
pbPCMBuffer = new BYTE [nPCMBufferSize];
pbAACBuffer = new BYTE [nMaxOutputBytes];
// (2.1) Get current encoding configuration
pConfiguration = faacEncGetCurrentConfiguration(hEncoder);
pConfiguration->inputFormat = FAAC_INPUT_16BIT;
// (2.2) Set encoding configuration
nRet = faacEncSetConfiguration(hEncoder, pConfiguration);
for(int i = 0; 1; i++)
{
// 读入的实际字节数,最大不会超过nPCMBufferSize,一般只有读到文件尾时才不是这个值
nBytesRead = fread(pbPCMBuffer, 1, nPCMBufferSize, fpIn);
// 输入样本数,用实际读入字节数计算,一般只有读到文件尾时才不是nPCMBufferSize/(nPCMBitSize/8);
nInputSamples = nBytesRead / (nPCMBitSize / 8);
// (3) Encode
nRet = faacEncEncode(
hEncoder, (int*) pbPCMBuffer, nInputSamples, pbAACBuffer, nMaxOutputBytes);
fwrite(pbAACBuffer, 1, nRet, fpOut);
printf("%d: faacEncEncode returns %d\n", i, nRet);
if(nBytesRead <= 0)
{
break;
}
}
// (4) Close FAAC engine
nRet = faacEncClose(hEncoder);
delete[] pbPCMBuffer;
delete[] pbAACBuffer;
fclose(fpIn);
fclose(fpOut);
//getchar();
return 0;
}
4.2 编译运行
将上述代码保存为“wav2aac.cpp”文件,然后编译:
g++ wav2aac.cpp -o wav2aac -L/usr/local/lib -lfaac -I/usr/local/include
运行:
./wav2aac
然后就生成了out.aac
文件了,听听看吧!~
本文福利, C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓见下面↓↓文章底部点击领取↓↓
边栏推荐
- 互换性测量与技术——偏差与公差的计算,公差图的绘制,配合与公差等级的选择方法
- The thirteenth day of learning programming
- EasyCVR接入GB28181设备时,设备接入正常但视频无法播放是什么原因?
- oracle的基数会影响到查询速度吗?
- 云平台下ESB产品开发步骤说明
- AI+医疗:使用神经网络进行医学影像识别分析
- LeetCode热题(12.买卖股票的最佳时机)
- AI+Medical: Using Neural Networks for Medical Image Recognition and Analysis
- uni-app - 获取汉字拼音首字母(根据中文获取拼音首字母)
- 获取链表长度
猜你喜欢
JS-DOM element object
[idea error] Invalid target distribution: 17 solution reference
阿里低代码框架 lowcode-engine 之自定义物料篇
调试技巧总结
VIT 源码详解
互换性与测量技术——表面粗糙度选取和标注方法
When EasyCVR is connected to the GB28181 device, what is the reason that the device is connected normally but the video cannot be played?
Kubernetes集群搭建Zabbix监控平台
树莓派入门(5)系统备份
CTO说MySQL单表行数不要超过2000w,为啥?
随机推荐
面试常考的7种排序算法
Redis老了吗?Redis与Dragonfly性能比较
高度塌陷问题的解决办法
“顶梁柱”滑坡、新增长极难担重任,阿里“蹲下”是为了跳更高?
Realization of vending machine function based on FPGA state machine
字体反扒
LeetCode Hot Questions (12. The Best Time to Buy and Sell Stocks)
A practice arrangement about map GIS (below) GIS practice of Redis
80端口和443端口是什么?有什么区别?
求和、计数的窗口函数应用
成都纸质发票再见!开住宿费电子发票即将全面取代酒店餐饮加油站发票
AI+Medical: Using Neural Networks for Medical Image Recognition and Analysis
STC8H development (15): GPIO drive Ci24R1 wireless module
What problems should we pay attention to when building a programmatic trading system?
DOM-DOM tree, a DOM tree has three types of nodes
输入起始位置,终止位置截取链表
Briefly, talk about the use of @Transactional in the project
论文精度 —— 2017 CVPR《High-Resolution Image Inpainting using Multi-Scale Neural Patch Synthesis》
Goodbye Chongqing paper invoices!The issuance of electronic invoices for accommodation expenses will soon completely replace the invoices of hotels, catering and gas stations
图解LeetCode——640. 求解方程(难度:中等)