文章目录

  • 前言
  • 一、接口设计
  • 二、完整代码
  • 三、使用示例
    • 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对音频编码相关推荐

  1. 【Android RTMP】音频数据采集编码 ( 音频数据采集编码 | AAC 高级音频编码 | FAAC 编码器 | Ubuntu 交叉编译 FAAC 编码器 )

    文章目录 安卓直播推流专栏博客总结 一. 音频数据采集.编码 二. AAC 高级音频编码 三. FAAC 编码器 四. Ubuntu 18.04.4 交叉编译 FAAC 编码器 安卓直播推流专栏博客总 ...

  2. aac蓝牙编解码协议_蓝牙音频编码哪个音质好?今天我们来逐一解读

    家有影院致力于帮助渴望学习.热爱电影.希望通过自己双手搭建出适合自己的家庭影院的朋友.如果你是这样的人,我们和500位同样热爱家庭影院的伙伴愿意一起帮助你实现梦想.同时,我们还能帮助你找到价格优惠的靠 ...

  3. 【Android RTMP】安卓直播推流总结 ( 直播服务器搭建 | NV21 图像采集 | H.264 视频编码 | PCM 音频采集 | AAC 音频编码 | RTMP 包封装推流 )

    文章目录 一. 安卓直播推流专栏博客总结 二. 相关资源介绍 三. GitHub 源码地址 四. 整体 Android 直播推流数据到服务器并观看直播演示过程 Android 直播推流流程 : 手机采 ...

  4. 音频编码标准发展现状

    一.概述 音频信号数字化之后所面临的一个问题是巨大的数据量,这为存储和传输带来了压力.例如,对于CD音质的数字音频,所用的采样频率为44.1 kHz,量化精度为16bit:采用双声道立体声时,其数码率 ...

  5. MPEG音频编码实验

    实验原理 MPEG简介 MPEG-1 MPEG组织制定的第一个视频和音频有损压缩标准,也是最早推出及应用在市场上的MPEG技术,其原来的主要目标是在CD光盘上记录影像,后来被广泛应用在VCD光盘.视频 ...

  6. FFmpeg音频编码 ---- pcm转aac(使用新版ffmpeg API,亲测可用)

    /** * @projectName 08-01-encode_audio * @brief 音频编码 * 从本地读取PCM数据进行AAC编码 * 1. 输入PCM格式问题,通过AVCodec的sam ...

  7. FFmpeg简单使用:音频编码 ---- pcm转aac

    基本流程  函数说明 avcodec_find_encoder:根据指定的AVCodecID查找注册的编码器. avcodec_alloc_context3:为AVCodecContext分配内存. ...

  8. uvc音频传输协议_蓝牙中的三种音频编码:Apt-X、SBC、AAC,请问分别有什么区别?...

    Apt-X在理论上声音保留的细节会更多,但需要购买对应的使用授权:SBC是A2DP蓝牙音频传输协议强制规定的编码格式,音质比MP3差:ACC是杜比实验室为音乐社区提供的技术,音质比SBC好.详细介绍如 ...

  9. 【Android RTMP】音频数据采集编码 ( FAAC 音频编码参数设置 | FAAC 编码器创建 | 获取编码器参数 | 设置 AAC 编码规格 | 设置编码器输入输出参数 )

    文章目录 一. 头文件.成员变量准备 二. 创建 FAAC 编码器 三. 获取并设置 FAAC 编码器参数 四. 设置 FAAC 编码器编码标准 五. 设置 FAAC 编码器 AAC 编码规格 六. ...

  10. 基于FFmpeg的音频编码(PCM数据编码成AAC android)

    概述 在Android上实现录音,并利用 FFmpeg将PCM数据编码成AAC. 详细 代码下载:http://www.demodashi.com/demo/10512.html 之前做的一个demo ...

最新文章

  1. 关于SQLServer2005的学习笔记——约束、Check、触发器的执行顺序
  2. Bi-level error correction for PacBio long reads. PacBio长读数的两级纠错
  3. 旧电脑怎么升级配置_旧电脑升级哪些配件效果最好?答案莫过于这3点!
  4. 【项目管理】ITTO-质量管理
  5. Unity3d疑难问题解决
  6. 【学术相关】普通在读奶爸博士生的一年总结!
  7. matlab 双向链表,双向链表基本操作(C语言实现)
  8. 软链接文件和硬链接文件
  9. 多个ORACLE HOME时的程序连接
  10. 2月18 多项式拟合原理、全过程,loss函数,正则化,迭代与梯度下降,plotly
  11. 【线性回归】-最小二乘法求一元线性回归公式推导及代码实现
  12. 2021-05-13 Redis面试题 MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据?
  13. select搜索功能实现
  14. photoshop涂抹工具
  15. 使用Django+MySQL快速搭建一个属于自己的网站
  16. android和苹果内存,安卓的8G运行内存为什么与苹果3G的运行内存不能抗衡?
  17. 【DP】AGC012B Splatter Painting
  18. vue高德地图实现关键字搜索
  19. PowerDesigner 安装
  20. PEPS无钥匙进入系统-传统PEPS与数字钥匙系统

热门文章

  1. Android 防止App退出 或者 启动另一个App
  2. javase核心day13
  3. 系统命令联网激活方法
  4. oracle创建完成 sys密码怎么修改,如何重置密码 oracle sys和system
  5. 国家区块链漏洞库《区块链漏洞定级细则》发布
  6. 专访Riverbed CEO:私有化和出售业务瘦身后的Riverbed更专注
  7. 爬取京东收件地址下得所有数据
  8. 解决Windows10下java环境变量配置不生效的问题
  9. 简单的python爬取淘宝数据
  10. 每日面试】阿里巴巴 Java后端 57min