音频编解码·实战篇(1)WAV转至AAC(AAC编码)
2014-04-04 15:14
381 查看
http://blog.csdn.net/simongyley/article/details/8507928
这里利用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
[/code]
如果才用默认的 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数据的最大长度 );
[/code]
2.2 Get/Set encoding configuration
Prototype:
获取编码器的配置:faacEncConfigurationPtr faacEncGetCurrentConfiguration // 得到指向当前编码器配置的指针 ( faacEncHandle hEncoder // FAAC的handle );
[/code]
设定编码器的配置:
int FAACAPI faacEncSetConfiguration ( faacDecHandle hDecoder, // 此前得到的FAAC的handle faacEncConfigurationPtr config // FAAC编码器的配置 );
[/code]
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缓冲区的实际大小 );
[/code]
2.4 Close FAAC engine
Prototype
void faacEncClose ( faacEncHandle hEncoder // 此前得到的FAAC handle );
[/code]
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; }
[/code]
4.2 编译运行
将上述代码保存为“wav2aac.cpp”文件,然后编译:g++ wav2aac.cpp -o wav2aac -L/usr/local/lib -lfaac -I/usr/local/include
[/code]
运行:
./wav2aac
[/code]
然后就生成了
out.aac文件了,听听看吧!~
5 Reference
AudioCoding.com -FAACDogfoot – 재밌는 개발
-
相关文章推荐
- Linux 使用uinput创建虚拟input设备
- 从日期+时间的格式的字符串中取到自己想要的数值的感想
- INSTALL_FAILED_INSUFFICIENT_STORAGE 错误解决
- STM32F103C8T6 can端口映射
- Android 获得所有应用程序包
- How to say "no"?
- 开放,有的像雪,浑然一
- 关于org.apache.jasper.JasperException: Unable to compile class for JSP问题的解决
- 重写View的时候遇到inflate的错误
- 通过wpa_cli连接一个
- Asp.Net MVC 4 Web API 中的安全认证-使用OAuth
- C#将对象转换为JSON和将JSON转换为对象
- suse 源的添加与删除,以及源地址
- centos svn快速搭建
- Linux进程间通信(二)---管道通信之无名管道及其基础实验
- eclipse常用快捷键 --10大常用快捷键 可以提高不小的工作效率哦
- 俊逸,看似柔弱,却亭亭玉立,
- PHPexcel设置单元格日期格式
- C++快速排序算法实现
- 从《小时代》的粉丝营销看乐视影业的营销方法论