21 #include "../../SDL_internal.h" 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);
148 DSOUND_FreeDeviceHandle(
void *handle)
154 FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID
data)
156 const int iscapture = (int) ((
size_t)
data);
160 LPGUID cpyguid = (LPGUID)
SDL_malloc(
sizeof (GUID));
170 DSOUND_DetectDevices(
void)
172 pDirectSoundCaptureEnumerateW(FindAllDevs, (
void *) ((
size_t) 1));
173 pDirectSoundEnumerateW(FindAllDevs, (
void *) ((
size_t) 0));
178 DSOUND_WaitDevice(
_THIS)
188 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
190 if (result != DS_OK) {
191 if (result == DSERR_BUFFERLOST) {
192 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
195 SetDSerror(
"DirectSound GetCurrentPosition", result);
200 while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) {
205 IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
206 if ((status & DSBSTATUS_BUFFERLOST)) {
207 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
208 IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
209 if ((status & DSBSTATUS_BUFFERLOST)) {
213 if (!(status & DSBSTATUS_PLAYING)) {
214 result = IDirectSoundBuffer_Play(this->hidden->mixbuf, 0, 0,
216 if (result == DS_OK) {
220 SetDSerror(
"DirectSound Play", result);
226 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
228 if (result != DS_OK) {
229 SetDSerror(
"DirectSound GetCurrentPosition", result);
236 DSOUND_PlayDevice(
_THIS)
239 if (this->hidden->locked_buf) {
240 IDirectSoundBuffer_Unlock(this->hidden->mixbuf,
241 this->hidden->locked_buf,
242 this->hidden->mixlen,
NULL, 0);
248 DSOUND_GetDeviceBuf(
_THIS)
252 HRESULT result = DS_OK;
256 this->hidden->locked_buf =
NULL;
257 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
259 if (result == DSERR_BUFFERLOST) {
260 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
261 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
264 if (result != DS_OK) {
265 SetDSerror(
"DirectSound GetCurrentPosition", result);
268 cursor /= this->hidden->mixlen;
273 if (spot < this->hidden->lastchunk) {
274 spot += this->hidden->num_buffers;
276 if (spot > this->hidden->lastchunk + 1) {
277 fprintf(stderr,
"Audio dropout, missed %d fragments\n",
278 (spot - (this->hidden->lastchunk + 1)));
282 this->hidden->lastchunk =
cursor;
283 cursor = (cursor + 1) % this->hidden->num_buffers;
284 cursor *= this->hidden->mixlen;
287 result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
288 this->hidden->mixlen,
289 (LPVOID *) & this->hidden->locked_buf,
290 &rawlen,
NULL, &junk, 0);
291 if (result == DSERR_BUFFERLOST) {
292 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
293 result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
294 this->hidden->mixlen,
296 hidden->locked_buf, &rawlen, NULL,
299 if (result != DS_OK) {
300 SetDSerror(
"DirectSound Lock", result);
303 return (this->hidden->locked_buf);
307 DSOUND_WaitDone(
_THIS)
312 if (stream != NULL) {
314 DSOUND_PlayDevice(
this);
316 DSOUND_WaitDevice(
this);
319 IDirectSoundBuffer_Stop(this->hidden->mixbuf);
323 DSOUND_CloseDevice(
_THIS)
325 if (this->hidden != NULL) {
326 if (this->hidden->sound != NULL) {
327 if (this->hidden->mixbuf != NULL) {
329 IDirectSoundBuffer_Release(this->hidden->mixbuf);
330 this->hidden->mixbuf =
NULL;
332 IDirectSound_Release(this->hidden->sound);
333 this->hidden->sound =
NULL;
345 CreateSecondary(
_THIS, HWND focus)
347 LPDIRECTSOUND sndObj = this->hidden->sound;
348 LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
350 const int numchunks = 8;
351 HRESULT result = DS_OK;
353 LPVOID pvAudioPtr1, pvAudioPtr2;
354 DWORD dwAudioBytes1, dwAudioBytes2;
360 wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
362 wfmt.wFormatTag = WAVE_FORMAT_PCM;
367 wfmt.nSamplesPerSec = this->
spec.
freq;
368 wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
369 wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
376 result = IDirectSound_SetCooperativeLevel(sndObj,
377 focus, DSSCL_PRIORITY);
379 result = IDirectSound_SetCooperativeLevel(sndObj,
383 if (result != DS_OK) {
384 return SetDSerror(
"DirectSound SetCooperativeLevel", result);
389 format.dwSize =
sizeof(
format);
390 format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
392 format.dwFlags |= DSBCAPS_GLOBALFOCUS;
394 format.dwFlags |= DSBCAPS_STICKYFOCUS;
396 format.dwBufferBytes = numchunks *
chunksize;
397 if ((format.dwBufferBytes < DSBSIZE_MIN) ||
398 (format.dwBufferBytes > DSBSIZE_MAX)) {
399 return SDL_SetError(
"Sound buffer size must be between %d and %d",
400 DSBSIZE_MIN / numchunks, DSBSIZE_MAX / numchunks);
402 format.dwReserved = 0;
403 format.lpwfxFormat = &wfmt;
404 result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
405 if (result != DS_OK) {
406 return SetDSerror(
"DirectSound CreateSoundBuffer", result);
408 IDirectSoundBuffer_SetFormat(*sndbuf, &wfmt);
411 result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
412 (LPVOID *) & pvAudioPtr1, &dwAudioBytes1,
413 (LPVOID *) & pvAudioPtr2, &dwAudioBytes2,
414 DSBLOCK_ENTIREBUFFER);
415 if (result == DS_OK) {
417 IDirectSoundBuffer_Unlock(*sndbuf,
418 (LPVOID) pvAudioPtr1, dwAudioBytes1,
419 (LPVOID) pvAudioPtr2, dwAudioBytes2);
427 DSOUND_OpenDevice(
_THIS,
void *handle,
const char *devname,
int iscapture)
433 LPGUID guid = (LPGUID) handle;
438 if (this->hidden == NULL) {
441 SDL_memset(this->hidden, 0, (
sizeof *this->hidden));
444 result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
445 if (result != DS_OK) {
446 DSOUND_CloseDevice(
this);
447 return SetDSerror(
"DirectSoundCreate", result);
450 while ((!valid_format) && (test_format)) {
451 switch (test_format) {
458 this->hidden->num_buffers = CreateSecondary(
this, NULL);
459 if (this->hidden->num_buffers > 0) {
468 DSOUND_CloseDevice(
this);
472 return SDL_SetError(
"DirectSound: Unsupported audio format");
476 this->hidden->mixlen = this->
spec.
size;
483 DSOUND_Deinitialize(
void)
492 if (!DSOUND_Load()) {
512 "directsound",
"DirectSound", DSOUND_Init, 0
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
void(* DetectDevices)(void)
uint32_t Uint32
An unsigned 32-bit integer type.
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
void(* PlayDevice)(_THIS)
void(* WaitDevice)(_THIS)
Uint16 SDL_AudioFormat
Audio format flags.
AudioBootStrap DSOUND_bootstrap
SDL_AudioFormat SDL_NextAudioFormat(void)
#define SDL_AUDIO_ISFLOAT(x)
uint8_t Uint8
An unsigned 8-bit integer type.
#define SDL_AUDIO_BITSIZE(x)
void(* Deinitialize)(void)
#define WIN_StringToUTF8(S)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
#define SDL_OutOfMemory()
void(* CloseDevice)(_THIS)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
void(* FreeDeviceHandle)(void *handle)
Uint8 *(* GetDeviceBuf)(_THIS)
#define SDL_arraysize(array)
void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)