libfdk_aac音频采样数和编码字节数注意

正常人听觉的频率范围大约在20Hz~20kHz之间,根据奈奎斯特采样理论(2倍),为了保证声音不失真,采样频率应该在40kHz左右。(采样频率必须大于等于音频信号的最大频率的两倍,记住,是最大频率。)目前语音识别服务只支持16000Hz和8000Hz两种采样率,其中8000Hz一般是电话业务使用,其余都使用16000Hz。 22050的采样频率是常用的,44100已是CD音质。
44100 Hz - 音频 CD, 也常用于 MPEG-1 音频(VCD,SVCD,MP3)所用采样率48000 Hz - miniDV、数字电视、DVD、DAT、电影和专业音频所用的数字声音所用采样率8000 Hz - 电话所用采样率, 对于人的说话已经足够22050 Hz - 无线电广播所用采样率 引用链接:https://blog.csdn.net/Osean_li/article/details/84107451

出于历史原因,所有CD一律采用44.1KHz,而DVD/BD视频音轨一律采用48KHz。所以不出意外,你听到的那些音乐都是44.1KHz,而你看的视频,它们的音频一般都采用48KHz的采样率。
aac为有损压缩,同时48000->44100的转换对音质也有损伤。
由于人耳听觉范围是20Hz~20kHz,根据香农采样定理(也叫奈奎斯特采样定理),理论上来说采样率大于40kHz的音频格式都可以称之为无损格式。
我们的耳朵听到的频率间隔为20-20KHZ,我们的发声频率为100-3KHZ左右,所以可以看出如果只是单纯的采集发声频率可以使用8KHZ就可以,采样率必须是输入信号最高频率的2倍以上,这样才会最大可能的保存信号信息.故我们的听到的样本的采样率一般都为44.1KHZ及以上.
fdk_aac 支持的音频采样率:7350 8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000
fdk_aac 样本类型:只支持16bit pcm输入.
CBR模式:
设置目标码率,当样本之间差异较小时,可以通过该方法更好地控制文件大小,设置每个通道为64kbps.立体声为128kbps
VBR模式:
指定目标质量,而不是码率,质量从1到5由低到高.使用参数-vbr,vbr模式下大致给出了每个通道对应的码率,参考libfdk_aac介绍
首先需要了解的是AAC文件格式有ADIF和ADTS两种,其中ADIF(Audio Data Interchange Format 音频数据交换格式)的特征是解码必须在明确定义的开始处进行,不能从数据流中间开始;而ADTS(Audio Data Transport Stream 音频数据传输流)则相反,这种格式的特征是有同步字,解码可以在这个流中任何位置开始,正如它的名字一样,这是一种和TS流类似的格式。

ADTS头包含了AAC文件的采样率、通道数、帧数据长度等信息,分为固定头信息和可变头信息两部分。ADTS格式中每一帧都有头信息,具备流特征,适合于网络传输与处理,而ADIF只有一个统一的头,并且这两种格式的header格式也是不同的。目前主流使用的都是ADTS格式。ADIF只有一个统一的头,所以必须得到所有的数据后才能进行解码,一般用于磁盘文件中,实时流协议中不使用。
ADTS头和音频信息是交替存储的:
在这里插入图片描述

正确的说法是不同profile决定了每个aac帧含有多少个sample,即帧数据长度,具体来说,对应关系如下:

AACENC_GRANULE_LENGTH =
0x0105, /*!< Core encoder (AAC) audio frame length in samples:

  • 2048 HE-AAC v1/v2
  • 1024: Default configuration.//AAC-LC 1024
  • 512: Default length in LD/ELD configuration.
  • 480: Length in LD/ELD configuration.
  • 256: Length for ELD reduced delay mode (x2).
  • 240: Length for ELD reduced delay mode (x2).
  • 128: Length for ELD reduced delay mode (x4).
  • 120: Length for ELD reduced delay mode (x4). */
    其中LC即Low Complexity,HE即High Efficiency,注意,其中数据表示单通道的采样数,如1024,表示单通道每秒采样1024帧。每次送入编码器的数据必须是上述设定或默认的数据,如果不是的话会在缓冲区中暂存,然后够了之后再送进去。
    部分libfdk_aac源码如下:
aacEncInfo(aacEncHandle, &info);
int input_size       = channel * 2 * info.frameLength;

其中假如设置一包压缩的aac音频采样数为1024(术语叫帧数据长度),那么如果送进去的采样数不够1024的话,不会有输出,等到够1024时才输出一包,就是图中的AAC ES包。

参考:https://blog.csdn.net/mo4776/article/details/104054049
声道数:
0: Defined in AOT Specifc Config
1: 1 channel: front-center
2: 2 channels: front-left, front-right
3: 3 channels: front-center, front-left, front-right
4: 4 channels: front-center, front-left, front-right, back-center
5: 5 channels: front-center, front-left, front-right, back-left, back-right
6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel
8-15: Reserved

实测记录如下:
设备 send进的采样数 声音
pulse 128 听不到
dsnoop 1024 正常
sysdefault 940 能听到,有噪音,无缓存
null 32768 超过1024,报错

实测当送进去128,1024,940时到avcodec_send_frame时,avcodec_receive_packet一对一返回,开始并没有几帧缓存,av_interleaved_write_frame也一对一执行,一没有返回。也就是三者总是保持一对一执行,后两者都有返回,并且一开始没有缓存。
当send进去的frame_a带有32768个采样数时,报错:

more samples than frame size (avcodec_encode_audio2)

因为fdk_aac默认编码是1024个字节,所以多出的字节会报错。
且当送进去128时,用代码去解码,实测frame_a->nb_samples = 1024 frame_a->linesize[0] = 8192(注意fdk_aac编码只接受16位,输出是fltp,frame_a->linesize[1] = 0),fdk_aac默认是1024个字节一次输出,因此说明,当送进去的不够1024个采样时,编码器并不会缓冲,等待填充,而是填充无效数据使其够1024个字节,然后输出,这也是播放时无法正常播放的原因。

哎呦喂ヾ(✿゚▽゚)ノ~路长馆小,雪轻帘薄,酒热乎,这位爷~您ヾ(✿゚▽゚)ノ~ 里面坐~
本公众号专注分享C++,ffmpeg,opencv等相关音视频知识
webrtc,udp,tcp,rtsp,rtmp,srt/nginx+rtmp等流媒体协议和服务器
同时也会有大厂音视频技术专家不定期直播分享…
国人开发流媒体srs服务器,及yangrtc(国人版的webrtc)协议新动向
偶尔分享下程序员梦呓碎碎念(๑•॒̀ ູ॒•́๑)啦啦啦
目前刚刚开通,接受读者的优质投稿…
鉴于国内音视频圈子小,起步晚,以致分享少,门槛高,特开通分享,一起扇动这阵风吧!
微信扫描下方二维码,关注公众号,赶快进入音视频开发者社区吧!

猜你喜欢

转载自blog.csdn.net/weixin_43466192/article/details/121509955