#include "SDL.h" struct { Uint8 *sound; // pointer to wave data Uint32 soundlen; // length of wave data int soundpos; // current play position }wave; int done; static void quit(int rc) { SDL_Quit(); exit(rc); } void SDLCALL fill_audio(void *unused, Uint8 *stream, int len) { Uint8 *waveptr; int waveleft; int copylen; SDL_memset(stream, 0, len); if (wave.soundpos == wave.soundlen) { done = 1; return; } waveptr = wave.sound + wave.soundpos; waveleft = wave.soundlen - wave.soundpos; waveleft <= len ? (copylen = waveleft) : (copylen = len); SDL_memcpy(stream, waveptr, copylen); wave.soundpos += copylen; SDL_Log("len: %d, copylen:%d\n", len, copylen); } /* SDL播放音频wave文件测试 */ int audio_test() { SDL_AudioSpec spec; const char * audio_file = "sample.wav"; done = 0; // 1. init SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); if (SDL_Init(SDL_INIT_AUDIO) < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL:%s\n", SDL_GetError()); return (1); } // 2. open audio wave file if (SDL_LoadWAV(audio_file, &spec, &wave.sound, &wave.soundlen) == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", audio_file, SDL_GetError()); quit(1); } spec.callback = fill_audio; // 3. open audio if (SDL_OpenAudio(&spec, NULL) < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open audio: %s\n", SDL_GetError()); SDL_FreeWAV(wave.sound); quit(2); } SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver()); // 4. play SDL_PauseAudio(0); /* 5. fill audio data, it's be done by fill_audio */ // 6. waiting for play end while (0 == done) { SDL_Delay(1); } // 7. close SDL_CloseAudio(); SDL_FreeWAV(wave.sound); SDL_Quit(); return 0; }
以上代码参考自SDL的test文件夹下的loopwave.c函数。
由上,用SDL播放音频wave文件包含如下流程:
1、 调用SDL_Init(SDL_INIT_AUDIO)初始化音频子系统;
2、 调用SDL_LoadWAW()打开音频wave文件,获取对应的spec、波形数据及波形数据长度等信息;
3、 调用SDL_OpenAudio()打开音频设备(在这之前还需要设置spec的callback成员),这函数实际上是启动了SDL_RunAudio线程,用于实际的音频播放;
4、 调用SDL_PauseAudio(0)播放音频;
5、 调用spec.callback()函数,填充音频数据(这一步由SDL_RunAudio线程完成);
6、 待播放完成后,关闭音频音频设备(SDL_CloseAudio()),释放波形数据buffer(SDL_FreeWAV()),然后退出。