当前位置: 首页 > news >正文

音视频开发_SDL音频播放器的实现

今天向大家介绍一下如何通过 SDL 实现一个PCM音频播放器。这是一个最简单的播放器,它不涉及到音频的解复用,解码等工作。我们只需要将音频原始数据喂给 SDL 音频接口就可以听到悦耳的声音了。在下面的列子中我将向你演示,使用 SDL 做这样一个播放器是何等的简单。

当然这个看似简单的播放器其实是由许多的理论基础在底层支持着的

播放音频的基本原则

如果我们要播放一段声音,想当然的认为直接将播放的声音发送给声卡,这样扬声器就会将声音播放出来。只要我们不断的送数据,声音就会不停的输出。

事实上真的是这样吗?当 然 不 是!!!

实际上,所有的音频播放都遵守着一个原则,就是当声卡将要播放的声音输出到扬声器时,它首先会通过回调函数,向你要它一部分声频数据,然后拿着这部分音频数据去播放。等播放完了,它会再向你要下一部分。

至于要的数据的多少,什么时候向你要,这些都是由声卡决定的。对于我们上层应用来说,这些都是由底层 API 决定的。

为什么会出现这种情况呢?为什么播放音频与我们一般的逻辑相反呢?这是因为声卡会严格按照音频的播放时间进行播放,不会多一秒,也不会少一秒。正因为它能准确的计算出时间来,而应用层是不知道这个时间的,所以我们必须按照声卡的要求给它喂数据,而不能依据自己的性子来。

那么有人会问,为什么声卡可以精准的计算出播放时间来呢?这是因为在播放之前我们给它设置了采样率、通道数、采样大小等参数,通过这些参数它就可以计算出时间来。

我们来做个计算,假设采样率是 48000, 双通道,采样大小是 16bit,那么一秒种的数据是多少呢? 48000*2*16=1536000. 反过来,如果我们有一段 8M 的数据,那么声卡就知道它能播放 5秒多的声音。

上面的一大段文字描述,实际上只是想说明一个道理,就是要播放的声音数据,是声卡主动要的,不能由上层直接设置。这是通过回调函数来实现的。后面会有具体的例子。

SDL如何处理音频

SDL是一个处理多媒体的开源库,我们来看看它是如何播放音频的,具体的操作步骤是啥?

  • 打开音频设备
  • 设置音频参数
  • 播放音频
  • 向声卡喂数据
  • 关闭音频设置

详细API介绍

  • 打开音频设备
int SDL_OpenAudio(SDL_AudioSpec* desired,SDL_AudioSpec* obtained)

desired: 设置音频参数。

参数

说明

freq

每秒采频率

SDL_AudioFormat

音频数据存储格式

channels

通道数

silence

静音值

samples

采样个数

size

音频缓冲区大小

SDL_AudioCallback

回调函数

userdata

回调函数参数指针

  • btained: 返回参数。
  • 关闭音频设备
void SDL_CloseAudio(void)

播放与暂停

void SDL_PauseAudio(int pause_on)
  • pause_on: 0, 暂停播放;1, 播放;
  • 喂数据
void SDL_MixAudio(Uint8*    dst,const Uint8* src,Uint32       len,int          volume)
  • dst: 目的缓冲区
  • src: 源缓冲区
  • len: 音频数据长度
  • volume: 音量大小,0-128 之间的数。SDL_MIX_MAXVOLUME代表最大音量。

例子

这个例子主要为大家展示了一下如何使用 SDL 的音频 API 来播放声音。其基本流程是,从 pcm 文件一块一块的读数据。然后通过 read_audio_data 这个回调函数给声卡喂数据。如果一次没用完,SDL会再次调用回调函数读数据。

如果audio_buf中的数据用完了,则再次从文件中读一块数据,直到读到文件尾。

#include <stdio.h>
#include <SDL.h>#define BLOCK_SIZE 4096000static Uint8 *audio_buf = NULL;
static Uint8 *audio_pos = NULL;
static size_t buffer_len = 0;//callback function for audio devcie
void read_audio_data(void *udata, Uint8 *stream, int len){if(buffer_len == 0){return;}SDL_memset(stream, 0, len);len = (len < buffer_len) ? len : buffer_len;SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);audio_pos += len;buffer_len -= len;
}int main(int argc, char *argv[])
{int ret = -1;FILE *audio_fd = NULL;SDL_AudioSpec spec;char *path = "./test.pcm";//SDL initializeif(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)){fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());return ret;}//open pcm fileaudio_fd = fopen(path, "r");if(!audio_fd){fprintf(stderr, "Failed to open pcm file!\n");goto __FAIL;}//SDL_AudioSpecspec.freq = 44100;;spec.format = AUDIO_S16SYS;spec.channels = 2;spec.silence = 0;spec.samples = 1024;;spec.callback = read_audio_data;;spec.userdata = NULL;//open audio devcieif(SDL_OpenAudio(&spec, NULL)){fprintf(stderr, "Failed to open audio device, %s\n", SDL_GetError());goto __FAIL;}//play audioSDL_PauseAudio(0);do{//read data from pcm filebuffer_len = fread(audio_buf, 1, BLOCK_SIZE, audio_fd);fprintf(stderr, "block size is %zu\n", buffer_len);audio_pos = audio_buf;//the main thread wait for a momentwhile(audio_pos < (audio_buf + buffer_len)) {SDL_Delay(1);}}while(buffer_len !=0);//close audio deviceSDL_CloseAudio();ret = 0;__FAIL://release some resourcesif(audio_buf){free(audio_buf);}if(audio_fd){fclose(audio_fd);}//quit SDLSDL_Quit();return ret;
}

粉丝福利, 免费领取C++音视频学习资料包+学习路线大纲、技术视频/代码,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,编解码,推拉流,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

相关文章:

音视频开发_SDL音频播放器的实现

今天向大家介绍一下如何通过 SDL 实现一个PCM音频播放器。这是一个最简单的播放器&#xff0c;它不涉及到音频的解复用&#xff0c;解码等工作。我们只需要将音频原始数据喂给 SDL 音频接口就可以听到悦耳的声音了。在下面的列子中我将向你演示&#xff0c;使用 SDL 做这样一个…...

C语言学习系列:初识C语言

前言&#xff0c;C语言是什么 语言&#xff0c;比如中文、英语、法语、德语等&#xff0c;是人与人交流的工具。 C语言也是语言&#xff0c;不过是一种特殊的语言&#xff0c;是人与计算机交流的工具。 为什么叫C语言呢&#xff1f; 这就要从C语言的历史说起了。 一&#…...

利用反向代理编写HTTP抓包工具——可视化界面

手写HTTP抓包工具——可视化界面 项目描述语言golang可视化fynev2功能代理抓包、重发、记录 目录 1. 示例1.1 主界面1.2 开启反向代理1.3 抓包1.4 历史记录1.5 重发 2. 核心代码2.1 GUI2.1 抓包 3. 结语3.1 传送门 1. 示例 1.1 主界面 1.2 开启反向代理 1.3 抓包 1.4 历史记录…...

下拉框数据被遮挡 且 后续数据无法下拉的 解决方法

目录 前言1. 问题所示2. 原理分析3. 解决方法3.1 添加空白版2.2 调整z-index2.3 父容器的溢出属性2.4 调整样式属性4. 效果图前言 小程序使用的是Uniapp,原理都差不多,索性标题就不标注Uniapp(小程序) 对于该问题调试了一个晚上,最终解决,对此记录下来 1. 问题所示 执…...

课设--学生成绩管理系统(二)

欢迎来到 Papicatch的博客 目录 &#x1f40b;引言 &#x1f988;编写目的 &#x1f988;项目说明 &#x1f40b;产品介绍 &#x1f988;产品概要说明 &#x1f988;产品用户定位 &#x1f988;产品中的角色 &#x1f40b; 产品总体业务流程图 &#x1f40b; 产品功…...

STM32CubeMX配置-外部中断配置

一、简介 MCU为STM32G070&#xff0c;配置为上升沿触发外部中断&#xff0c;在上升沿外部中断回调函数中进行相关操作。 二、外部中断配置 查看规格书中管教描述&#xff0c;找到I/O对应的外部中断线&#xff0c;然后进行如下上升沿触发外部中断配置。 三、生成代码 调用上升沿…...

基于Vue的日程排班表 - common-schedule

原文&#xff1a;基于Vue的日程排班表 - common-schedule-CSDN博客...

SmartEDA、Multisim、Proteus大比拼:电路设计王者之争?

在电路设计领域&#xff0c;SmartEDA、Multisim和Proteus无疑是三款备受瞩目的软件工具。它们各自拥有独特的功能和优势&#xff0c;但在这场电路设计王者的竞争中&#xff0c;谁才是真正的领跑者&#xff1f;让我们深入探究这三款软件的异同&#xff0c;揭示它们各自的魅力所在…...

【教资科一传统文化】文化素养传统文化之神话传说、天文历法、古代称谓、中国传统节日、成语典故

目录 ​编辑 传统文化之天文历法 (一)四时(四季)从农历、名称上掌握 (二)二十四节气&#xff08;1、名称2、季节-节气3、特殊&#xff09; (三)十二时辰&#xff08;1.先后顺序2.时间段3.别称&#xff09; (四)五更(五夜) (五)天干地支(1.名称2.纪年) ​文化素养传统文化…...

Apache Pulsar 从入门到精通

一、快速入门 Pulsar 是一个分布式发布-订阅消息平台&#xff0c;具有非常灵活的消息模型和直观的客户端 API。 最初由 Yahoo 开发&#xff0c;在 2016 年开源&#xff0c;并于2018年9月毕业成为 Apache 基金会的顶级项目。Pulsar 已经在 Yahoo 的生产环境使用了三年多&#…...

[Bug]使用duckduckgo的duckduckgo_search API搜索图片出现了错误

现在在kaggle上学习一个课程&#xff0c;第一课主要是识别图片里面是不是鸟&#x1f426;。其中一步是使用duckduckgo 搜索图片&#xff0c;源码&#xff1a; from duckduckgo_search import ddg_images from fastcore.all import * from fastbook import search_images_ddgde…...

线程池若干问题

线程池中线程异常后&#xff0c;销毁还是复用&#xff1f; 线程池在提交任务前&#xff0c;可以提前创建线程吗&#xff1f; 线程池中线程异常后&#xff0c;销毁还是复用&#xff1f; 直接说结论&#xff0c;需要分两种情况&#xff1a; 使用execute()提交任务&#xff1a…...

k8s+RabbitMQ单机部署

1 k8s 配置文件yaml: apiVersion: apps/v1 kind: Deployment metadata:name: rabbitmq-deploynamespace: rz-dt spec:replicas: 1selector:matchLabels:app: rabbitmqtemplate:metadata:labels:app: rabbitmqspec:containers:- name: rabbitmqimage: "rz-dt-image-server…...

github.com/therecipe/qt windows中安装

github.com/therecipe/qt windows中安装 a.准备好源码,解压到go/src/github.com/therecipe/qtwin下 b.设置cmd环境变量: set QT_DIRM:\work\tool\Qt5.14.2\5.14.2\mingw73_64 set QT_VERSION5.14.2 set QT_API5.13.0 set QT_QMAKE_DIRM:\work\tool\Qt5.14.2\5.14.2\mingw73_64\…...

LogicFlow 学习笔记——11. 对齐线 和 键盘快捷键

对齐线 Snapline 对齐线能够在节点移动过程中&#xff0c;将移动节点的位置与画布中其他节点位置进行对比&#xff0c;辅助位置调整。位置对比有如下两个方面。 节点中心位置节点的边框 对齐线使用 普通编辑模式下&#xff0c;默认开启对齐线&#xff0c;也可通过配置进行关…...

FastWeb - Lua开源跨平台网站开发服务

在网站开发领域&#xff0c;大家都熟知PHPStudy和宝塔这两款广受欢迎的工具&#xff0c;但今天我要介绍的是一款功能强大、支持跨平台的开源Lua网站开发服务——Fast Web&#xff0c;以及与之配套的网站管理器。 Fast Web简介 Fast Web是一款基于Lua编写的网站开发框架&#…...

原子阿波罗STM32F767程序的控制器改为STM32F407驱动LCD屏

由于手里没有原子大神的F429开发板&#xff0c;又还想学习原子大神的F429开发板程序&#xff0c;前几天&#xff0c;经过更换控制器&#xff0c;成功把原子大神的F429开发板程序用到了F407开发板上&#xff0c;驱动LCD屏显示成功&#xff0c;目的&#xff0c;就是熟悉原子大神的…...

04-jQuery工具函数及 jQuery 插件

1. jQuery工具函数 在jQuery中,工具函数是指直接依附于jQuery对象,针对jQuery对象本身定义的方法,即全局性的,我们统称为工具函数,或Utilites函数。 主要作用于&#xff1a;字符串、数组、对象。 调用格式: $.函数名()或jQuery.函数名() 1.1 $.get() 通过远程 HTTP GET 请…...

基于Python的花卉识别分类系统【W9】

简介&#xff1a; 基于Python的花卉识别分类系统利用深度学习和计算机视觉技术&#xff0c;能够准确识别和分类各种花卉&#xff0c;如玫瑰、郁金香和向日葵等。这种系统不仅有助于植物学研究和园艺管理&#xff0c;还在生态保护、智能农业和市场销售等领域展现广泛应用前景。随…...

Visual Studio Code 配置教程,手把手教你如何配置

文章目录 引言1. 安装 VS Code1.1 下载和安装1.2 初次启动 2. 基本配置2.1 设置用户和工作区配置2.2 常用配置项 3. 安装和配置扩展插件3.1 安装扩展3.2 推荐扩展3.3 配置扩展 4. 主题和配色方案4.1 安装主题4.2 切换主题4.3 自定义配色方案 5. 版本控制集成5.1 配置 Git5.2 Gi…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...