音频重采样-libswresample

头文件<libswresample/swresample.h>

功能:
1)采样频率转换:对音频的采样频率转换,如将采样率从44.1K转换到48K,注意从高采样频率到低采样频率的音频转换是一个有损的过程。
2)声道格式转换:对音频的声道格式转换,将立体声转换为单声道。
3)样本格式转换:对音频的样本格式转换,还包括Packed和Planar包装格式之间相互转换。

音频重采样步骤:
    1)创建重采样过程的上下文环境,SwrContext结构体
    2)设置参数( 通道数、采样率、采样长度),将重采样的参数设置到SwrContext中:swr_alloc_set_opts()
    3)SwrContext初始化:swr_init()    //每次设置或修改SwrContext参数后都必须调用swr_init()
    4)分配样本数据内存空间: av_sample_alloc()、 av_samples_alloc_array_and_samples()
    5)开启重采样转换: swr_convert() 针对每一帧音频的处理
    6)重采样转换完成后释放资源:swr_free()

1、swr_alloc_set_opts()

SwrContext *swr_alloc_set_opts(struct SwrContext *s,/*上下文结构体,若为NULL会自动分配一个*/
                               int64_t out_ch_layout,/*重采样声道layout*/
                               AVSampleFormat out_sample_fmt,/*重采样样本格式*/
                               int out_sample_rate,/*重采样的样本率/采样率*/
                               int64_t in_ch_layout,/*源声道layout*/
                               AVSampleFormat in_sample_fmt,/*源音频的样本格式*/
                               int in_sample_rate,/*源音频的样本率/采样率*/
                               int log_offset,/*日志 一般为NULL*/
                               void *log_ctx/*日志 一般为NULL*/
);

设置重采样参数,一般而言重采样后采样率最好大于重采样前的采样率(不然容易发生数据丢失出现杂音)。也可以通过 swr_alloc()函数创建SwrContext上下文结构,再调用AVOptions的API( av_opt_set_*)来设置具体的参数。

2、int swr_init()

int swr_init(struct SwrContext *s);        // 每次设置或修改SwrContext参数后都必须调用swr_init()

3、swr_convert()

int swr_convert(struct SwrContext *s, /*上下文结构体*/ 
                            uint8_t **out, /*重采样后的数据*/ 
                            int out_count, /*重采样后单通道的样本数量(不是字节数)*/ 
                            const uint8_t **in , /*采样前的源数据*/
                            int in_count /*源单通道的样本数量*/
);
1) 如果没有提供足够的空间用于保存输出数据,采样数据会缓存在swr中。可以通过 swr_get_out_samples()来获取下一次调用swr_convert在给定输入样本数量下输出样本数量的上限,来提供足够的空间。
2)如果是采样频率转换,转换完成后采样数据可能会缓存在swr中,它希望你能给它更多的输入数据。
3)如果实际上并不需要更多输入数据,通过调用swr_convert(),其中参数in_count设置为0来获取缓存在swr中的数据。
4)转换结束之后需要冲刷swr_context的缓冲区,通过调用swr_convert(),其中参数in设置为NULL,参数in_count设置为0。
 

在调用swr_context转换之前需要分配内存空间用于保存重采样的输出数据,内存空间的大小跟通道个数、样本格式、样本个数有关。libavutil中提供了一些函数方便管理样本数据,例如av_samples_alloc()和av_samples_alloc_array_and_samples()函数用于分配存储音频数据的空间。

int av_samples_alloc(uint8_t **audio_data, /*对应frame的data数据,每个元素是指向一个通道的数据的指针*/
                    int *linesize, /*audio_data中每个元素的大小,对于frame的linsize*/
                    int nb_channels, /*通道个数*/
                    int nb_samples,  /*每个通道的样本数*/
                    enum AVSampleFormat sample_fmt, /*音频格式*/
                    int align /*audio_data中对齐方式 (0:默认对齐方式, 1:无对齐*/
);
//返回值大于等于0表示分配成功

 

要在 C 语言中实现 FFmpeg音频重采样,需要使用 FFmpeglibswresample 库。下面是一个简单的音频重采样的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <libswresample/swresample.h> int main(int argc, char **argv) { // source audio data uint8_t *src_data[2] = { NULL }; src_data[0] = (uint8_t *)malloc(src_nb_samples * src_channels * sizeof(uint8_t)); src_data[1] = NULL; int src_nb_samples = 1024; int src_channels = 2; int src_sample_rate = 44100; int src_bytes_per_sample = 2; // destination audio data uint8_t *dst_data[2] = { NULL }; dst_data[0] = (uint8_t *)malloc(dst_nb_samples * dst_channels * sizeof(uint8_t)); dst_data[1] = NULL; int dst_nb_samples = 1024; int dst_channels = 1; int dst_sample_rate = 48000; int dst_bytes_per_sample = 2; // create resampler context SwrContext *swr_ctx = swr_alloc_set_opts(NULL, av_get_default_channel_layout(dst_channels), AV_SAMPLE_FMT_S16, dst_sample_rate, av_get_default_channel_layout(src_channels), AV_SAMPLE_FMT_S16, src_sample_rate, 0, NULL); swr_init(swr_ctx); // perform audio resampling swr_convert(swr_ctx, dst_data, dst_nb_samples, (const uint8_t **)src_data, src_nb_samples); // cleanup swr_free(&swr_ctx); free(src_data[0]); free(dst_data[0]); return 0; } ``` 上述代码中,我们首先定义了源音频和目标音频的相关参数,包括采样率、声道数、采样位数等。然后我们创建了一个 SwrContext 上下文对象,并设置了源和目标音频的相关参数。接着我们调用 swr_init 函数初始化这个上下文对象,然后使用 swr_convert 函数将原始音频数据重采样为目标音频数据。最后我们释放了上下文对象和内存空间。 需要注意的是,该示例代码仅为了演示音频重采样的基本流程,实际使用时还需要进行参数检查和错误处理等操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值