基于FFmpeg, 实现 8k 16bit 立体声 转码 16k 16bit 单声道。
命令 🐳
ffmpeg -i original.wav -ac 1 -ar 16000 new.wav
CODE 🚀
-
设置重采样数据
-
输入: 立体声, 双通道, 8k, 16bit
输出: 单声道, 单通道, 16k, 16bit
-
// 准备重采样 struct SwrContext* swr = swr_alloc(); av_opt_set_int(swr, "in_channel_count", pCodecCtx->channels, 0); av_opt_set_int(swr, "out_channel_count", DST_CHANNELS, 0); av_opt_set_int(swr, "in_channel_layout", pCodecCtx->channel_layout, 0); av_opt_set_int(swr, "out_channel_layout", AV_CH_LAYOUT_MONO, 0); av_opt_set_int(swr, "in_sample_rate", pCodecCtx->sample_rate, 0); av_opt_set_int(swr, "out_sample_rate", DST_SAMPLE_RATE, 0); av_opt_set_sample_fmt(swr, "in_sample_fmt", pCodecCtx->sample_fmt, 0); av_opt_set_sample_fmt(swr, "out_sample_fmt", DST_SAMPLE_FMT, 0); // 初始化 swr_init(swr); if (!swr_is_initialized(swr)) { fprintf(stderr, "Resampler has not been properly initialized\n"); return NULL; }
-
-
重采样
-
解码一帧音频
-
// 解码一帧音频 if (avcodec_decode_audio4(pCodecCtx, frame, &gotFrame, &packet) < 0) break; if (!gotFrame) { printf("avcodec_decode_audio4 error. \n"); continue; }
-
-
计算实际重采样后得到的数据大小, 然后重新分配缓存
-
int dst_nb_samples = av_rescale_rnd(swr_get_delay(swr, DST_SAMPLE_RATE) + frame->nb_samples,DST_SAMPLE_RATE, pCodecCtx->sample_rate, AV_ROUND_UP);
-
-
由于双声道转单声道,所以输入的通道个数等于输出通道个数的2倍。
-
int outSize = dst_nb_samples * 2; int inSize = frame->nb_samples;
-
-
据音频格式分配相应大小的内存空间
-
uint8_t** buffer; av_samples_alloc((uint8_t**)&buffer, NULL, DST_CHANNELS, outSize, DST_SAMPLE_FMT, 0);
-
-
进行重采样
-
// 重采样 int frame_count = swr_convert(swr, (uint8_t**)&buffer, outSize, (const uint8_t**)frame->data, inSize); if (frame_count < 0) { av_freep(&buffer); printf("swr_convert error\n"); break; }
-
-
获取给定音频参数所需的缓冲区大小。
-
dst_bufsize = av_samples_get_buffer_size(&dst_linesize, DST_CHANNELS, frame_count, DST_SAMPLE_FMT, 0); if (dst_bufsize < 0) { av_freep(&buffer); printf("av_samples_get_buffer_size error\n"); return -1; }
-
-
写入 wav 文件
-
audioFileSize += dst_bufsize; fwrite(buffer, 1, dst_bufsize, p); fflush(p); av_freep(&buffer);
-
-
写入文件长度和数据长度 ,最后关闭文件
-
fseek(p, 40, SEEK_SET); fwrite(&audioFileSize, 1, sizeof(int32_t), p); audioFileSize += 36; fseek(p, 4, SEEK_SET); fwrite(&audioFileSize, 1, sizeof(int32_t), p); fclose(p);
-
-
DEMO: https://download.csdn.net/download/haiyangyunbao813/17984367
参考博客 🅱️
- https://blog.csdn.net/weixin_41353840/article/details/112568105?utm_medium=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase
- https://blog.csdn.net/sun007700/article/details/115034806