不同的⾳源有不同的格式,采样率等,所谓的重采样,就是改变⾳频的采样率、sample format、声道数等参数,使之按照我们期望的参数输出。
重采样的参数
typedef struct audio_resampler_params {
// 输入参数
enum AVSampleFormat src_sample_fmt;
int src_sample_rate;
uint64_t src_channel_layout;
// 输出参数
enum AVSampleFormat dst_sample_fmt;
int dst_sample_rate;
uint64_t dst_channel_layout;
}audio_resampler_params_t;
封装的重采样器
typedef struct audio_resampler {
struct SwrContext *swr_ctx; // 重采样上下文
audio_resampler_params_t resampler_params; // 重采样的设置参数
int is_fifo_only; // 不需要进行重采样,只需要缓存到 audio_fifo
int is_flushed; // flush的时候使用
AVAudioFifo *audio_fifo; // 采样点的缓存
int64_t in_start_pts; // 进入的起始pts
int64_t in_last_pts; // 保存上一次的pts时间戳
int64_t out_start_pts; // 输出的pts
int64_t out_cur_pts; // 当前pts
uint8_t **resampled_data; // 用来缓存重采样后的数据
int resampled_data_size; // 重采样后的采样数
int src_channels; // 输入的通道数
int dst_channels; // 输出通道数
int64_t total_resampled_num; // 统计总共的重采样点数
}audio_resampler_t;
/* alloc*/
audio_resampler->swr_ctx = swr_alloc();
/* set options */
av_opt_set_sample_fmt(audio_resampler->swr_ctx, "in_sample_fmt", resampler_params.src_sample_fmt, 0);
av_opt_set_int(audio_resampler->swr_ctx, "in_channel_layout", resampler_params.src_channel_layout, 0);
av_opt_set_int(audio_resampler->swr_ctx, "in_sample_rate", resampler_params.src_sample_rate, 0);
av_opt_set_sample_fmt(audio_resampler->swr_ctx, "out_sample_fmt", resampler_params.dst_sample_fmt, 0);
av_opt_set_int(audio_resampler->swr_ctx, "out_channel_layout", resampler_params.dst_channel_layout, 0);
av_opt_set_int(audio_resampler->swr_ctx, "out_sample_rate", resampler_params.dst_sample_rate, 0);
/* initialize the resampling context */
ret = swr_init(audio_resampler->swr_ctx);
audio_resampler->audio_fifo = av_audio_fifo_alloc(resampler_params.dst_sample_fmt, audio_resampler->dst_channels, 1);
src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
// 给输入源分配内存空间
av_samples_alloc_array_and_samples(&src_data, &src_linesize, src_nb_channels, src_nb_samples, src_sample_fmt, 0);
dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
// 分配输出缓存内存
av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, dst_sample_fmt, 0);
int nb_samples = swr_convert(resampler->swr_ctx, resampler->resampled_data, dst_nb_samples, (const uint8_t **)src_data, src_nb_samples);
int ret_size = av_audio_fifo_write(resampler->audio_fifo, (void **)resampler->resampled_data, nb_samples);
c) 接收音频:从audio fifo中读取一帧数据并写入目标缓存。
av_audio_fifo_read(resampler->audio_fifo, (void **)frame->data, nb_samples);
5.冲刷缓冲区,以及进行内存释放。
https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/resample_audio.c