C++ 使用fdk-aac对音频编码
文章目录
- 前言
- 一、接口设计
- 二、完整代码
- 三、使用示例
- 1.双声道
- 2.单声道
- 总结
前言
mp4的音频流通常是aac编码,我们做音视频采集的时候就需要将,采集的音频PCM编码成aac,然后再打包进mp4,而aac编解码库中fdk-aac是性能较好的,使用方式也比较简单。在C++项目中使用,通常再做一层封装,提高模块的复用性和替换性。本文将展示C++将fdk-aac封装成一个编码对象,以及使用示例。
一、接口设计
由于我前面的文章已经给出了fdk-aac的使用示例:《Windows上使用vs编译fdk-aac》,所以在这里直接设计对象的接口。
/// <summary>
/// aac编码对象
/// 所有方法采用异常处理进行错误提示,使用时注意使用try-catch,抛出对象为std::exception。
/// 构造方法参数的声道数是最大缓存数量,并非实际声道数,实际声道数由SetChannelMode方法确定,本版本需要确保SetChannelMode的声道数与构造方法参数的声道数一致。
/// </summary>
class FdkaacEncoder {public:/// <summary>/// 编码数据到达事件参数/// </summary>class EncodedDataArrivedEventArgs {public:/// <summary>/// 音频帧/// </summary>AudioCodingFrame Frame;};/// <summary>/// 编码数据到达事件/// </summary>std::function<void(void*,EncodedDataArrivedEventArgs*)> EncodedDataArrived;/// <summary>/// 构造方法/// </summary>/// <param name="">编码参数</param>FdkaacEncoder(SoundFormat format);/// <summary>/// 析构方法/// </summary>~FdkaacEncoder();/// <summary>/// 获取声音格式/// </summary>/// <returns>声音格式</returns>SoundFormat GetSoundFormat();/// <summary>/// 设置比特率/// </summary>/// <param name="value">比特率,单位byte</param>void SetBitrate(int value);/// <summary>/// 获取比特率/// </summary>/// <returns>比特率,单位byte</returns>int GetBitrate();/// <summary>/// 设置封装类型/// </summary>/// <param name="value">封装类型</param>void SetTransportType(TransportType value);/// <summary>/// 获取封装类型/// </summary>/// <returns>封装类型</returns>TransportType GetTransportType();/// <summary>/// 设置比特率模式(CBR、VBR)/// </summary>/// <param name="value">比特率模式</param>void SetBitrateMode(BitrateModde value);/// <summary>/// 获取比特率模式(CBR、VBR)/// </summary>/// <returns>比特率模式</returns>BitrateModde GetBitrateMode();/// <summary>/// 设置声道顺序/// </summary>/// <param name="value">声道顺序</param>void SetChannelOrder(ChannelOrder value);/// <summary>/// 获取声道顺序/// </summary>/// <returns>声道顺序</returns>ChannelOrder GetChannelOrder();/// <summary>/// 设置声道模式,声道数需要小于等于构造方法设置的声道数。/// </summary>/// <param name="value">声道模式</param>void SetChannelMode(ChannelMode value);/// <summary>/// 获取声道模式/// </summary>/// <returns></returns>ChannelMode GetChannelMode();/// <summary>/// 设置频段复制模式/// </summary>/// <param name="value">频段复制模式</param>void SetSbrMode(SbrMode value);/// <summary>/// 获取频段复制模式/// </summary>/// <returns>频段复制模式</returns>SbrMode GetSbrMode();/// <summary>/// 设置AOT/// </summary>/// <param name="">AOT</param>void SetAudioObjectType(AudioObjectType);/// <summary>/// 获取AOT/// </summary>/// <returns>AOT</returns>AudioObjectType GetAudioObjectType();/// <summary>/// 写入音频数据/// 注意数据长度不能过大,否则导致音频不正常,建议2048。/// </summary>/// <param name="data">音频数据</param>/// <param name="dataLength">数据长度</param>void Write(unsigned char* data, int dataLength);
}
二、完整代码
对上述接口进行实现,进过调试、测试得到如下完整代码:
vs2019项目包含使用示例、所有接口测试程序及测试音频文件。
https://download.csdn.net/download/u013113678/78957355
三、使用示例
将wav文件编码成acc文件。其中WavFileReader对象参考:《C++ 读取wav文件中的PCM数据》
1.双声道
#include<stdio.h>
#include<exception>
#include"WavFileReader.h"
#include"FdkaacEncoder.h"
void main(int argc, char* argv[])
{FILE* f=nullptr;try { //wav文件读取对象AC::WavFileReader wr;//aac编码对象//其中参数的声道数是最大缓存数量,并非实际声道数,实际声道数由SetChannelMode方法确定,本版本需要确保SetChannelMode的声道数与构造方法参数的声道数一致。AC::FdkaacEncoder fe({ 2 ,44100 ,16 });unsigned char buf[2048];//设置参数fe.SetSbrMode(AC::SbrMode_Disable);fe.SetAudioObjectType(AC::AudioObjectType::AUDIOOBJECTTYPE_AAC_LC);fe.SetBitrate(128 * 1024);fe.SetChannelMode(AC::ChannelMode::CHANNELMODE_2);fe.SetChannelOrder(AC::CHANNELORDER_WAV);fe.SetBitrateMode(AC::BitrateModde::BITRATEMODDE_CBR);fe.SetTransportType(AC::TRANSPORTTYPE_MP4_ADTS);//注册编码数据到达事件fe.EncodedDataArrived = [&](auto s, auto e) {//将得到的编码数据写入文件fwrite(e->Frame.Data, 1, e->Frame.DataLength, f);};//创建aac文件f = fopen("test_music.aac", "wb+");if (!f){throw std::exception("create aac file fail,create name:test_music.aac");}//打开wav文件if (!wr.OpenWavFile("test_music.wav")){throw std::exception("open wav file fail,filename:test_music.wav");} while (1){ //读取wav中的pcm数据int size = wr.ReadData(buf, 2048);if (size < 1)break;//将pcm数据写入编码器fe.Write(buf, size);} printf("encode completed\n");}catch(std::exception e){printf("%s\n",e.what());}catch (...) {printf("unknown errror\n");}if(f)fclose(f);
}
2.单声道
#include<stdio.h>
#include<exception>
#include"WavFileReader.h"
#include"FdkaacEncoder.h"
void main(int argc, char* argv[])
{FILE* f = nullptr;try {//wav文件读取对象AC::WavFileReader wr;//aac编码对象//其中参数的声道数是最大缓存数量,并非实际声道数,实际声道数由SetChannelMode方法确定,本版本需要确保SetChannelMode的声道数与构造方法参数的声道数一致。AC::FdkaacEncoder fe({ 1 ,44100 ,16 });unsigned char buf[2048];//设置参数fe.SetSbrMode(AC::SbrMode_Disable);fe.SetAudioObjectType(AC::AudioObjectType::AUDIOOBJECTTYPE_AAC_LC);fe.SetBitrate(128 * 1024);fe.SetChannelMode(AC::ChannelMode::CHANNELMODE_1);fe.SetChannelOrder(AC::CHANNELORDER_WAV);fe.SetBitrateMode(AC::BitrateModde::BITRATEMODDE_CBR);fe.SetTransportType(AC::TRANSPORTTYPE_MP4_ADTS);//注册编码数据到达事件fe.EncodedDataArrived = [&](auto s, auto e) {//将得到的编码数据写入文件fwrite(e->Frame.Data, 1, e->Frame.DataLength, f);};//创建aac文件f = fopen("test_music_1ch441s16b.aac", "wb+");if (!f){throw std::exception("create aac file fail,create name:test_music_1ch441s16b.aac");}//打开wav文件if (!wr.OpenWavFile("test_music_1ch441s16b.wav")){throw std::exception("open wav file fail,filename:test_music_1ch441s16b.wav");}while (1){ //读取wav中的pcm数据int size = wr.ReadData(buf, 2048);if (size < 1)break;//将pcm数据写入编码器fe.Write(buf, size);}printf("encode completed\n");}catch (std::exception e) {printf("%s\n", e.what());}catch (...) {printf("unknown errror\n");}if (f)fclose(f);
}
总结
以上就是今天要讲的内容,将编码器设计成对象可以灵活的使用在项目中,尤其需要使用设计模式,比如原型模式:一个aac编码器接口可以有不同的实现fdk-aac只是其中一种实现,写好的代码可以随意切换编码器对象。或者策略模式,设计一个编码器接口,调用时根据编码格式选择合适的编码器。总的来说,这个对象的设计和实现不算特别难,就是在细节的地方需要注意,比如错误提示,边界值处理等。
C++ 使用fdk-aac对音频编码相关推荐
- 【Android RTMP】音频数据采集编码 ( 音频数据采集编码 | AAC 高级音频编码 | FAAC 编码器 | Ubuntu 交叉编译 FAAC 编码器 )
文章目录 安卓直播推流专栏博客总结 一. 音频数据采集.编码 二. AAC 高级音频编码 三. FAAC 编码器 四. Ubuntu 18.04.4 交叉编译 FAAC 编码器 安卓直播推流专栏博客总 ...
- aac蓝牙编解码协议_蓝牙音频编码哪个音质好?今天我们来逐一解读
家有影院致力于帮助渴望学习.热爱电影.希望通过自己双手搭建出适合自己的家庭影院的朋友.如果你是这样的人,我们和500位同样热爱家庭影院的伙伴愿意一起帮助你实现梦想.同时,我们还能帮助你找到价格优惠的靠 ...
- 【Android RTMP】安卓直播推流总结 ( 直播服务器搭建 | NV21 图像采集 | H.264 视频编码 | PCM 音频采集 | AAC 音频编码 | RTMP 包封装推流 )
文章目录 一. 安卓直播推流专栏博客总结 二. 相关资源介绍 三. GitHub 源码地址 四. 整体 Android 直播推流数据到服务器并观看直播演示过程 Android 直播推流流程 : 手机采 ...
- 音频编码标准发展现状
一.概述 音频信号数字化之后所面临的一个问题是巨大的数据量,这为存储和传输带来了压力.例如,对于CD音质的数字音频,所用的采样频率为44.1 kHz,量化精度为16bit:采用双声道立体声时,其数码率 ...
- MPEG音频编码实验
实验原理 MPEG简介 MPEG-1 MPEG组织制定的第一个视频和音频有损压缩标准,也是最早推出及应用在市场上的MPEG技术,其原来的主要目标是在CD光盘上记录影像,后来被广泛应用在VCD光盘.视频 ...
- FFmpeg音频编码 ---- pcm转aac(使用新版ffmpeg API,亲测可用)
/** * @projectName 08-01-encode_audio * @brief 音频编码 * 从本地读取PCM数据进行AAC编码 * 1. 输入PCM格式问题,通过AVCodec的sam ...
- FFmpeg简单使用:音频编码 ---- pcm转aac
基本流程 函数说明 avcodec_find_encoder:根据指定的AVCodecID查找注册的编码器. avcodec_alloc_context3:为AVCodecContext分配内存. ...
- uvc音频传输协议_蓝牙中的三种音频编码:Apt-X、SBC、AAC,请问分别有什么区别?...
Apt-X在理论上声音保留的细节会更多,但需要购买对应的使用授权:SBC是A2DP蓝牙音频传输协议强制规定的编码格式,音质比MP3差:ACC是杜比实验室为音乐社区提供的技术,音质比SBC好.详细介绍如 ...
- 【Android RTMP】音频数据采集编码 ( FAAC 音频编码参数设置 | FAAC 编码器创建 | 获取编码器参数 | 设置 AAC 编码规格 | 设置编码器输入输出参数 )
文章目录 一. 头文件.成员变量准备 二. 创建 FAAC 编码器 三. 获取并设置 FAAC 编码器参数 四. 设置 FAAC 编码器编码标准 五. 设置 FAAC 编码器 AAC 编码规格 六. ...
- 基于FFmpeg的音频编码(PCM数据编码成AAC android)
概述 在Android上实现录音,并利用 FFmpeg将PCM数据编码成AAC. 详细 代码下载:http://www.demodashi.com/demo/10512.html 之前做的一个demo ...
最新文章
- 关于SQLServer2005的学习笔记——约束、Check、触发器的执行顺序
- Bi-level error correction for PacBio long reads. PacBio长读数的两级纠错
- 旧电脑怎么升级配置_旧电脑升级哪些配件效果最好?答案莫过于这3点!
- 【项目管理】ITTO-质量管理
- Unity3d疑难问题解决
- 【学术相关】普通在读奶爸博士生的一年总结!
- matlab 双向链表,双向链表基本操作(C语言实现)
- 软链接文件和硬链接文件
- 多个ORACLE HOME时的程序连接
- 2月18 多项式拟合原理、全过程,loss函数,正则化,迭代与梯度下降,plotly
- 【线性回归】-最小二乘法求一元线性回归公式推导及代码实现
- 2021-05-13 Redis面试题 MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据?
- select搜索功能实现
- photoshop涂抹工具
- 使用Django+MySQL快速搭建一个属于自己的网站
- android和苹果内存,安卓的8G运行内存为什么与苹果3G的运行内存不能抗衡?
- 【DP】AGC012B Splatter Painting
- vue高德地图实现关键字搜索
- PowerDesigner 安装
- PEPS无钥匙进入系统-传统PEPS与数字钥匙系统