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
39static void* DSoundDLL =
NULL;
40typedef HRESULT (WINAPI *fnDirectSoundCreate8)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
41typedef HRESULT (WINAPI *fnDirectSoundEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
42typedef HRESULT (WINAPI *fnDirectSoundCaptureCreate8)(LPCGUID,LPDIRECTSOUNDCAPTURE8 *,LPUNKNOWN);
43typedef HRESULT (WINAPI *fnDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW,LPVOID);
44static fnDirectSoundCreate8 pDirectSoundCreate8 =
NULL;
45static fnDirectSoundEnumerateW pDirectSoundEnumerateW =
NULL;
46static fnDirectSoundCaptureCreate8 pDirectSoundCaptureCreate8 =
NULL;
47static 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.");
100SetDSerror(
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);
153DSOUND_FreeDeviceHandle(
void *
handle)
159FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID
data)
161 const int iscapture = (int) ((
size_t)
data);
165 LPGUID cpyguid = (LPGUID)
SDL_malloc(
sizeof (GUID));
175DSOUND_DetectDevices(
void)
177 pDirectSoundCaptureEnumerateW(FindAllDevs, (
void *) ((
size_t) 1));
178 pDirectSoundEnumerateW(FindAllDevs, (
void *) ((
size_t) 0));
183DSOUND_WaitDevice(
_THIS)
193 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
196 if (
result == DSERR_BUFFERLOST) {
197 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
200 SetDSerror(
"DirectSound GetCurrentPosition",
result);
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,
225 SetDSerror(
"DirectSound Play",
result);
231 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
234 SetDSerror(
"DirectSound GetCurrentPosition",
result);
241DSOUND_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);
252DSOUND_GetDeviceBuf(
_THIS)
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,
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;
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,
304 SetDSerror(
"DirectSound Lock",
result);
307 return (this->hidden->locked_buf);
311DSOUND_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) {
349 h->lastchunk = (
h->lastchunk + 1) %
h->num_buffers;
355DSOUND_FlushCapture(
_THIS)
359 if (IDirectSoundCaptureBuffer_GetCurrentPosition(
h->capturebuf, &junk, &
cursor) == DS_OK) {
365DSOUND_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);
389CreateSecondary(
_THIS,
const DWORD
bufsize, WAVEFORMATEX *wfmt)
391 LPDIRECTSOUND sndObj = this->hidden->sound;
392 LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
395 LPVOID pvAudioPtr1, pvAudioPtr2;
396 DWORD dwAudioBytes1, dwAudioBytes2;
401 format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
402 format.dwFlags |= DSBCAPS_GLOBALFOCUS;
404 format.lpwfxFormat = wfmt;
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);
418 IDirectSoundBuffer_Unlock(*sndbuf,
419 (LPVOID) pvAudioPtr1, dwAudioBytes1,
420 (LPVOID) pvAudioPtr2, dwAudioBytes2);
432CreateCaptureBuffer(
_THIS,
const DWORD
bufsize, WAVEFORMATEX *wfmt)
434 LPDIRECTSOUNDCAPTURE
capture = this->hidden->capture;
435 LPDIRECTSOUNDCAPTUREBUFFER *
capturebuf = &this->hidden->capturebuf;
441 format.dwFlags = DSCBCAPS_WAVEMAPPED;
443 format.lpwfxFormat = wfmt;
447 return SetDSerror(
"DirectSound CreateCaptureBuffer",
result);
452 IDirectSoundCaptureBuffer_Release(*
capturebuf);
453 return SetDSerror(
"DirectSound Start",
result);
461 IDirectSoundCaptureBuffer_Release(*
capturebuf);
462 return SetDSerror(
"DirectSound GetCurrentPosition",
result);
474 const DWORD numchunks = 8;
479 LPGUID guid = (LPGUID)
handle;
485 if (this->hidden ==
NULL) {
492 result = pDirectSoundCaptureCreate8(guid, &this->hidden->capture,
NULL);
494 return SetDSerror(
"DirectSoundCaptureCreate8",
result);
497 result = pDirectSoundCreate8(guid, &this->hidden->sound,
NULL);
499 return SetDSerror(
"DirectSoundCreate8",
result);
501 result = IDirectSound_SetCooperativeLevel(this->hidden->sound,
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;
545 this->hidden->num_buffers = numchunks;
558 return SDL_SetError(
"DirectSound: Unsupported audio format");
568DSOUND_Deinitialize(
void)
577 if (!DSOUND_Load()) {
599 "directsound",
"DirectSound", DSOUND_Init, 0
#define SDL_assert(condition)
void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
SDL_AudioFormat SDL_NextAudioFormat(void)
Uint16 SDL_AudioFormat
Audio format flags.
#define SDL_AUDIO_ISFLOAT(x)
#define SDL_AUDIO_BITSIZE(x)
#define SDL_OutOfMemory()
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
GLenum GLuint GLsizei bufsize
GLfloat GLfloat GLfloat GLfloat h
#define SDL_arraysize(array)
AudioBootStrap DSOUND_bootstrap
char * WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid)
EGLImageKHR EGLint EGLint * handle
void(* PlayDevice)(_THIS)
void(* WaitDevice)(_THIS)
void(* CloseDevice)(_THIS)
void(* FlushCapture)(_THIS)
void(* DetectDevices)(void)
void(* Deinitialize)(void)
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
void(* FreeDeviceHandle)(void *handle)
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Uint8 *(* GetDeviceBuf)(_THIS)
LPDIRECTSOUNDCAPTUREBUFFER capturebuf
LPDIRECTSOUNDCAPTURE capture