ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SDL相关函数的使用及注意事项(正确关闭SDL音频设备)

2020-12-01 10:01:12  阅读:223  来源: 互联网

标签:函数 int len 音频设备 INIT 注意事项 SDL audio


本文主要的目的在于讲解SDL2库常用的函数库以及讲述在项目中遇到的使用SDL,将记录SDL的初始化以及如何使用SDL开启渲染音频和关闭。


一、SDL播放音频使用步骤及函数说明

(1)SDL初始化:

int SDLCALL SDL_Init(Uint32 flags)

说明:该函数是用于激活需要激活的子系统的初始化函数,其中该SDL的子系统有很多例如音频和视频等子系统,传入的参数具有如下,常用的有 SDL_INIT_AUDIO和SDL_INIT_VIDEO :

#define SDL_INIT_TIMER          0x00000001
#define SDL_INIT_AUDIO          0x00000010
#define SDL_INIT_VIDEO          0x00000020 
#define SDL_INIT_JOYSTICK       0x00000200 
#define SDL_INIT_HAPTIC         0x00001000
#define SDL_INIT_GAMECONTROLLER 0x00002000 
#define SDL_INIT_EVENTS         0x00004000
#define SDL_INIT_NOPARACHUTE    0x00100000 
#define SDL_INIT_EVERYTHING ( \
                SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
                SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER \
            )

(2)打开设备函数:

int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired,SDL_AudioSpec * obtained);

说明:这个函数是用于打开设备使用的,以及通过SDL_AudioSpec * desired传入所需要的参数,如下为该结构体的定义,包括了音频的格式(SDL_AudioFormat format)、音频的通道数(Uint8 channels)以及比较重要的回调函数指针(SDL_AudioCallback callback)等:

typedef struct SDL_AudioSpec
{
    int freq;                   /**< DSP frequency -- samples per second */
    SDL_AudioFormat format;     /**< Audio data format */
    Uint8 channels;             /**< Number of channels: 1 mono, 2 stereo */
    Uint8 silence;              /**< Audio buffer silence value (calculated) */
    Uint16 samples;             /**< Audio buffer size in samples (power of 2) */
    Uint16 padding;             /**< Necessary for some compile environments */
    Uint32 size;                /**< Audio buffer size in bytes (calculated) */
    SDL_AudioCallback callback;
    void *userdata;
} SDL_AudioSpec;

(3)启停音频设备函数:

void SDLCALL SDL_PauseAudio(int pause_on);

说明:在使用 SDL_OpenAudio()函数后,应该需要使用SDL_PauseAudio(0)函数且传入参数0来使SDL调用回调函数来播放音频;若传入的是大于0的值此时将暂停音频播放设备,期间将传入静音数据。

(4)对音频数据进行混音函数

void SDLCALL SDL_MixAudio(Uint8 * dst, const Uint8 * src,Uint32 len, int volume);

说明:这是一个混音函数,可以将两段音频进行混音播放。

三、关闭函数特别说明:

因为当使用了SDL_OpenAudio()函数后,回调函数就会以线程的方式启动的,同时如果当需要关闭SDL音频设备时 ,仅仅使用SDL_CloseAudio()时不够的,下次如果再次使用SDL_OpenAudio()会报错,此时还需要进行一个操作就是需要停止掉回调线程,本文使用了一个参数int is_stop_sdl_audio_player = false;来控制线程的启停。

如下为回调函数对该参数的判断,和退出情况,当is_stop_sdl_audio_player为true时结束线程,完成关闭SDL全部操作。

…..
if (is_stop_sdl_audio_player == true)
{
	//is_stop_sdl_audio_player = false;//清零
	xhlog("exit fillaudio\n");
	return ;
}

…..

四、代码展示

(1)SDL初始化函数

extern int audio_sample_rate;//rtmp中获取得到的音频采样频率,默认是44.1khz
int SDL_INIT_PLAYER(void)
{
	//Init
	int ret = 0;
	if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER| SDL_INIT_VIDEO )) 
	{
		//printf("Could not initialize SDL - %s\n", SDL_GetError());
		xhlog("Could not initialize SDL - %s\n", SDL_GetError());
		return -1;
	}
	//SDL_AudioSpec
	SDL_AudioSpec wanted_spec;
	//wanted_spec.freq = 44100;
	wanted_spec.freq = audio_sample_rate;
	wanted_spec.format = AUDIO_S16SYS;
	wanted_spec.channels = 2;
	wanted_spec.silence = 0;
	wanted_spec.samples = 1024;//1024;
	wanted_spec.callback = fill_audio;
	if (SDL_OpenAudio(&wanted_spec, NULL)<0) {

		//printf("can't open audio.\n");
		xhlog("can't open audio.\n");
		return -1;
	}
	SDL_PauseAudio(0);
	is_stop_sdl_audio_player = false;
	return 0;
}

(2)填充数据播放

/*函数名称:SDL_START_PLAYER
*函数功能:使用SDL播放PCM,使用线程来播放
*传入参数:unsigned char *data_pcm:pcm的数据指针;
*			int len_data_pcm:pcm数据的长度
*函数返回值:成功返回0,失败返回-1;
*函数作者:吴豪乐
*日期:2020年7月29日
*/
#if 0
int SDL_START_PLAYER(unsigned char *data_pcm, int len_data_pcm)
#endif
DWORD WINAPI SDL_START_PLAYER(LPVOID lpParam)
{
	audio_chunk = (Uint8 *)lpParam;
	if (audio_chunk == NULL)
	{
		xhlog("audio audio_chunk is NULL\n");
		return -1;
	}
	//SDL_LockAudio();

	audio_pos = audio_chunk;
	int pcm_buffer_size = 4096;
	
	//Audio buffer length
	audio_len = pcm_buffer_size;
	while (audio_len > 0)//Wait until finish
	{
		SDL_Delay(1);
	}
	return 0;
}

(3)循环读取数据线程函数

/* Audio Callback
 * 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 
 * 
*/ 
int is_stop_sdl_audio_player = false;
void  fill_audio(void *udata,Uint8 *stream,int len){ 

	int count_played = 0;//已经播放了数据大小
	if (is_stop_sdl_audio_player == true)
	{
		//is_stop_sdl_audio_player = false;//清零
		xhlog("exit fillaudio\n");
		return ;
	}
	if (len == 4096 && audio_len == 0)
	{

		//xhlog("temp:%d\n", temp);
		//if(temp == 4096)
			//audio_len = len;
		SDL_memset(stream, 0, temp);
		//return;//这一句测试一下是否导致噪点,检测后发现这个return注释掉会噪点少很多
	}
	pcm_ptr_save = pcm_ptr;
	pcm_ptr = audio_pos;

	while (len > 0 && audio_len > 0)
	{
		SDL_memset(stream, 0, audio_len);
		if (audio_len == 0)
		{
			continue;
		}
		temp = (len > audio_len ? audio_len : len);

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

(4)停止播放函数

/*函数名称:SDL_STOP_PLAYER
*函数功能:停止SDL播放PCM,关闭线程来播放
*传入参数:无
*函数返回值:成功返回0,失败返回-1;
*函数作者:吴豪乐
*日期:2020年11月27日
*/
void SDL_STOP_PLAYER(void)
{
	printf("stop audioplayer\n");
	is_stop_sdl_audio_player = true;
	SDL_CloseAudio();
}

每写一篇文章都不容易,尊重别人的知识产权才是对自己和技术的尊重。为了避免发生知识产权被侵权的情况,我决定做出以下声明:

1.博客中标注原创的文章,版权归原作者 吴豪乐工作室 所有;

2.未经原作者允许不得转载本文内容,否则将视为侵权;

3.转载或者引用本文内容请注明来源及原作者;

4.对于不遵守此声明或者其他违法使用本文内容者,本人依法保留追究权等。

标签:函数,int,len,音频设备,INIT,注意事项,SDL,audio
来源: https://blog.csdn.net/weixin_41353840/article/details/110421951

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有