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 *fnDirectSoundCaptureCreate8)(LPCGUID,LPDIRECTSOUNDCAPTURE8 *,LPUNKNOWN);
42 typedef HRESULT (WINAPI *fnDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW,LPVOID);
43 static fnDirectSoundCreate8 pDirectSoundCreate8 =
NULL;
44 static fnDirectSoundEnumerateW pDirectSoundEnumerateW =
NULL;
45 static fnDirectSoundCaptureCreate8 pDirectSoundCaptureCreate8 =
NULL;
46 static fnDirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW =
NULL;
51 pDirectSoundCreate8 =
NULL;
52 pDirectSoundEnumerateW =
NULL;
53 pDirectSoundCaptureCreate8 =
NULL;
54 pDirectSoundCaptureEnumerateW =
NULL;
56 if (DSoundDLL !=
NULL) {
71 if (DSoundDLL ==
NULL) {
75 #define DSOUNDLOAD(f) { \
76 p##f = (fn##f) SDL_LoadFunction(DSoundDLL, #f); \
77 if (!p##f) loaded = 0; \
80 DSOUNDLOAD(DirectSoundCreate8);
81 DSOUNDLOAD(DirectSoundEnumerateW);
82 DSOUNDLOAD(DirectSoundCaptureCreate8);
83 DSOUNDLOAD(DirectSoundCaptureEnumerateW);
87 SDL_SetError(
"DirectSound: System doesn't appear to have DX8.");
99 SetDSerror(
const char *
function,
int code)
101 static const char *error;
102 static char errbuf[1024];
107 error =
"Unsupported interface -- Is DirectX 8.0 or later installed?";
109 case DSERR_ALLOCATED:
110 error =
"Audio device in use";
112 case DSERR_BADFORMAT:
113 error =
"Unsupported audio format";
115 case DSERR_BUFFERLOST:
116 error =
"Mixing buffer was lost";
118 case DSERR_CONTROLUNAVAIL:
119 error =
"Control requested is not available";
121 case DSERR_INVALIDCALL:
122 error =
"Invalid call for the current state";
124 case DSERR_INVALIDPARAM:
125 error =
"Invalid parameter";
128 error =
"No audio device found";
130 case DSERR_OUTOFMEMORY:
131 error =
"Out of memory";
133 case DSERR_PRIOLEVELNEEDED:
134 error =
"Caller doesn't have priority";
136 case DSERR_UNSUPPORTED:
137 error =
"Function not supported";
141 "%s: Unknown DirectSound error: 0x%x",
function, code);
152 DSOUND_FreeDeviceHandle(
void *
handle)
158 FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID
data)
160 const int iscapture = (
int) ((
size_t)
data);
164 LPGUID cpyguid = (LPGUID)
SDL_malloc(
sizeof (GUID));
174 DSOUND_DetectDevices(
void)
176 pDirectSoundCaptureEnumerateW(FindAllDevs, (
void *) ((
size_t) 1));
177 pDirectSoundEnumerateW(FindAllDevs, (
void *) ((
size_t) 0));
182 DSOUND_WaitDevice(
_THIS)
192 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
195 if (
result == DSERR_BUFFERLOST) {
196 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
199 SetDSerror(
"DirectSound GetCurrentPosition",
result);
209 IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
210 if ((status & DSBSTATUS_BUFFERLOST)) {
211 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
212 IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
213 if ((status & DSBSTATUS_BUFFERLOST)) {
217 if (!(status & DSBSTATUS_PLAYING)) {
218 result = IDirectSoundBuffer_Play(this->hidden->mixbuf, 0, 0,
224 SetDSerror(
"DirectSound Play",
result);
230 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
233 SetDSerror(
"DirectSound GetCurrentPosition",
result);
240 DSOUND_PlayDevice(
_THIS)
243 if (this->hidden->locked_buf) {
244 IDirectSoundBuffer_Unlock(this->hidden->mixbuf,
245 this->hidden->locked_buf,
246 this->spec.size,
NULL, 0);
251 DSOUND_GetDeviceBuf(
_THIS)
259 this->hidden->locked_buf =
NULL;
260 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
262 if (
result == DSERR_BUFFERLOST) {
263 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
264 result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
268 SetDSerror(
"DirectSound GetCurrentPosition",
result);
276 if (spot < this->hidden->lastchunk) {
277 spot += this->hidden->num_buffers;
279 if (spot > this->hidden->lastchunk + 1) {
280 fprintf(stderr,
"Audio dropout, missed %d fragments\n",
281 (spot - (this->hidden->lastchunk + 1)));
285 this->hidden->lastchunk =
cursor;
287 cursor *= this->spec.size;
290 result = IDirectSoundBuffer_Lock(this->hidden->mixbuf,
cursor,
292 (LPVOID *) & this->hidden->locked_buf,
293 &rawlen,
NULL, &junk, 0);
294 if (
result == DSERR_BUFFERLOST) {
295 IDirectSoundBuffer_Restore(this->hidden->mixbuf);
296 result = IDirectSoundBuffer_Lock(this->hidden->mixbuf,
cursor,
299 hidden->locked_buf, &rawlen,
NULL,
303 SetDSerror(
"DirectSound Lock",
result);
306 return (this->hidden->locked_buf);
310 DSOUND_CaptureFromDevice(
_THIS,
void *
buffer,
int buflen)
313 DWORD junk,
cursor, ptr1len, ptr2len;
324 if (IDirectSoundCaptureBuffer_GetCurrentPosition(
h->capturebuf, &junk, &
cursor) != DS_OK) {
334 if (IDirectSoundCaptureBuffer_Lock(
h->capturebuf,
h->lastchunk * this->spec.size, this->spec.size, &ptr1, &ptr1len, &ptr2, &ptr2len, 0) != DS_OK) {
344 if (IDirectSoundCaptureBuffer_Unlock(
h->capturebuf, ptr1, ptr1len, ptr2, ptr2len) != DS_OK) {
348 h->lastchunk = (
h->lastchunk + 1) %
h->num_buffers;
354 DSOUND_FlushCapture(
_THIS)
358 if (IDirectSoundCaptureBuffer_GetCurrentPosition(
h->capturebuf, &junk, &
cursor) == DS_OK) {
364 DSOUND_CloseDevice(
_THIS)
366 if (this->hidden->mixbuf !=
NULL) {
367 IDirectSoundBuffer_Stop(this->hidden->mixbuf);
368 IDirectSoundBuffer_Release(this->hidden->mixbuf);
370 if (this->hidden->sound !=
NULL) {
371 IDirectSound_Release(this->hidden->sound);
373 if (this->hidden->capturebuf !=
NULL) {
374 IDirectSoundCaptureBuffer_Stop(this->hidden->capturebuf);
375 IDirectSoundCaptureBuffer_Release(this->hidden->capturebuf);
377 if (this->hidden->capture !=
NULL) {
378 IDirectSoundCapture_Release(this->hidden->capture);
388 CreateSecondary(
_THIS,
const DWORD
bufsize, WAVEFORMATEX *wfmt)
390 LPDIRECTSOUND sndObj = this->hidden->sound;
391 LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
394 LPVOID pvAudioPtr1, pvAudioPtr2;
395 DWORD dwAudioBytes1, dwAudioBytes2;
400 format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
401 format.dwFlags |= DSBCAPS_GLOBALFOCUS;
403 format.lpwfxFormat = wfmt;
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);
417 IDirectSoundBuffer_Unlock(*sndbuf,
418 (LPVOID) pvAudioPtr1, dwAudioBytes1,
419 (LPVOID) pvAudioPtr2, dwAudioBytes2);
431 CreateCaptureBuffer(
_THIS,
const DWORD
bufsize, WAVEFORMATEX *wfmt)
433 LPDIRECTSOUNDCAPTURE
capture = this->hidden->capture;
434 LPDIRECTSOUNDCAPTUREBUFFER *
capturebuf = &this->hidden->capturebuf;
440 format.dwFlags = DSCBCAPS_WAVEMAPPED;
442 format.lpwfxFormat = wfmt;
446 return SetDSerror(
"DirectSound CreateCaptureBuffer",
result);
451 IDirectSoundCaptureBuffer_Release(*
capturebuf);
452 return SetDSerror(
"DirectSound Start",
result);
460 IDirectSoundCaptureBuffer_Release(*
capturebuf);
461 return SetDSerror(
"DirectSound GetCurrentPosition",
result);
473 const DWORD numchunks = 8;
478 LPGUID guid = (LPGUID)
handle;
484 if (this->hidden ==
NULL) {
491 result = pDirectSoundCaptureCreate8(guid, &this->hidden->capture,
NULL);
493 return SetDSerror(
"DirectSoundCaptureCreate8",
result);
496 result = pDirectSoundCreate8(guid, &this->hidden->sound,
NULL);
498 return SetDSerror(
"DirectSoundCreate8",
result);
500 result = IDirectSound_SetCooperativeLevel(this->hidden->sound,
504 return SetDSerror(
"DirectSound SetCooperativeLevel",
result);
508 while ((!valid_format) && (test_format)) {
509 switch (test_format) {
521 bufsize = numchunks * this->
spec.
size;
522 if ((bufsize < DSBSIZE_MIN) || (
bufsize > DSBSIZE_MAX)) {
523 SDL_SetError(
"Sound buffer size must be between %d and %d",
524 (
int) ((DSBSIZE_MIN < numchunks) ? 1 : DSBSIZE_MIN / numchunks),
525 (
int) (DSBSIZE_MAX / numchunks));
531 wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
533 wfmt.wFormatTag = WAVE_FORMAT_PCM;
538 wfmt.nSamplesPerSec = this->
spec.
freq;
539 wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
540 wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
544 this->hidden->num_buffers = numchunks;
557 return SDL_SetError(
"DirectSound: Unsupported audio format");
567 DSOUND_Deinitialize(
void)
576 if (!DSOUND_Load()) {
598 "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)
Uint8 *(* GetDeviceBuf)(_THIS)
void(* Deinitialize)(void)
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
void(* FreeDeviceHandle)(void *handle)
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
LPDIRECTSOUNDCAPTUREBUFFER capturebuf
LPDIRECTSOUNDCAPTURE capture
typedef int(__stdcall *FARPROC)()