23 #if SDL_AUDIO_DRIVER_DSOUND
30 #include "../SDL_audio_c.h"
33 #ifndef WAVE_FORMAT_IEEE_FLOAT
34 #define WAVE_FORMAT_IEEE_FLOAT 0x0003
38 static void* DSoundDLL =
NULL;
39 typedef HRESULT(WINAPI*fnDirectSoundCreate8)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
40 typedef HRESULT(WINAPI*fnDirectSoundEnumerateW)(LPDSENUMCALLBACKW,
LPVOID);
41 typedef HRESULT(WINAPI*fnDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW,
LPVOID);
42 static fnDirectSoundCreate8 pDirectSoundCreate8 =
NULL;
43 static fnDirectSoundEnumerateW pDirectSoundEnumerateW =
NULL;
44 static fnDirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW =
NULL;
49 pDirectSoundCreate8 =
NULL;
50 pDirectSoundEnumerateW =
NULL;
51 pDirectSoundCaptureEnumerateW =
NULL;
53 if (DSoundDLL !=
NULL) {
68 if (DSoundDLL ==
NULL) {
72 #define DSOUNDLOAD(f) { \
73 p##f = (fn##f) SDL_LoadFunction(DSoundDLL, #f); \
74 if (!p##f) loaded = 0; \
77 DSOUNDLOAD(DirectSoundCreate8);
78 DSOUNDLOAD(DirectSoundEnumerateW);
79 DSOUNDLOAD(DirectSoundCaptureEnumerateW);
83 SDL_SetError(
"DirectSound: System doesn't appear to have DX8.");
95 SetDSerror(
const char *
function,
int code)
97 static const char *
error;
98 static char errbuf[1024];
103 error =
"Unsupported interface -- Is DirectX 8.0 or later installed?";
105 case DSERR_ALLOCATED:
106 error =
"Audio device in use";
108 case DSERR_BADFORMAT:
109 error =
"Unsupported audio format";
111 case DSERR_BUFFERLOST:
112 error =
"Mixing buffer was lost";
114 case DSERR_CONTROLUNAVAIL:
115 error =
"Control requested is not available";
117 case DSERR_INVALIDCALL:
118 error =
"Invalid call for the current state";
120 case DSERR_INVALIDPARAM:
121 error =
"Invalid parameter";
124 error =
"No audio device found";
126 case DSERR_OUTOFMEMORY:
127 error =
"Out of memory";
129 case DSERR_PRIOLEVELNEEDED:
130 error =
"Caller doesn't have priority";
132 case DSERR_UNSUPPORTED:
133 error =
"Function not supported";
137 "%s: Unknown DirectSound error: 0x%x",
function, code);
149 FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module,
LPVOID data)
166 pDirectSoundCaptureEnumerateW(FindAllDevs, addfn);
168 pDirectSoundEnumerateW(FindAllDevs, addfn);
174 DSOUND_WaitDevice(
_THIS)
184 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
186 if (result != DS_OK) {
187 if (result == DSERR_BUFFERLOST) {
188 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
191 SetDSerror(
"DirectSound GetCurrentPosition", result);
196 while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) {
201 IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
202 if ((status & DSBSTATUS_BUFFERLOST)) {
203 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
204 IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
205 if ((status & DSBSTATUS_BUFFERLOST)) {
209 if (!(status & DSBSTATUS_PLAYING)) {
210 result = IDirectSoundBuffer_Play(this->hidden->mixbuf, 0, 0,
212 if (result == DS_OK) {
216 SetDSerror(
"DirectSound Play", result);
222 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
224 if (result != DS_OK) {
225 SetDSerror(
"DirectSound GetCurrentPosition", result);
232 DSOUND_PlayDevice(
_THIS)
235 if (this->hidden->locked_buf) {
236 IDirectSoundBuffer_Unlock(this->hidden->mixbuf,
237 this->hidden->locked_buf,
238 this->hidden->mixlen,
NULL, 0);
244 DSOUND_GetDeviceBuf(
_THIS)
252 this->hidden->locked_buf =
NULL;
253 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
255 if (result == DSERR_BUFFERLOST) {
256 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
257 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
260 if (result != DS_OK) {
261 SetDSerror(
"DirectSound GetCurrentPosition", result);
264 cursor /= this->hidden->mixlen;
269 if (spot < this->hidden->lastchunk) {
270 spot += this->hidden->num_buffers;
272 if (spot > this->hidden->lastchunk + 1) {
273 fprintf(stderr,
"Audio dropout, missed %d fragments\n",
274 (spot - (this->hidden->lastchunk + 1)));
278 this->hidden->lastchunk = cursor;
279 cursor = (cursor + 1) % this->hidden->num_buffers;
280 cursor *= this->hidden->mixlen;
283 result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
284 this->hidden->mixlen,
285 (
LPVOID *) & this->hidden->locked_buf,
286 &rawlen,
NULL, &junk, 0);
287 if (result == DSERR_BUFFERLOST) {
288 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
289 result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
290 this->hidden->mixlen,
292 hidden->locked_buf, &rawlen, NULL,
295 if (result != DS_OK) {
296 SetDSerror(
"DirectSound Lock", result);
299 return (this->hidden->locked_buf);
303 DSOUND_WaitDone(
_THIS)
308 if (stream != NULL) {
309 SDL_memset(stream, this->spec.silence, this->hidden->mixlen);
310 DSOUND_PlayDevice(
this);
312 DSOUND_WaitDevice(
this);
315 IDirectSoundBuffer_Stop(this->hidden->mixbuf);
319 DSOUND_CloseDevice(
_THIS)
321 if (this->hidden != NULL) {
322 if (this->hidden->sound != NULL) {
323 if (this->hidden->mixbuf != NULL) {
325 IDirectSoundBuffer_Release(this->hidden->mixbuf);
326 this->hidden->mixbuf =
NULL;
328 IDirectSound_Release(this->hidden->sound);
329 this->hidden->sound =
NULL;
341 CreateSecondary(
_THIS, HWND focus)
343 LPDIRECTSOUND sndObj = this->hidden->sound;
344 LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
346 const int numchunks = 8;
349 LPVOID pvAudioPtr1, pvAudioPtr2;
350 DWORD dwAudioBytes1, dwAudioBytes2;
372 result = IDirectSound_SetCooperativeLevel(sndObj,
373 focus, DSSCL_PRIORITY);
375 result = IDirectSound_SetCooperativeLevel(sndObj,
379 if (result != DS_OK) {
380 return SetDSerror(
"DirectSound SetCooperativeLevel", result);
385 format.dwSize =
sizeof(
format);
386 format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
388 format.dwFlags |= DSBCAPS_GLOBALFOCUS;
390 format.dwFlags |= DSBCAPS_STICKYFOCUS;
392 format.dwBufferBytes = numchunks *
chunksize;
393 if ((format.dwBufferBytes < DSBSIZE_MIN) ||
394 (format.dwBufferBytes > DSBSIZE_MAX)) {
395 return SDL_SetError(
"Sound buffer size must be between %d and %d",
396 DSBSIZE_MIN / numchunks, DSBSIZE_MAX / numchunks);
398 format.dwReserved = 0;
399 format.lpwfxFormat = &wfmt;
400 result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
401 if (result != DS_OK) {
402 return SetDSerror(
"DirectSound CreateSoundBuffer", result);
404 IDirectSoundBuffer_SetFormat(*sndbuf, &wfmt);
407 result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
408 (
LPVOID *) & pvAudioPtr1, &dwAudioBytes1,
409 (
LPVOID *) & pvAudioPtr2, &dwAudioBytes2,
410 DSBLOCK_ENTIREBUFFER);
411 if (result == DS_OK) {
412 SDL_memset(pvAudioPtr1, this->spec.silence, dwAudioBytes1);
413 IDirectSoundBuffer_Unlock(*sndbuf,
414 (
LPVOID) pvAudioPtr1, dwAudioBytes1,
415 (
LPVOID) pvAudioPtr2, dwAudioBytes2);
422 typedef struct FindDevGUIDData
430 FindDevGUID(LPGUID guid, LPCWSTR desc, LPCWSTR module,
LPVOID _data)
433 FindDevGUIDData *data = (FindDevGUIDData *) _data;
435 const int match = (
SDL_strcmp(str, data->devname) == 0);
447 DSOUND_OpenDevice(
_THIS,
const char *devname,
int iscapture)
453 FindDevGUIDData devguid;
456 if (devname != NULL) {
458 devguid.devname = devname;
460 pDirectSoundCaptureEnumerateW(FindDevGUID, &devguid);
462 pDirectSoundEnumerateW(FindDevGUID, &devguid);
464 if (!devguid.found) {
465 return SDL_SetError(
"DirectSound: Requested device not found");
467 guid = &devguid.guid;
473 if (this->hidden == NULL) {
476 SDL_memset(this->hidden, 0, (
sizeof *this->hidden));
479 result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
480 if (result != DS_OK) {
481 DSOUND_CloseDevice(
this);
482 return SetDSerror(
"DirectSoundCreate", result);
485 while ((!valid_format) && (test_format)) {
486 switch (test_format) {
492 this->spec.format = test_format;
493 this->hidden->num_buffers = CreateSecondary(
this, NULL);
494 if (this->hidden->num_buffers > 0) {
503 DSOUND_CloseDevice(
this);
507 return SDL_SetError(
"DirectSound: Unsupported audio format");
511 this->hidden->mixlen = this->spec.size;
518 DSOUND_Deinitialize(
void)
527 if (!DSOUND_Load()) {
545 "directsound",
"DirectSound", DSOUND_Init, 0
void(* CloseDevice)(_THIS)
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
void(* SDL_AddAudioDevice)(const char *name)
void(* WaitDevice)(_THIS)
DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt,...)
typedef HRESULT(WINAPI *LPD3DXIMTSIGNALCALLBACK)(CONST D3DXVECTOR2 *uv
Uint8 *(* GetDeviceBuf)(_THIS)
DECLSPEC void SDLCALL SDL_free(void *mem)
Uint16 SDL_AudioFormat
Audio format flags.
AudioBootStrap DSOUND_bootstrap
int(* OpenDevice)(_THIS, const char *devname, int iscapture)
SDL_AudioFormat SDL_NextAudioFormat(void)
uint32_t Uint32
An unsigned 32-bit integer type.
#define SDL_AUDIO_ISFLOAT(x)
void(* PlayDevice)(_THIS)
void(* DetectDevices)(int iscapture, SDL_AddAudioDevice addfn)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
DECLSPEC void *SDLCALL SDL_LoadObject(const char *sofile)
#define SDL_AUDIO_BITSIZE(x)
DECLSPEC void SDLCALL SDL_Delay(Uint32 ms)
Wait a specified number of milliseconds before returning.
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
DECLSPEC void SDLCALL SDL_UnloadObject(void *handle)
#define WIN_StringToUTF8(S)
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
void(* Deinitialize)(void)
typedef LPVOID(WINAPI *PFNWGLCREATEIMAGEBUFFERI3DPROC)(HDC hDC
#define SDL_OutOfMemory()
#define SDL_arraysize(array)
#define WAVE_FORMAT_IEEE_FLOAT
DECLSPEC void *SDLCALL SDL_memcpy(void *dst, const void *src, size_t len)
uint8_t Uint8
An unsigned 8-bit integer type.
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex
typedef BOOL(WINAPI *PFNWGLSETSTEREOEMITTERSTATE3DLPROC)(HDC hDC