21 #include "../../SDL_internal.h" 23 #if SDL_AUDIO_DRIVER_DSOUND 31 #include "../SDL_audio_c.h" 34 #ifndef WAVE_FORMAT_IEEE_FLOAT 35 #define WAVE_FORMAT_IEEE_FLOAT 0x0003 39 static void* DSoundDLL =
NULL;
40 typedef HRESULT (WINAPI *fnDirectSoundCreate8)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
41 typedef HRESULT (WINAPI *fnDirectSoundEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
42 typedef HRESULT (WINAPI *fnDirectSoundCaptureCreate8)(LPCGUID,LPDIRECTSOUNDCAPTURE8 *,LPUNKNOWN);
43 typedef HRESULT (WINAPI *fnDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW,LPVOID);
44 static fnDirectSoundCreate8 pDirectSoundCreate8 =
NULL;
45 static fnDirectSoundEnumerateW pDirectSoundEnumerateW =
NULL;
46 static fnDirectSoundCaptureCreate8 pDirectSoundCaptureCreate8 =
NULL;
47 static fnDirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW =
NULL;
52 pDirectSoundCreate8 =
NULL;
53 pDirectSoundEnumerateW =
NULL;
54 pDirectSoundCaptureCreate8 =
NULL;
55 pDirectSoundCaptureEnumerateW =
NULL;
57 if (DSoundDLL !=
NULL) {
72 if (DSoundDLL ==
NULL) {
76 #define DSOUNDLOAD(f) { \ 77 p##f = (fn##f) SDL_LoadFunction(DSoundDLL, #f); \ 78 if (!p##f) loaded = 0; \ 81 DSOUNDLOAD(DirectSoundCreate8);
82 DSOUNDLOAD(DirectSoundEnumerateW);
83 DSOUNDLOAD(DirectSoundCaptureCreate8);
84 DSOUNDLOAD(DirectSoundCaptureEnumerateW);
88 SDL_SetError(
"DirectSound: System doesn't appear to have DX8.");
100 SetDSerror(
const char *
function,
int code)
102 static const char *error;
103 static char errbuf[1024];
108 error =
"Unsupported interface -- Is DirectX 8.0 or later installed?";
110 case DSERR_ALLOCATED:
111 error =
"Audio device in use";
113 case DSERR_BADFORMAT:
114 error =
"Unsupported audio format";
116 case DSERR_BUFFERLOST:
117 error =
"Mixing buffer was lost";
119 case DSERR_CONTROLUNAVAIL:
120 error =
"Control requested is not available";
122 case DSERR_INVALIDCALL:
123 error =
"Invalid call for the current state";
125 case DSERR_INVALIDPARAM:
126 error =
"Invalid parameter";
129 error =
"No audio device found";
131 case DSERR_OUTOFMEMORY:
132 error =
"Out of memory";
134 case DSERR_PRIOLEVELNEEDED:
135 error =
"Caller doesn't have priority";
137 case DSERR_UNSUPPORTED:
138 error =
"Function not supported";
142 "%s: Unknown DirectSound error: 0x%x",
function, code);
153 DSOUND_FreeDeviceHandle(
void *
handle)
159 FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID
data)
165 LPGUID cpyguid = (LPGUID)
SDL_malloc(
sizeof (GUID));
175 DSOUND_DetectDevices(
void)
177 pDirectSoundCaptureEnumerateW(FindAllDevs, (
void *) ((
size_t) 1));
178 pDirectSoundEnumerateW(FindAllDevs, (
void *) ((
size_t) 0));
183 DSOUND_WaitDevice(
_THIS)
193 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
195 if (result != DS_OK) {
196 if (result == DSERR_BUFFERLOST) {
197 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
200 SetDSerror(
"DirectSound GetCurrentPosition", result);
205 while ((cursor / this->
spec.
size) == this->hidden->lastchunk) {
210 IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
211 if ((status & DSBSTATUS_BUFFERLOST)) {
212 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
213 IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
214 if ((status & DSBSTATUS_BUFFERLOST)) {
218 if (!(status & DSBSTATUS_PLAYING)) {
219 result = IDirectSoundBuffer_Play(this->hidden->mixbuf, 0, 0,
221 if (result == DS_OK) {
225 SetDSerror(
"DirectSound Play", result);
231 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
233 if (result != DS_OK) {
234 SetDSerror(
"DirectSound GetCurrentPosition", result);
241 DSOUND_PlayDevice(
_THIS)
244 if (this->hidden->locked_buf) {
245 IDirectSoundBuffer_Unlock(this->hidden->mixbuf,
246 this->hidden->locked_buf,
247 this->spec.size,
NULL, 0);
252 DSOUND_GetDeviceBuf(
_THIS)
256 HRESULT result = DS_OK;
260 this->hidden->locked_buf =
NULL;
261 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
263 if (result == DSERR_BUFFERLOST) {
264 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
265 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
268 if (result != DS_OK) {
269 SetDSerror(
"DirectSound GetCurrentPosition", result);
277 if (spot < this->hidden->lastchunk) {
278 spot += this->hidden->num_buffers;
280 if (spot > this->hidden->lastchunk + 1) {
281 fprintf(stderr,
"Audio dropout, missed %d fragments\n",
282 (spot - (this->hidden->lastchunk + 1)));
286 this->hidden->lastchunk =
cursor;
287 cursor = (cursor + 1) % this->hidden->num_buffers;
288 cursor *= this->spec.size;
291 result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
293 (LPVOID *) & this->hidden->locked_buf,
294 &rawlen,
NULL, &junk, 0);
295 if (result == DSERR_BUFFERLOST) {
296 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
297 result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
300 hidden->locked_buf, &rawlen, NULL,
303 if (result != DS_OK) {
304 SetDSerror(
"DirectSound Lock", result);
307 return (this->hidden->locked_buf);
311 DSOUND_CaptureFromDevice(
_THIS,
void *
buffer,
int buflen)
314 DWORD junk,
cursor, ptr1len, ptr2len;
325 if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->
capturebuf, &junk, &cursor) != DS_OK) {
335 if (IDirectSoundCaptureBuffer_Lock(h->
capturebuf, h->
lastchunk * this->spec.size, this->spec.size, &ptr1, &ptr1len, &ptr2, &ptr2len, 0) != DS_OK) {
345 if (IDirectSoundCaptureBuffer_Unlock(h->
capturebuf, ptr1, ptr1len, ptr2, ptr2len) != DS_OK) {
355 DSOUND_FlushCapture(
_THIS)
359 if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->
capturebuf, &junk, &cursor) == DS_OK) {
365 DSOUND_CloseDevice(
_THIS)
367 if (this->hidden->mixbuf != NULL) {
368 IDirectSoundBuffer_Stop(this->hidden->mixbuf);
369 IDirectSoundBuffer_Release(this->hidden->mixbuf);
371 if (this->hidden->sound != NULL) {
372 IDirectSound_Release(this->hidden->sound);
374 if (this->hidden->capturebuf != NULL) {
375 IDirectSoundCaptureBuffer_Stop(this->hidden->capturebuf);
376 IDirectSoundCaptureBuffer_Release(this->hidden->capturebuf);
378 if (this->hidden->capture != NULL) {
379 IDirectSoundCapture_Release(this->hidden->capture);
389 CreateSecondary(
_THIS,
const DWORD
bufsize, WAVEFORMATEX *wfmt)
391 LPDIRECTSOUND sndObj = this->hidden->sound;
392 LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
393 HRESULT result = DS_OK;
395 LPVOID pvAudioPtr1, pvAudioPtr2;
396 DWORD dwAudioBytes1, dwAudioBytes2;
400 format.dwSize =
sizeof(
format);
401 format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
402 format.dwFlags |= DSBCAPS_GLOBALFOCUS;
403 format.dwBufferBytes =
bufsize;
404 format.lpwfxFormat = wfmt;
405 result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
406 if (result != DS_OK) {
407 return SetDSerror(
"DirectSound CreateSoundBuffer", result);
409 IDirectSoundBuffer_SetFormat(*sndbuf, wfmt);
412 result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
413 (LPVOID *) & pvAudioPtr1, &dwAudioBytes1,
414 (LPVOID *) & pvAudioPtr2, &dwAudioBytes2,
415 DSBLOCK_ENTIREBUFFER);
416 if (result == DS_OK) {
418 IDirectSoundBuffer_Unlock(*sndbuf,
419 (LPVOID) pvAudioPtr1, dwAudioBytes1,
420 (LPVOID) pvAudioPtr2, dwAudioBytes2);
432 CreateCaptureBuffer(
_THIS,
const DWORD bufsize, WAVEFORMATEX *wfmt)
434 LPDIRECTSOUNDCAPTURE
capture = this->hidden->capture;
435 LPDIRECTSOUNDCAPTUREBUFFER *
capturebuf = &this->hidden->capturebuf;
440 format.dwSize =
sizeof (
format);
441 format.dwFlags = DSCBCAPS_WAVEMAPPED;
442 format.dwBufferBytes =
bufsize;
443 format.lpwfxFormat = wfmt;
445 result = IDirectSoundCapture_CreateCaptureBuffer(capture, &format, capturebuf, NULL);
446 if (result != DS_OK) {
447 return SetDSerror(
"DirectSound CreateCaptureBuffer", result);
450 result = IDirectSoundCaptureBuffer_Start(*capturebuf, DSCBSTART_LOOPING);
451 if (result != DS_OK) {
452 IDirectSoundCaptureBuffer_Release(*capturebuf);
453 return SetDSerror(
"DirectSound Start", result);
458 result = IDirectSoundCaptureBuffer_GetCurrentPosition(*capturebuf, &junk, &cursor);
459 if (result != DS_OK) {
460 IDirectSoundCaptureBuffer_Stop(*capturebuf);
461 IDirectSoundCaptureBuffer_Release(*capturebuf);
462 return SetDSerror(
"DirectSound GetCurrentPosition", result);
465 this->hidden->lastchunk = cursor / this->
spec.
size;
472 DSOUND_OpenDevice(
_THIS,
void *
handle,
const char *devname,
int iscapture)
474 const DWORD numchunks = 8;
479 LPGUID guid = (LPGUID) handle;
485 if (this->hidden == NULL) {
492 result = pDirectSoundCaptureCreate8(guid, &this->hidden->capture, NULL);
493 if (result != DS_OK) {
494 return SetDSerror(
"DirectSoundCaptureCreate8", result);
497 result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
498 if (result != DS_OK) {
499 return SetDSerror(
"DirectSoundCreate8", result);
501 result = IDirectSound_SetCooperativeLevel(this->hidden->sound,
504 if (result != DS_OK) {
505 return SetDSerror(
"DirectSound SetCooperativeLevel", result);
509 while ((!valid_format) && (test_format)) {
510 switch (test_format) {
522 bufsize = numchunks * this->
spec.
size;
523 if ((bufsize < DSBSIZE_MIN) || (bufsize > DSBSIZE_MAX)) {
524 SDL_SetError(
"Sound buffer size must be between %d and %d",
525 (
int) ((DSBSIZE_MIN < numchunks) ? 1 : DSBSIZE_MIN / numchunks),
526 (
int) (DSBSIZE_MAX / numchunks));
532 wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
534 wfmt.wFormatTag = WAVE_FORMAT_PCM;
539 wfmt.nSamplesPerSec = this->
spec.
freq;
540 wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
541 wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
543 rc = iscapture ? CreateCaptureBuffer(
this, bufsize, &wfmt) : CreateSecondary(this, bufsize, &wfmt);
545 this->hidden->num_buffers = numchunks;
558 return SDL_SetError(
"DirectSound: Unsupported audio format");
568 DSOUND_Deinitialize(
void)
577 if (!DSOUND_Load()) {
599 "directsound",
"DirectSound", DSOUND_Init, 0
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
void(* DetectDevices)(void)
LPDIRECTSOUNDCAPTUREBUFFER capturebuf
GLfloat GLfloat GLfloat GLfloat h
void(* PlayDevice)(_THIS)
void(* WaitDevice)(_THIS)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Uint16 SDL_AudioFormat
Audio format flags.
SDL_AudioFormat SDL_NextAudioFormat(void)
GLenum GLuint GLsizei bufsize
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
#define SDL_AUDIO_ISFLOAT(x)
char * WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid)
EGLImageKHR EGLint EGLint * handle
LPDIRECTSOUNDCAPTURE capture
#define SDL_AUDIO_BITSIZE(x)
void(* Deinitialize)(void)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
#define SDL_assert(condition)
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
#define SDL_OutOfMemory()
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
void(* CloseDevice)(_THIS)
void(* FreeDeviceHandle)(void *handle)
void(* FlushCapture)(_THIS)
Uint8 *(* GetDeviceBuf)(_THIS)
AudioBootStrap DSOUND_bootstrap
#define SDL_arraysize(array)
void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)