SDL2.0超简单入门 100行代码实现播放wav声音文件

时间:2021-05-05 12:12:03

sdl主要用图形界面显示及播放声音,本人刚刚接触sdl,写了个简单的入门程序,实现播放声音文件,现分享一下当做个笔记。

// sound2.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
extern "C"
{
	//SDL
	#include "sdl/SDL.h"
	#include "sdl/SDL_thread.h"

	#pragma comment(lib, "lib\\SDL2main.lib")
	#pragma comment(lib, "lib\\SDL2.lib")
};
#include <iostream>
using namespace std;

#define SOUND_DATA_LEN 409600//samples*channel*2byte=4096的倍数

//音频数据结构
typedef struct SoundData
{
	Uint8   buffer[SOUND_DATA_LEN];//数据缓存
	Uint8   *position;//缓存当前播放指针
	Uint32  length;//待播放的缓存长度
}SoundData;



//SDL 2.0
//播放回调
void fill_audio(void *udata, Uint8 *stream, int len)
{ 
	SoundData* sd = (SoundData*)udata;
	SDL_memset(stream, 0, len);
	
	//缓存数据已播放完毕
	if(sd->length <= 0)
	{
		return;
	}
	
	//缓存中能播放最大的长度
	len = len > sd->length ?sd->length : len;

	//将数据混合至声卡设备
	SDL_MixAudio(stream, sd->position, len, SDL_MIX_MAXVOLUME);
	sd->position += len;//当前播放位置更新
	sd->length -= len;//缓存剩余长度更新
}

int _tmain(int argc, _TCHAR* argv[])
{
	char *file_name = "Sweety - 樱花草.wav";//只支持.wav文件
	
	//声音缓存结构
	SoundData sd;
	
	//步骤(1)设置音频信息
	//SDL 2.0 Support for multiple windows
	SDL_AudioSpec wanted_spec;
	wanted_spec.freq = 44100;//44.1KHz采样率
	wanted_spec.format = AUDIO_S16SYS;//采样数据格式
	wanted_spec.channels = 2;//2声道
	wanted_spec.silence = 0;//静音时大小
	wanted_spec.samples = 1024;//每次播放长度1024*2channels*2byte
	wanted_spec.callback = fill_audio;//设置播放回调函数
	wanted_spec.userdata = &sd;//传递数据给回调函数

	

	//步骤(2)打开音频设备
	if (SDL_OpenAudio(&wanted_spec, NULL)<0)
	{ 
		printf("can't open audio.\n"); 
		goto end; 
	}


	FILE* file = fopen(file_name, "rb");
	if(!file)
	{
		cout<<"无法打开声音文件:"<<file_name<<endl;
		goto end;
	}

	int count = 0;//文件帧数
	int len = 0;//能读文件数据长度

	//步骤(3)开始播放
	SDL_PauseAudio(0);
	//循环读文件数据至缓存
	while(len = fread(sd.buffer, 1, SOUND_DATA_LEN, file))
	{
		sd.length = len;//Audio buffer length
		sd.position = sd.buffer;
		//存存数据未播放完等待
		while(sd.length>0)
		{
			SDL_Delay(1);
		}
		printf("文件帧:%03d\n", count++);
	}
	
end:
	fclose(file);
	
	//步骤(4)退出
	SDL_Quit();

	system("pause");
	return 0;
}