使用FFMPEG进行音频重采样

news2024/12/24 11:31:43

准备

1. ffmpeg 4.4

2. sdl2

3.一段原始的音频PCM数据

重采样流程

1.设置输入音频参数和输出音频参数

2.根据设置的参数初始化SwrContent上下文

3.创建一个输入buffer, 根据输入的音频参数(采样率,通道数,样本位深度)申请空间,填入默认数据,用于存储输入音频数据

4.创建一个输出buffer, 根据输出的音频参数(采样率,通道数,样本位深度)申请空间,填入默认数据,用于存储重采样后的数据

5.读取PCM数据,每次读取的大小等于输入buffer的大小

6.进行重采样swr_convert

7.将输出的buffer拷贝到SDL2音频回调缓冲区中播放,或者直接写入文件,使用ffplay进行测试,也可以封装成Frame送到音频编码器中(如aac),进行编码后保存。

关键代码

设置重采样参数并初始化SWr_Content结构


struct SwrContext* swr_ctx;

swr_ctx = swr_alloc_set_opts(nullptr,
		AV_CH_LAYOUT_MONO, //输出通道
		AV_SAMPLE_FMT_S16, //输出样本格式
		44100, //输出采样率
		AV_CH_LAYOUT_STEREO,  //输入通道
		AV_SAMPLE_FMT_FLT,  //输入样本格式
		44100, //输入采样率
		0, nullptr); 

	swr_init(swr_ctx);

输入/输出buffer 创建

	//输入数据buffer
	uint8_t** pcm_buffer;
	int src_linesize;
	int src_nb_channels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);
	int ret = av_samples_alloc_array_and_samples(&pcm_buffer, &src_linesize, src_nb_channels, frame_nb_samples, AV_SAMPLE_FMT_FLT, 0);
	if (ret < 0) {
		fprintf(stderr, "Could not allocate source samples\n");	
	}

	//输出数据buffer
	uint8_t** out_buffer;
	int dst_linesize;
	int dst_nb_channels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_MONO);
	ret = av_samples_alloc_array_and_samples(&out_buffer, &dst_linesize, dst_nb_channels, frame_nb_samples, AV_SAMPLE_FMT_S16, 0);
	if (ret < 0) {
		fprintf(stderr, "Could not allocate source samples\n");
	}

读文件并进行重采样

readcount = fread((char *)pcm_buffer[0], 1, src_linesize, fp);

data_count += readcount;
printf("   Now Playing %10d KBytes data.  %d \n", data_count / 1024, readcount);
		
swr_convert(swr_ctx, out_buffer, frame_nb_samples, (const uint8_t**)pcm_buffer, frame_nb_samples);

源码分享

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sdl.h"

extern "C"
{
	#include <libavutil/opt.h>
	#include <libavutil/channel_layout.h>
	#include <libavutil/samplefmt.h>
	#include <libswresample/swresample.h>
}

static  Uint32  audio_len;
static  Uint8* audio_pos;
int frame_nb_samples = 1024; //一帧数据样本数
struct SwrContext* swr_ctx;


void  fill_audio_pcm(void* udata, Uint8* stream, int len) 
{
	SDL_memset(stream, 0, len);

	if (audio_len == 0)
		return;
	len = (len > audio_len ? audio_len : len);

	SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);
	audio_pos += len;
	audio_len -= len;
}

int main(int argc, char* argv[])
{
	if (SDL_Init(SDL_INIT_AUDIO || SDL_INIT_TIMER))
	{
		printf("SDL init error\n");
		return -1;
	}

	swr_ctx = swr_alloc_set_opts(nullptr,
		AV_CH_LAYOUT_MONO, //输出通道
		AV_SAMPLE_FMT_S16, //输出样本格式
		44100, //输出采样率
		AV_CH_LAYOUT_STEREO,  //输入通道
		AV_SAMPLE_FMT_FLT,  //输入样本格式
		44100, //输入采样率
		0, nullptr); 

	swr_init(swr_ctx);

	//SDL_AudioSpec
	SDL_AudioSpec wanted_spec;
	wanted_spec.freq = 44100;
	wanted_spec.format = AUDIO_F32; //AUDIO_S16LSB; //AUDIO_F32;
	wanted_spec.channels = 2;
	wanted_spec.silence = 0;
	wanted_spec.samples = frame_nb_samples;
	wanted_spec.callback = fill_audio_pcm;

	if (SDL_OpenAudio(&wanted_spec, NULL) < 0) {
		printf("can't open audio.\n");
		return -1;
	}
	//Play
	SDL_PauseAudio(0);
	
	//输入数据buffer
	uint8_t** pcm_buffer;
	int src_linesize;
	int src_nb_channels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);
	int ret = av_samples_alloc_array_and_samples(&pcm_buffer, &src_linesize, src_nb_channels, frame_nb_samples, AV_SAMPLE_FMT_FLT, 0);
	if (ret < 0) {
		fprintf(stderr, "Could not allocate source samples\n");	
	}

	//输出数据buffer
	uint8_t** out_buffer;
	int dst_linesize;
	int dst_nb_channels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_MONO);
	ret = av_samples_alloc_array_and_samples(&out_buffer, &dst_linesize, dst_nb_channels, frame_nb_samples, AV_SAMPLE_FMT_S16, 0);
	if (ret < 0) {
		fprintf(stderr, "Could not allocate source samples\n");
	}

	FILE* fp = nullptr;
	fopen_s(&fp, "D:/工程/音视频分析/source/f32le.pcm", "rb+");
	if (fp == NULL) {
		printf("cannot open this file\n");
		return -1;
	}
	int readcount = -1;
	int data_count = 0;
	while (!feof(fp)) 
	{
		readcount = fread((char *)pcm_buffer[0], 1, src_linesize, fp);

		data_count += readcount;
		printf("   Now Playing %10d KBytes data.  %d \n", data_count / 1024, readcount);
		
		swr_convert(swr_ctx, out_buffer, frame_nb_samples, (const uint8_t**)pcm_buffer, frame_nb_samples);

		//Set audio buffer (PCM data)
		audio_len = dst_linesize; 
		audio_pos =  (Uint8*)out_buffer[0]; //(Uint8*)pcm_buffer[0];

		while (audio_len > 0)
			SDL_Delay(1);
		
	}

	if (pcm_buffer)
		av_freep(&pcm_buffer[0]);
	av_freep(&pcm_buffer);

	if (out_buffer)
		av_freep(&out_buffer[0]);
	av_freep(&out_buffer);

	swr_free(&swr_ctx);

	fclose(fp);
	SDL_Quit();

	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/547292.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习项目实战-能源利用率 Part-3(特征工程与特征筛选)

博主前期相关的博客可见下&#xff1a; 机器学习项目实战-能源利用率 Part-1&#xff08;数据清洗&#xff09; 机器学习项目实战-能源利用率 Part-2&#xff08;探索性数据分析&#xff09; 这部分进行的特征工程与特征筛选。 三 特征工程与特征筛选 一般情况下我们分两步走…

李彦宏一句“车水马龙”,中国AI的一幕天地宽广

“什么叫生成式&#xff1f;比如说&#xff0c;给我画一幅车水马龙的图片。这种东西&#xff0c;过去人们不觉得是人工智能应该做的事&#xff0c;现在可以做了。”5月18日&#xff0c;百度CEO李彦宏在天津举办的第七届世界智能大会上演讲时&#xff0c;说了这么一句话。 不了解…

保护你无价的数据 | 推荐一个开源备份工具,可去重、增量、压缩、还原到特定日期...

Borg 数据备份 Borg 的优势是 高效&#xff1a;BorgBackup 会将文件按数据块去重&#xff0c;只有改动的数据块才会被备份。一个 25 GiB 的虚拟机磁盘文件&#xff0c;只改动了 1 GiB&#xff0c;那就只会新增备份这 1 GiB 的数据&#xff1b;高速&#xff1a;核心算法使用 C 编…

5-《Kotlin》

5-《Kotlin》 1.kotlin基础&#xff1a; From Java To Kotlin2.Kotlin 的延迟初始化: lateinit var 和 by lazy1.lateinit var2.by lazy 3 Kotlin Tips:怎么用 Kotlin 去提高生产力&#xff08;kotlin优势&#xff09;Tip1- 更简洁的字符串Tip2- Kotlin中大多数控制结构都是表达…

[RapidOCRWeb] 桌面版使用教程

引言 说明&#xff1a;桌面版指的是可以直接解压&#xff0c;双击即可运行的版本。通俗来说&#xff0c;对rapidocr_web做了打包&#xff0c;将相关依赖全部放到一个zip包中&#xff0c;不需要本地有额外的环境&#xff0c;降低使用门槛。下面会以Windows版为例&#xff0c;作…

LeetCode 1373. 二叉搜索子树的最大键值和

【LetMeFly】1373.二叉搜索子树的最大键值和 力扣题目链接&#xff1a;https://leetcode.cn/problems/maximum-sum-bst-in-binary-tree/ 给你一棵以 root 为根的 二叉树 &#xff0c;请你返回 任意 二叉搜索子树的最大键值和。 二叉搜索树的定义如下&#xff1a; 任意节点的…

pandas---数据处理(excel文件)

近期在弄一个项目的前期数据&#xff0c;所以总结了一下&#xff0c;内容如下&#xff08;以下以csv文件为例&#xff09; 1. DataFrame常用操作1.1 DataFrame去除空行&#xff08;1&#xff09;对于一般空行&#xff08;2&#xff09;对于列表式&#xff08;list&#xff09;空…

Redis(二)对事务进行操作及Jedis

系列文章目录 Redis入门笔记&#xff08;一&#xff09;&#xff1a;Redis在Linux下安装和八大数据类型 文章目录 系列文章目录前言Redis对事务进行操作开启事务&#xff1a;multi执行事务&#xff1a;exec放弃事务&#xff1a;discard编译型异常&#xff08;命令错误&#xf…

信息安全-数据安全-字节大数据平台安全与权限治理实践

导读&#xff1a;本次分享题目为字节跳动大数据平台安全与权限治理实践&#xff0c;文章会围绕下面四点展开&#xff1a; 字节大数据安全体系现状和难点 细粒度权限管控和治理 资产保护能力 数据删除能力 分享嘉宾&#xff5c;许从余 火山引擎 数据平台产品经理 编辑整理&#…

Spring 5 笔记 - 新功能

1. Spring 5 框架新功能 整个Spring 5 框架的代码基于Java8&#xff0c;运行时兼容JDK9&#xff0c;许多不建议使用的类和方法在代码库中删除。Spring 5.0 框架自带了通用的日志封装 &#xff08;1&#xff09;Spring 5 已经移除 Log4jConfigListener&#xff0c;官方建议使用…

立创EDA标准版指南1-原理图与封装库

立创 EDA 标准版 由于立创 EDA 新版本改了对应术语&#xff0c;这是对于的表格&#xff1a; 原理图库->符号 PCB 库->封装 PCB 3D 库->3D 模型 下面的全部讲述将依据旧版称呼&#xff0c;因为更直观&#xff0c;新版称呼模棱两可并且与 AD 的工程架构差别较大 这是…

数据分析11——Pandas中数据偏移/数据切分/数据结构转换

数据偏移&#xff1a; 1、shift函数&#xff1a; 在 Pandas 中&#xff0c;shift 函数用于将数组的数据向前或向后平移指定的步数。它可以应用于 Series 或 DataFrame 类型的数据中&#xff0c;并返回一个平移后的新数据结构&#xff0c;其中每个元素都被取代为原始序列中对应…

kubernetes根据podName获取对应的主机pid

获取指定的podName kubectl get pods -n demo -owide登录对应的主机执行docker命令,获取到容器的id docker ps | grep PODNAME拿到的容器id&#xff0c;执行如下命令 获取容器的长的容器id docker inspect container_id找到容器id后 执行 apt-get install jq cat /var/lib…

关于Word文档的处理【笔记】

关于Word文档的处理【笔记】 前言推荐关于Word文档的处理一、解压word如何恢复1 准备2 解压3 恢复 二、对word文档进行图片替换1 首先解压word文档2 进入word文档存放图片的路径3 批量给图片添加水印4 替换原来的media文件5 压缩为docx文件6 打开 最后 前言 2023-5-20 11:00:1…

uniapp 快手授权登录,发布、编辑、裁剪图片和视频,分享 Ba-Kwai

简介&#xff08;下载地址&#xff09; 快手授权登录&#xff0c;发布、编辑、裁剪图片和视频&#xff0c;一键智能裁剪&#xff0c;分享私信&#xff0c;打开用户主页&#xff0c;挂载小程序等。自带选择图片和选择视频方法。 抖音授权登录、发布、分享 Ba-Aweme&#xff08…

基于GitLab搭建DevSecOps流水线

本博客地址&#xff1a;https://security.blog.csdn.net/article/details/130734964 一、GitLab安装 GitLab是一个用于仓库管理系统的开源项目&#xff0c;使用Git作为代码管理工具&#xff0c;并在此基础上搭建Web服务&#xff0c;可通过Web界面访问公开的或者私人的项目。它…

【总结】数据建模调研与设计

一、数据建模背景和目的 1.1 数据建模任务背景 a. xxxx 中台新增数据建模模块&#xff0c;对标行业最佳实践&#xff0c;补齐数据中台短板。 b. 以往的数据建模&#xff0c;包括数仓模型的设计、数仓模型的落地&#xff0c;都是通过第三方的工具&#xff0c;例如DBwaver、Nav…

SOFA Weekly|SOFA 大事记、Layotto 社区会议回顾与预告、社区本周贡献

SOFA WEEKLY | 每周精选 筛选每周精华问答&#xff0c;同步开源进展 欢迎留言互动&#xff5e; SOFAStack&#xff08;Scalable Open Financial Architecture Stack&#xff09;是蚂蚁集团自主研发的金融级云原生架构&#xff0c;包含了构建金融级云原生架构所需的各个组件&am…

【信息安全案例】——应用软件安全(学习笔记)

&#x1f4d6; 前言&#xff1a;随着应用软件日益增多&#xff0c;与我们的生活深度绑定&#xff0c;应用软件的安全性问题愈发凸显。针对恶意代码、代码漏洞等安全风险&#xff0c;必须加强安全意识&#xff0c;采取有效措施进行防范。合理有效的安全措施能够确保用户的信息安…

(数字图像处理MATLAB+Python)第九章图像形态学运算-第一、二节:形态学基础和二值形态学运算

文章目录 一&#xff1a;形态学基础&#xff08;1&#xff09;结构元素&#xff08;2&#xff09;程序 二&#xff1a;二值形态学的基础运算&#xff08;1&#xff09;基本形态变换A&#xff1a;膨胀运算①&#xff1a;概述②&#xff1a;示例③&#xff1a;程序 B&#xff1a;…