Mercurial > sdl-ios-xcode
diff src/audio/windx5/SDL_dx5audio.c @ 2049:5f6550e5184f
Merged SDL-ryan-multiple-audio-device branch r2803:2871 into the trunk.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Tue, 17 Oct 2006 09:15:21 +0000 |
parents | 4ad1e863d100 |
children | bbc89e09503f |
line wrap: on
line diff
--- a/src/audio/windx5/SDL_dx5audio.c Sun Oct 01 16:10:41 2006 +0000 +++ b/src/audio/windx5/SDL_dx5audio.c Tue Oct 17 09:15:21 2006 +0000 @@ -28,160 +28,65 @@ #include "../SDL_audio_c.h" #include "SDL_dx5audio.h" -/* Define this if you want to use DirectX 6 DirectSoundNotify interface */ -//#define USE_POSITION_NOTIFY +/* !!! FIXME: move this somewhere that other drivers can use it... */ +#if defined(_WIN32_WCE) +#define WINDOWS_OS_NAME "Windows CE/PocketPC" +#elif defined(WIN64) +#define WINDOWS_OS_NAME "Win64" +#else +#define WINDOWS_OS_NAME "Win32" +#endif /* DirectX function pointers for audio */ -HRESULT(WINAPI * DSoundCreate) (LPGUID, LPDIRECTSOUND *, LPUNKNOWN); - -/* Audio driver functions */ -static int DX5_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void DX5_ThreadInit(_THIS); -static void DX5_WaitAudio_BusyWait(_THIS); -#ifdef USE_POSITION_NOTIFY -static void DX6_WaitAudio_EventWait(_THIS); -#endif -static void DX5_PlayAudio(_THIS); -static Uint8 *DX5_GetAudioBuf(_THIS); -static void DX5_WaitDone(_THIS); -static void DX5_CloseAudio(_THIS); - -/* Audio driver bootstrap functions */ - -static int -Audio_Available(void) -{ - HINSTANCE DSoundDLL; - int dsound_ok; - - /* Version check DSOUND.DLL (Is DirectX okay?) */ - dsound_ok = 0; - DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL")); - if (DSoundDLL != NULL) { - /* We just use basic DirectSound, we're okay */ - /* Yay! */ - /* Unfortunately, the sound drivers on NT have - higher latencies than the audio buffers used - by many SDL applications, so there are gaps - in the audio - it sounds terrible. Punt for now. - */ - OSVERSIONINFO ver; - ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&ver); - switch (ver.dwPlatformId) { - case VER_PLATFORM_WIN32_NT: - if (ver.dwMajorVersion > 4) { - /* Win2K */ - dsound_ok = 1; - } else { - /* WinNT */ - dsound_ok = 0; - } - break; - default: - /* Win95 or Win98 */ - dsound_ok = 1; - break; - } - /* Now check for DirectX 5 or better - otherwise - * we will fail later in DX5_OpenAudio without a chance - * to fall back to the DIB driver. */ - if (dsound_ok) { - /* DirectSoundCaptureCreate was added in DX5 */ - if (!GetProcAddress(DSoundDLL, TEXT("DirectSoundCaptureCreate"))) - dsound_ok = 0; - - } - /* Clean up.. */ - FreeLibrary(DSoundDLL); - } - return (dsound_ok); -} - -/* Functions for loading the DirectX functions dynamically */ static HINSTANCE DSoundDLL = NULL; +static HRESULT (WINAPI *DSoundCreate)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN) = NULL; static void -DX5_Unload(void) +DSOUND_Unload(void) { if (DSoundDLL != NULL) { FreeLibrary(DSoundDLL); - DSoundCreate = NULL; - DSoundDLL = NULL; } -} -static int -DX5_Load(void) -{ - int status; - DX5_Unload(); - DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL")); - if (DSoundDLL != NULL) { - DSoundCreate = (void *) GetProcAddress(DSoundDLL, - TEXT("DirectSoundCreate")); - } - if (DSoundDLL && DSoundCreate) { - status = 0; - } else { - DX5_Unload(); - status = -1; - } - return status; -} - -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - DX5_Unload(); - SDL_free(device->hidden); - SDL_free(device); + DSoundCreate = NULL; + DSoundDLL = NULL; } -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) + +static int +DSOUND_Load(void) { - SDL_AudioDevice *this; + int loaded = 0; + + DSOUND_Unload(); - /* Load DirectX */ - if (DX5_Load() < 0) { - return (NULL); + DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL")); + if (DSoundDLL == NULL) { + SDL_SetError("DirectSound: failed to load DSOUND.DLL"); + } else { + /* Now make sure we have DirectX 5 or better... */ + /* (DirectSoundCaptureCreate was added in DX5) */ + if (!GetProcAddress(DSoundDLL, TEXT("DirectSoundCaptureCreate"))) { + SDL_SetError("DirectSound: System doesn't appear to have DX5."); + } else { + DSoundCreate = (void *) GetProcAddress(DSoundDLL, + TEXT("DirectSoundCreate")); + } + + if (!DSoundCreate) { + SDL_SetError("DirectSound: Failed to find DirectSoundCreate"); + } else { + loaded = 1; + } } - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); + if (!loaded) { + DSOUND_Unload(); } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - /* Set the function pointers */ - this->OpenAudio = DX5_OpenAudio; - this->ThreadInit = DX5_ThreadInit; - this->WaitAudio = DX5_WaitAudio_BusyWait; - this->PlayAudio = DX5_PlayAudio; - this->GetAudioBuf = DX5_GetAudioBuf; - this->WaitDone = DX5_WaitDone; - this->CloseAudio = DX5_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; + return loaded; } -AudioBootStrap DSOUND_bootstrap = { - "dsound", "Win95/98/2000 DirectSound", - Audio_Available, Audio_CreateDevice -}; static void SetDSerror(const char *function, int code) @@ -192,8 +97,7 @@ errbuf[0] = 0; switch (code) { case E_NOINTERFACE: - error = - "Unsupported interface\n-- Is DirectX 5.0 or later installed?"; + error = "Unsupported interface -- Is DirectX 5.0 or later installed?"; break; case DSERR_ALLOCATED: error = "Audio device in use"; @@ -241,32 +145,36 @@ /* DirectSound needs to be associated with a window */ static HWND mainwin = NULL; /* */ + void -DX5_SoundFocus(HWND hwnd) +DSOUND_SoundFocus(HWND hwnd) { + /* !!! FIXME: probably broken with multi-window support in SDL 1.3 ... */ mainwin = hwnd; } static void -DX5_ThreadInit(_THIS) +DSOUND_ThreadInit(_THIS) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); } static void -DX5_WaitAudio_BusyWait(_THIS) +DSOUND_WaitDevice(_THIS) { - DWORD status; - DWORD cursor, junk; - HRESULT result; + DWORD status = 0; + DWORD cursor = 0; + DWORD junk = 0; + HRESULT result = DS_OK; /* Semi-busy wait, since we have no way of getting play notification on a primary mixing buffer located in hardware (DirectX 5.0) */ - result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor); + result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf, + &junk, &cursor); if (result != DS_OK) { if (result == DSERR_BUFFERLOST) { - IDirectSoundBuffer_Restore(mixbuf); + IDirectSoundBuffer_Restore(this->hidden->mixbuf); } #ifdef DEBUG_SOUND SetDSerror("DirectSound GetCurrentPosition", result); @@ -274,21 +182,22 @@ return; } - while ((cursor / mixlen) == lastchunk) { + while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) { /* FIXME: find out how much time is left and sleep that long */ SDL_Delay(1); /* Try to restore a lost sound buffer */ - IDirectSoundBuffer_GetStatus(mixbuf, &status); + IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status); if ((status & DSBSTATUS_BUFFERLOST)) { - IDirectSoundBuffer_Restore(mixbuf); - IDirectSoundBuffer_GetStatus(mixbuf, &status); + IDirectSoundBuffer_Restore(this->hidden->mixbuf); + IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status); if ((status & DSBSTATUS_BUFFERLOST)) { break; } } if (!(status & DSBSTATUS_PLAYING)) { - result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); + result = IDirectSoundBuffer_Play(this->hidden->mixbuf, 0, 0, + DSBPLAY_LOOPING); if (result == DS_OK) { continue; } @@ -299,7 +208,7 @@ } /* Find out where we are playing */ - result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, + result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf, &junk, &cursor); if (result != DS_OK) { SetDSerror("DirectSound GetCurrentPosition", result); @@ -308,222 +217,122 @@ } } -#ifdef USE_POSITION_NOTIFY static void -DX6_WaitAudio_EventWait(_THIS) -{ - DWORD status; - HRESULT result; - - /* Try to restore a lost sound buffer */ - IDirectSoundBuffer_GetStatus(mixbuf, &status); - if ((status & DSBSTATUS_BUFFERLOST)) { - IDirectSoundBuffer_Restore(mixbuf); - IDirectSoundBuffer_GetStatus(mixbuf, &status); - if ((status & DSBSTATUS_BUFFERLOST)) { - return; - } - } - if (!(status & DSBSTATUS_PLAYING)) { - result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); - if (result != DS_OK) { -#ifdef DEBUG_SOUND - SetDSerror("DirectSound Play", result); -#endif - return; - } - } - WaitForSingleObject(audio_event, INFINITE); -} -#endif /* USE_POSITION_NOTIFY */ - -static void -DX5_PlayAudio(_THIS) +DSOUND_PlayDevice(_THIS) { /* Unlock the buffer, allowing it to play */ - if (locked_buf) { - IDirectSoundBuffer_Unlock(mixbuf, locked_buf, mixlen, NULL, 0); + if (this->hidden->locked_buf) { + IDirectSoundBuffer_Unlock(this->hidden->mixbuf, + this->hidden->locked_buf, + this->hidden->mixlen, NULL, 0); } } static Uint8 * -DX5_GetAudioBuf(_THIS) +DSOUND_GetDeviceBuf(_THIS) { - DWORD cursor, junk; - HRESULT result; - DWORD rawlen; + DWORD cursor = 0; + DWORD junk = 0; + HRESULT result = DS_OK; + DWORD rawlen = 0; /* Figure out which blocks to fill next */ - locked_buf = NULL; - result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor); + this->hidden->locked_buf = NULL; + result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf, + &junk, &cursor); if (result == DSERR_BUFFERLOST) { - IDirectSoundBuffer_Restore(mixbuf); - result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, + IDirectSoundBuffer_Restore(this->hidden->mixbuf); + result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf, &junk, &cursor); } if (result != DS_OK) { SetDSerror("DirectSound GetCurrentPosition", result); return (NULL); } - cursor /= mixlen; + cursor /= this->hidden->mixlen; #ifdef DEBUG_SOUND /* Detect audio dropouts */ { DWORD spot = cursor; - if (spot < lastchunk) { - spot += NUM_BUFFERS; + if (spot < this->hidden->lastchunk) { + spot += this->hidden->num_buffers; } - if (spot > lastchunk + 1) { + if (spot > this->hidden->lastchunk + 1) { fprintf(stderr, "Audio dropout, missed %d fragments\n", - (spot - (lastchunk + 1))); + (spot - (this->hidden->lastchunk + 1))); } } #endif - lastchunk = cursor; - cursor = (cursor + 1) % NUM_BUFFERS; - cursor *= mixlen; + this->hidden->lastchunk = cursor; + cursor = (cursor + 1) % this->hidden->num_buffers; + cursor *= this->hidden->mixlen; /* Lock the audio buffer */ - result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, - (LPVOID *) & locked_buf, &rawlen, NULL, - &junk, 0); + result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor, + this->hidden->mixlen, + (LPVOID *) &this->hidden->locked_buf, + &rawlen, NULL, &junk, 0); if (result == DSERR_BUFFERLOST) { - IDirectSoundBuffer_Restore(mixbuf); - result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, - (LPVOID *) & locked_buf, &rawlen, - NULL, &junk, 0); + IDirectSoundBuffer_Restore(this->hidden->mixbuf); + result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor, + this->hidden->mixlen, + (LPVOID *) &this->hidden->locked_buf, + &rawlen, NULL, &junk, 0); } if (result != DS_OK) { SetDSerror("DirectSound Lock", result); return (NULL); } - return (locked_buf); -} - -static void -DX5_WaitDone(_THIS) -{ - Uint8 *stream; - - /* Wait for the playing chunk to finish */ - stream = this->GetAudioBuf(this); - if (stream != NULL) { - SDL_memset(stream, silence, mixlen); - this->PlayAudio(this); - } - this->WaitAudio(this); - - /* Stop the looping sound buffer */ - IDirectSoundBuffer_Stop(mixbuf); + return (this->hidden->locked_buf); } static void -DX5_CloseAudio(_THIS) +DSOUND_WaitDone(_THIS) { - if (sound != NULL) { - if (mixbuf != NULL) { - /* Clean up the audio buffer */ - IDirectSoundBuffer_Release(mixbuf); - mixbuf = NULL; - } - if (audio_event != NULL) { - CloseHandle(audio_event); - audio_event = NULL; - } - IDirectSound_Release(sound); - sound = NULL; + Uint8 *stream = DSOUND_GetDeviceBuf(this); + + /* Wait for the playing chunk to finish */ + if (stream != NULL) { + SDL_memset(stream, this->spec.silence, this->hidden->mixlen); + DSOUND_PlayDevice(this); } + DSOUND_WaitDevice(this); + + /* Stop the looping sound buffer */ + IDirectSoundBuffer_Stop(this->hidden->mixbuf); } -#ifdef USE_PRIMARY_BUFFER -/* This function tries to create a primary audio buffer, and returns the - number of audio chunks available in the created buffer. -*/ -static int -CreatePrimary(LPDIRECTSOUND sndObj, HWND focus, - LPDIRECTSOUNDBUFFER * sndbuf, WAVEFORMATEX * wavefmt, - Uint32 chunksize) +static void +DSOUND_CloseDevice(_THIS) { - HRESULT result; - DSBUFFERDESC format; - DSBCAPS caps; - int numchunks; + if (this->hidden != NULL) { + if (this->hidden->sound != NULL) { + if (this->hidden->mixbuf != NULL) { + /* Clean up the audio buffer */ + IDirectSoundBuffer_Release(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + IDirectSound_Release(this->hidden->sound); + this->hidden->sound = NULL; + } - /* Try to set primary mixing privileges */ - result = IDirectSound_SetCooperativeLevel(sndObj, focus, - DSSCL_WRITEPRIMARY); - if (result != DS_OK) { -#ifdef DEBUG_SOUND - SetDSerror("DirectSound SetCooperativeLevel", result); -#endif - return (-1); - } - - /* Try to create the primary buffer */ - SDL_memset(&format, 0, sizeof(format)); - format.dwSize = sizeof(format); - format.dwFlags = (DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2); - format.dwFlags |= DSBCAPS_STICKYFOCUS; -#ifdef USE_POSITION_NOTIFY - format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; -#endif - result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); - if (result != DS_OK) { -#ifdef DEBUG_SOUND - SetDSerror("DirectSound CreateSoundBuffer", result); -#endif - return (-1); + SDL_free(this->hidden); + this->hidden = NULL; } - - /* Check the size of the fragment buffer */ - SDL_memset(&caps, 0, sizeof(caps)); - caps.dwSize = sizeof(caps); - result = IDirectSoundBuffer_GetCaps(*sndbuf, &caps); - if (result != DS_OK) { -#ifdef DEBUG_SOUND - SetDSerror("DirectSound GetCaps", result); -#endif - IDirectSoundBuffer_Release(*sndbuf); - return (-1); - } - if ((chunksize > caps.dwBufferBytes) || - ((caps.dwBufferBytes % chunksize) != 0)) { - /* The primary buffer size is not a multiple of 'chunksize' - -- this hopefully doesn't happen when 'chunksize' is a - power of 2. - */ - IDirectSoundBuffer_Release(*sndbuf); - SDL_SetError - ("Primary buffer size is: %d, cannot break it into chunks of %d bytes\n", - caps.dwBufferBytes, chunksize); - return (-1); - } - numchunks = (caps.dwBufferBytes / chunksize); - - /* Set the primary audio format */ - result = IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); - if (result != DS_OK) { -#ifdef DEBUG_SOUND - SetDSerror("DirectSound SetFormat", result); -#endif - IDirectSoundBuffer_Release(*sndbuf); - return (-1); - } - return (numchunks); } -#endif /* USE_PRIMARY_BUFFER */ /* This function tries to create a secondary audio buffer, and returns the number of audio chunks available in the created buffer. */ static int -CreateSecondary(LPDIRECTSOUND sndObj, HWND focus, - LPDIRECTSOUNDBUFFER * sndbuf, WAVEFORMATEX * wavefmt, - Uint32 chunksize) +CreateSecondary(_THIS, HWND focus, WAVEFORMATEX *wavefmt) { + LPDIRECTSOUND sndObj = this->hidden->sound; + LPDIRECTSOUNDBUFFER *sndbuf = this->hidden->mixbuf; + Uint32 chunksize = this->spec.size; const int numchunks = 8; - HRESULT result; + HRESULT result = DS_OK; DSBUFFERDESC format; LPVOID pvAudioPtr1, pvAudioPtr2; DWORD dwAudioBytes1, dwAudioBytes2; @@ -538,9 +347,7 @@ DSSCL_NORMAL); } if (result != DS_OK) { -#ifdef DEBUG_SOUND SetDSerror("DirectSound SetCooperativeLevel", result); -#endif return (-1); } @@ -548,9 +355,6 @@ SDL_memset(&format, 0, sizeof(format)); format.dwSize = sizeof(format); format.dwFlags = DSBCAPS_GETCURRENTPOSITION2; -#ifdef USE_POSITION_NOTIFY - format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; -#endif if (!focus) { format.dwFlags |= DSBCAPS_GLOBALFOCUS; } else { @@ -578,11 +382,7 @@ (LPVOID *) & pvAudioPtr2, &dwAudioBytes2, DSBLOCK_ENTIREBUFFER); if (result == DS_OK) { - if (wavefmt->wBitsPerSample == 8) { - SDL_memset(pvAudioPtr1, 0x80, dwAudioBytes1); - } else { - SDL_memset(pvAudioPtr1, 0x00, dwAudioBytes1); - } + SDL_memset(pvAudioPtr1, this->spec.silence, dwAudioBytes1); IDirectSoundBuffer_Unlock(*sndbuf, (LPVOID) pvAudioPtr1, dwAudioBytes1, (LPVOID) pvAudioPtr2, dwAudioBytes2); @@ -592,148 +392,125 @@ return (numchunks); } -/* This function tries to set position notify events on the mixing buffer */ -#ifdef USE_POSITION_NOTIFY static int -CreateAudioEvent(_THIS) -{ - LPDIRECTSOUNDNOTIFY notify; - DSBPOSITIONNOTIFY *notify_positions; - int i, retval; - HRESULT result; - - /* Default to fail on exit */ - retval = -1; - notify = NULL; - - /* Query for the interface */ - result = IDirectSoundBuffer_QueryInterface(mixbuf, - &IID_IDirectSoundNotify, - (void *) ¬ify); - if (result != DS_OK) { - goto done; - } - - /* Allocate the notify structures */ - notify_positions = (DSBPOSITIONNOTIFY *) SDL_malloc(NUM_BUFFERS * - sizeof - (*notify_positions)); - if (notify_positions == NULL) { - goto done; - } - - /* Create the notify event */ - audio_event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (audio_event == NULL) { - goto done; - } - - /* Set up the notify structures */ - for (i = 0; i < NUM_BUFFERS; ++i) { - notify_positions[i].dwOffset = i * mixlen; - notify_positions[i].hEventNotify = audio_event; - } - result = IDirectSoundNotify_SetNotificationPositions(notify, - NUM_BUFFERS, - notify_positions); - if (result == DS_OK) { - retval = 0; - } - done: - if (notify != NULL) { - IDirectSoundNotify_Release(notify); - } - return (retval); -} -#endif /* USE_POSITION_NOTIFY */ - -static int -DX5_OpenAudio(_THIS, SDL_AudioSpec * spec) +DSOUND_OpenDevice(_THIS, const char *devname, int iscapture) { HRESULT result; WAVEFORMATEX waveformat; + int valid_format = 0; + SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); - /* Set basic WAVE format parameters */ + /* !!! FIXME: handle devname */ + /* !!! FIXME: handle iscapture */ + + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + while ((!valid_format) && (test_format)) { + switch (test_format) { + case AUDIO_U8: + case AUDIO_S16: + case AUDIO_S32: + this->spec.format = test_format; + valid_format = 1; + break; + } + test_format = SDL_NextAudioFormat(); + } + + if (!valid_format) { + DSOUND_CloseDevice(this); + SDL_SetError("DirectSound: Unsupported audio format"); + return 0; + } + SDL_memset(&waveformat, 0, sizeof(waveformat)); waveformat.wFormatTag = WAVE_FORMAT_PCM; - - /* Determine the audio parameters from the AudioSpec */ - switch (SDL_AUDIO_BITSIZE(spec->format)) { - case 8: - /* Unsigned 8 bit audio data */ - spec->format = AUDIO_U8; - silence = 0x80; - waveformat.wBitsPerSample = 8; - break; - case 16: - /* Signed 16 bit audio data */ - spec->format = AUDIO_S16; - silence = 0x00; - waveformat.wBitsPerSample = 16; - break; - case 32: - /* Signed 32 bit audio data */ - spec->format = AUDIO_S32; - silence = 0x00; - waveformat.wBitsPerSample = 32; - break; - default: - SDL_SetError("Unsupported audio format"); - return (-1); - } - waveformat.nChannels = spec->channels; - waveformat.nSamplesPerSec = spec->freq; + waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format); + waveformat.nChannels = this->spec.channels; + waveformat.nSamplesPerSec = this->spec.freq; waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample / 8); waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign; /* Update the fragment size as size in bytes */ - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Open the audio device */ - result = DSoundCreate(NULL, &sound, NULL); + result = DSoundCreate(NULL, &this->hidden->sound, NULL); if (result != DS_OK) { + DSOUND_CloseDevice(this); SetDSerror("DirectSoundCreate", result); - return (-1); + return 0; } /* Create the audio buffer to which we write */ - NUM_BUFFERS = -1; -#ifdef USE_PRIMARY_BUFFER - if (mainwin) { - NUM_BUFFERS = CreatePrimary(sound, mainwin, &mixbuf, - &waveformat, spec->size); - } -#endif /* USE_PRIMARY_BUFFER */ - if (NUM_BUFFERS < 0) { - NUM_BUFFERS = CreateSecondary(sound, mainwin, &mixbuf, - &waveformat, spec->size); - if (NUM_BUFFERS < 0) { - return (-1); - } -#ifdef DEBUG_SOUND - fprintf(stderr, "Using secondary audio buffer\n"); -#endif + this->hidden->num_buffers = CreateSecondary(this, mainwin, &waveformat); + if (this->hidden->num_buffers < 0) { + DSOUND_CloseDevice(this); + return 0; } -#ifdef DEBUG_SOUND - else - fprintf(stderr, "Using primary audio buffer\n"); -#endif - /* The buffer will auto-start playing in DX5_WaitAudio() */ - lastchunk = 0; - mixlen = spec->size; + /* The buffer will auto-start playing in DSOUND_WaitDevice() */ + this->hidden->mixlen = this->spec.size; -#ifdef USE_POSITION_NOTIFY - /* See if we can use DirectX 6 event notification */ - if (CreateAudioEvent(this) == 0) { - this->WaitAudio = DX6_WaitAudio_EventWait; - } else { - this->WaitAudio = DX5_WaitAudio_BusyWait; - } -#endif - return (0); + return 1; /* good to go. */ +} + + +static void +DSOUND_Deinitialize(void) +{ + DSOUND_Unload(); } + +static int +DSOUND_Init(SDL_AudioDriverImpl *impl) +{ + OSVERSIONINFO ver; + + /* + * Unfortunately, the sound drivers on NT have higher latencies than the + * audio buffers used by many SDL applications, so there are gaps in the + * audio - it sounds terrible. Punt for now. + */ + SDL_memset(&ver, '\0', sizeof (OSVERSIONINFO)); + ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&ver); + if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) + if (ver.dwMajorVersion <= 4) { + return 0; /* NT4.0 or earlier. Disable dsound support. */ + } + } + + if (!DSOUND_Load()) { + return 0; + } + + /* Set the function pointers */ + impl->OpenDevice = DSOUND_OpenDevice; + impl->PlayDevice = DSOUND_PlayDevice; + impl->WaitDevice = DSOUND_WaitDevice; + impl->WaitDone = DSOUND_WaitDone; + impl->ThreadInit = DSOUND_ThreadInit; + impl->GetDeviceBuf = DSOUND_GetDeviceBuf; + impl->CloseDevice = DSOUND_CloseDevice; + impl->Deinitialize = DSOUND_Deinitialize; + impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME */ + + return 1; +} + +AudioBootStrap DSOUND_bootstrap = { + "dsound", WINDOWS_OS_NAME "DirectSound", DSOUND_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */