最简单的基于 SDL2 的音频播放器

2023-12-31 18:28
文章标签 简单 音频 播放器 sdl2

本文主要是介绍最简单的基于 SDL2 的音频播放器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最简单的基于 SDL2 的音频播放器

  • 最简单的基于 SDL2 的音频播放器
    • 正文
    • 工程文件下载

参考雷霄骅博士的文章,链接:最简单的基于FFMPEG+SDL的音频播放器:拆分-解码器和播放器

最简单的基于 SDL2 的音频播放器

正文

SDL2 音频播放器实现了播放 PCM 数据。

如果你不会 Vusual Studio 下 SDL2 的项目配置,可以看我写的教程:Visual Studio 2015 中 SDL2 开发环境的搭建。

源代码:

// Simplest Audio Player SDL2.cpp : 定义控制台应用程序的入口点。/**
* 最简单的SDL2播放音频的例子(SDL2 播放 PCM)
* Simplest Audio Play SDL2 (SDL2 play PCM)
*
* 原程序:
* 雷霄骅 Lei Xiaohua
* leixiaohua1020@126.com
* 中国传媒大学/数字电视技术
* Communication University of China / Digital TV Technology
* http://blog.csdn.net/leixiaohua1020
*
* 修改:
* 刘文晨 Liu Wenchen
* 812288728@qq.com
* 电子科技大学/电子信息
* University of Electronic Science and Technology of China / Electronic and Information Science
* https://blog.csdn.net/ProgramNovice
*
* 本程序使用 SDL2 播放 PCM 音频采样数据。
* SDL 实际上是对底层绘图 API(Direct3D,OpenGL)的封装,使用起来明显简单于直接调用底层 API。
*
*
* 函数调用步骤如下:
*
* [初始化]
* SDL_Init(): 初始化 SDL。
* SDL_OpenAudio(): 根据参数(存储于 SDL_AudioSpec)打开音频设备。
* SDL_PauseAudio(): 播放音频数据。
*
* [循环播放数据]
* SDL_Delay(): 延时等待播放完成。
*
* This software plays PCM raw audio data using SDL2.
* SDL is a wrapper of low-level API (DirectSound).
* Use SDL is much easier than directly call these low-level API.
*
* The process is shown as follows:
*
* [Init]
* SDL_Init(): Init SDL.
* SDL_OpenAudio(): Opens the audio device with the desired
*					parameters (In SDL_AudioSpec).
* SDL_PauseAudio(): Play Audio.
*
* [Loop to play data]
* SDL_Delay(): Wait for completetion of playback.
*/#include "stdafx.h"#include <stdio.h>
#include <tchar.h>// 解决报错:无法解析的外部符号 __imp__fprintf,该符号在函数 _ShowError 中被引用
#pragma comment(lib, "legacy_stdio_definitions.lib")
extern "C"
{// 解决报错:无法解析的外部符号 __imp____iob_func,该符号在函数 _ShowError 中被引用FILE __iob_func[3] = { *stdin, *stdout, *stderr };
}extern "C"
{
#include "SDL2/SDL.h"
}// Buffer:
// |-----------|-------------|
// chunk-------pos---len-----|
static  Uint8  *audio_chunk;
static  Uint32  audio_len;
static  Uint8  *audio_pos;/* 音频回调函数
* 开始播放后,会有音频其他子线程来调用回调函数,进行音频数据的补充,经过测试每次补充 4096 个字节
* The audio function callback takes the following parameters:
* stream: A pointer to the audio buffer to be filled
* len: The length (in bytes) of the audio buffer
*
*/
void  fill_audio(void *udata, Uint8 *stream, int len)
{// SDL 2.0SDL_memset(stream, 0, len);if (audio_len == 0)		/*  Only  play  if  we  have  data  left  */return;len = (len > audio_len ? audio_len : len); /*  Mix  as  much  data  as  possible  *//* 混音播放函数* dst: 目标数据,这个是回调函数里面的 stream 指针指向的,直接使用回调的 stream 指针即可* src: 音频数据,这个是将需要播放的音频数据混到 stream 里面去,那么这里就是我们需要填充的播放的数据* len: 音频数据的长度* volume: 音量,范围 0~128 ,SAL_MIX_MAXVOLUME 为 128,设置的是软音量,不是硬件的音响*/SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);audio_pos += len;audio_len -= len;
}int main(int argc, char* argv[])
{// Step 1: 初始化音频子系统和计时器子系统if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER)){printf("Could not initialize SDL - %s.\n", SDL_GetError());return -1;}// Step 2: 根据音频信息打开音频设备// SDL_AudioSpec 是包含音频输出格式的结构体,同时它也包含当音频设备需要更多数据时调用的回调函数SDL_AudioSpec wanted_spec;wanted_spec.freq = 44100; // 采样率wanted_spec.format = AUDIO_S16SYS; // 音频数据格式wanted_spec.channels = 2; // 通道数wanted_spec.silence = 0; // 音频缓冲静音值wanted_spec.samples = 1024; // 基本是 512、1024,设置不合适可能会导致卡顿wanted_spec.callback = fill_audio;// 为音频设备提供数据回调(空值使用 SDL 自身预先定义的SDL_QueueAudio() 回调函数)// 使用所需参数打开音频设备if (SDL_OpenAudio(&wanted_spec, NULL) < 0){printf("Can't open audio.\n");return -1;}FILE *fp = fopen("NocturneNo2inEflat_44.1k_s16le.pcm", "rb+");if (fp == nullptr){printf("Could not open this file.\n");return -1;}const int pcm_buffer_size = 4096;char *pcm_buffer = (char *)malloc(pcm_buffer_size);int data_count = 0;// Step 3: 开始播放SDL_PauseAudio(0);// Step 4: 循环补充数据while (1){if (fread(pcm_buffer, 1, pcm_buffer_size, fp) != pcm_buffer_size){// Loopfseek(fp, 0, SEEK_SET);fread(pcm_buffer, 1, pcm_buffer_size, fp);data_count = 0;}printf("Now playing %10d bytes data.\n", data_count);data_count += pcm_buffer_size;// Set audio buffer (PCM data)audio_chunk = (Uint8 *)pcm_buffer;// Audio buffer lengthaudio_len = pcm_buffer_size;audio_pos = audio_chunk;// Wait until finishwhile (audio_len > 0){// 使用 SDL_Delay 进行 1ms 的延迟,用当前缓存区剩余未播放的长度大于 0 结合前面的延迟进行等待SDL_Delay(1);}}// Step 5: 关闭音频设备SDL_CloseAudio();fclose(fp);free(pcm_buffer);// Step 6: 退出 SDL 系统SDL_Quit();system("pause");return 0;
}

本程序可以直接在 Visual Studio 2015 上运行。

程序运行后,可以听到音频,循环播放。

程序输出:

在这里插入图片描述

工程文件下载

GitHub:UestcXiye / Simplest-Audio-Player-SDL2

CSDN:Simplest-Audio-Player-SDL2.zip

这篇关于最简单的基于 SDL2 的音频播放器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/556819

相关文章

一份LLM资源清单围观技术大佬的日常;手把手教你在美国搭建「百万卡」AI数据中心;为啥大模型做不好简单的数学计算? | ShowMeAI日报

👀日报&周刊合集 | 🎡ShowMeAI官网 | 🧡 点赞关注评论拜托啦! 1. 为啥大模型做不好简单的数学计算?从大模型高考数学成绩不及格说起 司南评测体系 OpenCompass 选取 7 个大模型 (6 个开源模型+ GPT-4o),组织参与了 2024 年高考「新课标I卷」的语文、数学、英语考试,然后由经验丰富的判卷老师评判得分。 结果如上图所

回调的简单理解

之前一直不太明白回调的用法,现在简单的理解下 就按这张slidingmenu来说,主界面为Activity界面,而旁边的菜单为fragment界面。1.现在通过主界面的slidingmenu按钮来点开旁边的菜单功能并且选中”区县“选项(到这里就可以理解为A类调用B类里面的c方法)。2.通过触发“区县”的选项使得主界面跳转到“区县”相关的新闻列表界面中(到这里就可以理解为B类调用A类中的d方法

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用。如果你看不懂,请留言。 完整代码: <!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><ti

探索蓝牙协议的奥秘:用ESP32实现高质量蓝牙音频传输

蓝牙(Bluetooth)是一种短距离无线通信技术,广泛应用于各种电子设备之间的数据传输。自1994年由爱立信公司首次提出以来,蓝牙技术已经经历了多个版本的更新和改进。本文将详细介绍蓝牙协议,并通过一个具体的项目——使用ESP32实现蓝牙音频传输,来展示蓝牙协议的实际应用及其优点。 蓝牙协议概述 蓝牙协议栈 蓝牙协议栈是蓝牙技术的核心,定义了蓝牙设备之间如何进行通信。蓝牙协议

python实现最简单循环神经网络(RNNs)

Recurrent Neural Networks(RNNs) 的模型: 上图中红色部分是输入向量。文本、单词、数据都是输入,在网络里都以向量的形式进行表示。 绿色部分是隐藏向量。是加工处理过程。 蓝色部分是输出向量。 python代码表示如下: rnn = RNN()y = rnn.step(x) # x为输入向量,y为输出向量 RNNs神经网络由神经元组成, python

宝塔面板部署青龙面板教程【简单易上手】

首先,你得有一台部署了宝塔面板的服务器(自己用本地电脑也可以)。 宝塔面板部署自行百度一下,很简单,这里就不走流程了,官网版本就可以,无需开心版。 首先,打开宝塔面板的软件商店,找到下图这个软件(Docker管理器)安装,青龙面板还是安装在docker里,这里依赖宝塔面板安装和管理docker。 安装完成后,进入SSH终端管理,输入代码安装青龙面板。ssh可以直接宝塔里操作,也可以安装ssh连接

XMG Quartz2D的简单使用

// //  Quratz2DView.m //  Quartz2D // //  Created by 王宁 on 16/5/6. //  Copyright © 2016年 ylshmacmini. All rights reserved. // #import "Quratz2DView.h" //Quartz@2D是一个二维绘图引擎,同时支

网页脚本输入这么简单

如何在网页中进行脚本操作呢? 研究了一下,很简单,用google浏览器的Console直接操作javaScript。思路: Created with Raphaël 2.1.0 开始 输入(如何输入) 点击(如何点击) 结束 下面是,通过脚本刷直播屏的实现,直接在Console输入即可 var words=new Arra

Linux网络编程之简单并发服务器

1.概念 与前面介绍的循环服务器不同,并发服务器对服务请求并发处理。而循环服务器只能够一个一个的处理客户端的请求,显然效率很低. 并发服务器通过建立多个子进程来实现对请求的并发处理,但是由于不清楚请求客户端的数目,因此很难确定子进程的数目。因此可以动态增加子进程与事先分配的子进程相结合的方法来实现并发服务器。 2. 算法流程 (1)TCP简单并发服务器:     服务器子进程1:

简单 使用 的makefile编写 框架

1、指定编译器,如海思平台:CROSS_COMPILE=arm-hisiv100nptl-linux-; 2、指定编译工具:GCC=$(CROSS_COMPILE)gcc   CC=$(CROSS_COMPILE)g++; 3、使用 export 导出 子makefile 要用的变量; 4、定义变量的形式  指定 工程源文件 需要使用到的 “宏”,在后面的 LDFLAGS 里面使用 -D将其