最简单的基于 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.0
	SDL_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)
		{
			// Loop
			fseek(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 length
		audio_len = pcm_buffer_size;
		audio_pos = audio_chunk;
		// Wait until finish
		while (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

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要下载一个基于FFmpeg SDL的最简单的视频播放器,可以按照以下步骤进行: 1. 首先,需要下载和安装FFmpeg软件包。FFmpeg是一个开源的跨平台多媒体框架,可以用于处理音频和视频文件。可以上FFmpeg官网(https://www.ffmpeg.org/)找到相应的下载链接,并根据操作系统选择正确的版本进行下载和安装。 2. 下载SDL库。SDL是一个跨平台的开发库,可以用于创建多媒体应用程序。可以在SDL官网(https://www.libsdl.org/)上找到相应的下载链接,并选择适合自己操作系统的版本进行下载和安装。 3. 使用编程语言(如C/C++)编写一个基于FFmpegSDL的视频播放器。可以使用任何喜欢的集成开发环境(IDE),如Visual Studio、Dev-C++等。根据自己的需求,可以封装FFmpegSDL的相关函数,以方便播放视频文件。 4. 在编程中,需要包含FFmpegSDL所需的头文件,并链接FFmpegSDL的库文件。可以在编译选项中添加"-lffmpeg"和"-lsdl"等参数。 5. 编写代码来打开视频文件,读取视频流,将每一帧解码和渲染到屏幕上并进行播放。可以使用FFmpeg提供的函数来进行解码和渲染,使用SDL提供的函数来显示图像并进行窗口管理。 6. 编译和运行程序,即可实现最简单的基于FFmpeg SDL的视频播放器。可以通过命令行输入视频文件的路径进行播放。 需要注意的是,基于FFmpeg SDL的视频播放器可以根据个人需求来进行功能的扩展,如添加播放控制(播放、暂停、停止等)、全屏显示、音量调节等功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值