音视频开发23 FFmpeg 音频重采样原理,音频重采样API 整理

代码实现的功能

目的是 将:
一个采样率为 44100,采样通道为 2,格式为 AV_SAMPLE_FMT_DBL in.pcm 数据
转换成
一个采样率为 48000,采样通道为 1,格式为 AV_SAMPLE_FMT_S16 out.pcm 数据

1.重采样

1.1 为什么要重采样?

为什么要重采样?当然是原有的⾳频参数不满⾜我们的需求。
⽐如在FFmpeg解码⾳频的时候,不同的⾳源有不同的格式,采样率等,在解码后的数据中的这些参数也会不⼀致。
(最新FFmpeg 解码⾳频后,⾳频格 式为AV_SAMPLE_FMT_FLTP,这个参数应该是⼀致的),
如果我们接下来需要使⽤解码后的⾳频数据做 其他操作,⽽这些参数的不⼀致导致会有很多额外⼯作,此时直接对其进⾏重采样,获取我们制定的⾳频 参数,这样就会⽅便很多。
再⽐如在将⾳频进⾏SDL播放时候,因为当前的SDL2.0不⽀持planar格式,也不⽀持浮点型的,⽽最新的 FFMPEG 16年会将⾳频解码为AV_SAMPLE_FMT_FLTP格式,因此此时就需要我们对其重采样,使之可 以在SDL2.0上进⾏播放。

1.2 什么是重采样

所谓的重采样,就是改变⾳频的 采样率、sample format、声道数 等参数,使之按照我们期望的参数输出。这里的改变是指 只要 上述三者的其中一个变化,就叫做重采样。

1.3 可调节的参数

通过重采样,我们可以对:
1. sample rate(采样率)
2. sample format(采样格式)
3. channel layout(通道布局,可以通过此参数获取声道数

2 对应参数解析

2.1 采样率

采样设备每秒抽取样本的次数  例如48000,44100,对应的是 AVFrame 结构体中的 sample_rate

2.2 采样格式及量化精度(位宽)

每种⾳频格式有不同的量化精度(位宽),位数越多,表示值就越精确,声⾳表现⾃然就越精准。
FFMpeg中⾳频格式有以下⼏种,每种格式有其占⽤的字节数信息(libavutil/samplefmt.h):
enum AVSampleFormat {
    AV_SAMPLE_FMT_NONE = -1,
    AV_SAMPLE_FMT_U8,          ///< unsigned 8 bits
    AV_SAMPLE_FMT_S16,         ///< signed 16 bits
    AV_SAMPLE_FMT_S32,         ///< signed 32 bits
    AV_SAMPLE_FMT_FLT,         ///< float
    AV_SAMPLE_FMT_DBL,         ///< double

    AV_SAMPLE_FMT_U8P,         ///< unsigned 8 bits, planar
    AV_SAMPLE_FMT_S16P,        ///< signed 16 bits, planar
    AV_SAMPLE_FMT_S32P,        ///< signed 32 bits, planar
    AV_SAMPLE_FMT_FLTP,        ///< float, planar
    AV_SAMPLE_FMT_DBLP,        ///< double, planar
    AV_SAMPLE_FMT_S64,         ///< signed 64 bits
    AV_SAMPLE_FMT_S64P,        ///< signed 64 bits, planar

    AV_SAMPLE_FMT_NB           ///< Number of sample formats. DO NOT USE if linking dynamically
};

2.3 平面模式和交错模式 - 分⽚(plane)和打包(packed

以双声道为例,
带P(plane)的数据格式在存储时,其左声道和右声道的数据是分开存储的,左声道的 数据存储在data[0],右声道的数据存储在data[1],每个声道的所占⽤的字节数为linesize[0]和 linesize[1];
不带P(packed)的⾳频数据在存储时,是按照LRLRLR...的格式交替存储在data[0]中,linesize[0]
表示总的数据量。

2.4 声道分布(channel_layout)

声道分布在FFmpeg\libavutil\channel_layout.h中有定义,⼀般来说⽤的⽐较多的是
AV_CH_LAYOUT_MONO  (单声道)            
AV_CH_LAYOUT_STEREO(双声道)
AV_CH_LAYOUT_SURROUND(三声道)
#define AV_CH_LAYOUT_MONO              (AV_CH_FRONT_CENTER)
#define AV_CH_LAYOUT_STEREO            (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT)
#define AV_CH_LAYOUT_2POINT1           (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY)
#define AV_CH_LAYOUT_2_1               (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER)
#define AV_CH_LAYOUT_SURROUND          (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER)

2.5 ⾳频帧的数据量计算

⼀帧⾳频的数据量(字节)= channel数 * 每个channel的样本数 * 每个样本占⽤的字节数
对应从AVFrame 中的数据为
avframe->ch_layout.nb_channels * avframe->nb_samples * av_get_bytes_per_sample((AVSampleFormat)avframe->format);
如果该⾳频帧是FLTP格式的PCM数据,包含1024个样本,双声道,那么该⾳频帧包含的⾳频数据量是  2*1024*4=8192字节。
FLTP 对应的数据大小可以通过 ffmpeg -sample_fmts 查看:
u8        8
s16      16
s32      32
flt      32
dbl      64
u8p       8
s16p     16
s32p     32
fltp     32
dblp     64
s64      64
s64p     64

如果是  AV_SAMPLE_FMT_DBL ,大小为: 2*1024*8 = 16384

2.6 ⾳频播放时间计算

以采样率44100Hz来计算,也就是每秒44100个样本,
因此 播放一个样本的时间为 1÷44100 秒 。
⽽aac正常⼀帧为1024个sample,可知aac每帧播放时间:
1÷44100 x 1024 秒 = 1÷44100 x 1024 x 1000 毫秒 = 23.21995464852608毫秒
即:⼀帧播放时间(毫秒
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值