Mercurial > sdl-ios-xcode
diff src/audio/windib/SDL_dibaudio.c @ 3841:3479f939987c SDL-ryan-multiple-audio-device
Moved windib (waveout) audio to 1.3 API and made other cleanups.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sun, 08 Oct 2006 23:04:24 +0000 |
parents | c8b3d3d13ed1 |
children | 66fb40445587 |
line wrap: on
line diff
--- a/src/audio/windib/SDL_dibaudio.c Sun Oct 08 08:58:36 2006 +0000 +++ b/src/audio/windib/SDL_dibaudio.c Sun Oct 08 23:04:24 2006 +0000 @@ -35,72 +35,20 @@ #include "win_ce_semaphore.h" #endif - -/* Audio driver functions */ -static int DIB_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void DIB_ThreadInit(_THIS); -static void DIB_WaitAudio(_THIS); -static Uint8 *DIB_GetAudioBuf(_THIS); -static void DIB_PlayAudio(_THIS); -static void DIB_WaitDone(_THIS); -static void DIB_CloseAudio(_THIS); - -/* Audio driver bootstrap functions */ +#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 static int -Audio_Available(void) -{ - return (1); -} - -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) +WINWAVEOUT_Available(void) { - SDL_AudioDevice *this; - - /* 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); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - /* Set the function pointers */ - this->OpenAudio = DIB_OpenAudio; - this->ThreadInit = DIB_ThreadInit; - this->WaitAudio = DIB_WaitAudio; - this->PlayAudio = DIB_PlayAudio; - this->GetAudioBuf = DIB_GetAudioBuf; - this->WaitDone = DIB_WaitDone; - this->CloseAudio = DIB_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; + return 1; /* Always available on win32/pocketpc systems... */ } -AudioBootStrap WAVEOUT_bootstrap = { - "waveout", "Win95/98/NT/2000 WaveOut", - Audio_Available, Audio_CreateDevice, 0 -}; - - /* The Win32 callback for filling the WAVE device */ static void CALLBACK FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, @@ -114,9 +62,9 @@ /* Signal that we are done playing a buffer */ #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) - ReleaseSemaphoreCE(audio_sem, 1, NULL); + ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL); #else - ReleaseSemaphore(audio_sem, 1, NULL); + ReleaseSemaphore(this->hidden->audio_sem, 1, NULL); #endif } @@ -146,48 +94,47 @@ /* Set high priority for the audio thread */ static void -DIB_ThreadInit(_THIS) +WINWAVEOUT_ThreadInit(_THIS) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); } void -DIB_WaitAudio(_THIS) +WINWAVEOUT_WaitDevice(_THIS) { /* Wait for an audio chunk to finish */ #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) - WaitForSemaphoreCE(audio_sem, INFINITE); + WaitForSemaphoreCE(this->hidden->audio_sem, INFINITE); #else - WaitForSingleObject(audio_sem, INFINITE); + WaitForSingleObject(this->hidden->audio_sem, INFINITE); #endif } Uint8 * -DIB_GetAudioBuf(_THIS) +WINWAVEOUT_GetDeviceBuf(_THIS) { - Uint8 *retval; - - retval = (Uint8 *) (wavebuf[next_buffer].lpData); - return retval; + return (Uint8 *) (this->hidden->wavebuf[this->hidden->next_buffer].lpData); } void -DIB_PlayAudio(_THIS) +WINWAVEOUT_PlayDevice(_THIS) { /* Queue it up */ - waveOutWrite(sound, &wavebuf[next_buffer], sizeof(wavebuf[0])); - next_buffer = (next_buffer + 1) % NUM_BUFFERS; + waveOutWrite(this->hidden->sound, + &this->hidden->wavebuf[this->hidden->next_buffer], + sizeof (this->hidden->wavebuf[0])); + this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS; } void -DIB_WaitDone(_THIS) +WINWAVEOUT_WaitDone(_THIS) { int i, left; do { left = NUM_BUFFERS; for (i = 0; i < NUM_BUFFERS; ++i) { - if (wavebuf[i].dwFlags & WHDR_DONE) { + if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) { --left; } } @@ -199,143 +146,198 @@ } void -DIB_CloseAudio(_THIS) +WINWAVEOUT_CloseDevice(_THIS) { - int i; - /* Close up audio */ - if (audio_sem) { + if (this->hidden != NULL) { + int i; + + if (this->hidden->audio_sem) { #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) - CloseSynchHandle(audio_sem); + CloseSynchHandle(this->hidden->audio_sem); #else - CloseHandle(audio_sem); + CloseHandle(this->hidden->audio_sem); #endif - } - if (sound) { - waveOutClose(sound); - } + this->hidden->audio_sem = 0; + } + + if (this->hidden->sound) { + waveOutClose(this->hidden->sound); + this->hidden->sound = 0; + } - /* Clean up mixing buffers */ - for (i = 0; i < NUM_BUFFERS; ++i) { - if (wavebuf[i].dwUser != 0xFFFF) { - waveOutUnprepareHeader(sound, &wavebuf[i], sizeof(wavebuf[i])); - wavebuf[i].dwUser = 0xFFFF; + /* Clean up mixing buffers */ + for (i = 0; i < NUM_BUFFERS; ++i) { + if (this->hidden->wavebuf[i].dwUser != 0xFFFF) { + waveOutUnprepareHeader(this->hidden->sound, + &this->hidden->wavebuf[i], + sizeof (this->hidden->wavebuf[i])); + this->hidden->wavebuf[i].dwUser = 0xFFFF; + } } - } - /* Free raw mixing buffer */ - if (mixbuf != NULL) { - SDL_free(mixbuf); - mixbuf = NULL; + + if (this->hidden->mixbuf != NULL) { + /* Free raw mixing buffer */ + SDL_free(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + + SDL_free(this->hidden); + this->hidden = NULL; } } int -DIB_OpenAudio(_THIS, SDL_AudioSpec * spec) +WINWAVEOUT_OpenDevice(_THIS, const char *devname, int iscapture) { + SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); + int valid_datatype = 0; MMRESULT result; + WAVEFORMATEX waveformat; int i; - WAVEFORMATEX waveformat; + + /* 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)); /* Initialize the wavebuf structures for closing */ - sound = NULL; - audio_sem = NULL; for (i = 0; i < NUM_BUFFERS; ++i) - wavebuf[i].dwUser = 0xFFFF; - mixbuf = NULL; + this->hidden->wavebuf[i].dwUser = 0xFFFF; + + while ((!valid_datatype) && (test_format)) { + valid_datatype = 1; + _this->spec.format = test_format; + switch (test_format) { + case AUDIO_U8: + case AUDIO_S16: + case AUDIO_S32: + break; /* valid. */ + + default: + valid_datatype = 0; + test_format = SDL_NextAudioFormat(); + break; + } + } + + if (!valid_datatype) { + WINWAVEOUT_CloseDevice(this); + SDL_SetError("Unsupported audio format"); + return 0; + } /* Set basic WAVE format parameters */ - SDL_memset(&waveformat, 0, sizeof(waveformat)); + SDL_memset(&waveformat, '\0', sizeof (waveformat)); waveformat.wFormatTag = WAVE_FORMAT_PCM; + waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format); - /* Determine the audio parameters from the AudioSpec */ - switch (SDL_AUDIO_BITSIZE(spec->format)) { - case 8: - /* Unsigned 8 bit audio data */ - spec->format = AUDIO_U8; - waveformat.wBitsPerSample = 8; - break; - case 16: - /* Signed 16 bit audio data */ - spec->format = AUDIO_S16; - waveformat.wBitsPerSample = 16; - break; - case 32: - /* Signed 32 bit audio data */ - spec->format = AUDIO_S32; - waveformat.wBitsPerSample = 32; - break; - default: - SDL_SetError("Unsupported audio format"); - return (-1); - } - waveformat.nChannels = spec->channels; - waveformat.nSamplesPerSec = spec->freq; + if (this->spec.channels > 2) + this->spec.channels = 2; /* !!! FIXME: is this right? */ + + waveformat.nChannels = this->spec.channels; + waveformat.nSamplesPerSec = this->spec.freq; waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample / 8); waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign; /* Check the buffer size -- minimum of 1/4 second (word aligned) */ - if (spec->samples < (spec->freq / 4)) - spec->samples = ((spec->freq / 4) + 3) & ~3; + if (this->spec.samples < (this->spec.freq / 4)) + this->spec.samples = ((this->spec.freq / 4) + 3) & ~3; /* Update the fragment size as size in bytes */ - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Open the audio device */ - result = waveOutOpen(&sound, WAVE_MAPPER, &waveformat, + result = waveOutOpen(&this->hidden->sound, WAVE_MAPPER, &waveformat, (DWORD_PTR) FillSound, (DWORD_PTR) this, CALLBACK_FUNCTION); if (result != MMSYSERR_NOERROR) { + WINWAVEOUT_CloseDevice(this); SetMMerror("waveOutOpen()", result); - return (-1); + return 0; } #ifdef SOUND_DEBUG /* Check the sound device we retrieved */ { WAVEOUTCAPS caps; - result = waveOutGetDevCaps((UINT) sound, &caps, sizeof(caps)); + result = waveOutGetDevCaps((UINT) this->hidden->sound, + &caps, sizeof(caps)); if (result != MMSYSERR_NOERROR) { + WINWAVEOUT_CloseDevice(this); SetMMerror("waveOutGetDevCaps()", result); - return (-1); + return 0; } printf("Audio device: %s\n", caps.szPname); } #endif /* Create the audio buffer semaphore */ + this->hidden->audio_sem = #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) - audio_sem = CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL); + CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL); #else - audio_sem = CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL); + CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL); #endif - if (audio_sem == NULL) { + if (this->hidden->audio_sem == NULL) { + WINWAVEOUT_CloseDevice(this); SDL_SetError("Couldn't create semaphore"); - return (-1); + return 0; } /* Create the sound buffers */ - mixbuf = (Uint8 *) SDL_malloc(NUM_BUFFERS * spec->size); + this->hidden->mixbuf = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size); if (mixbuf == NULL) { - SDL_SetError("Out of memory"); - return (-1); + WINWAVEOUT_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } for (i = 0; i < NUM_BUFFERS; ++i) { - SDL_memset(&wavebuf[i], 0, sizeof(wavebuf[i])); - wavebuf[i].lpData = (LPSTR) & mixbuf[i * spec->size]; - wavebuf[i].dwBufferLength = spec->size; - wavebuf[i].dwFlags = WHDR_DONE; - result = waveOutPrepareHeader(sound, &wavebuf[i], sizeof(wavebuf[i])); + SDL_memset(&this->hidden->wavebuf[i], '\0', + sizeof (this->hidden->wavebuf[i])); + this->hidden->wavebuf[i].dwBufferLength = this->spec.size; + this->hidden->wavebuf[i].dwFlags = WHDR_DONE; + this->hidden->wavebuf[i].lpData = + (LPSTR) &this->hidden->mixbuf[i * this->spec.size]; + result = waveOutPrepareHeader(this->hidden->sound, + &this->hidden->wavebuf[i], + sizeof (this->hidden->wavebuf[i])); if (result != MMSYSERR_NOERROR) { + WINWAVEOUT_CloseDevice(this); SetMMerror("waveOutPrepareHeader()", result); - return (-1); + return 0; } } - /* Ready to go! */ - next_buffer = 0; - return (0); + return 1; /* Ready to go! */ } + +static int +WINWAVEOUT_Init(SDL_AudioDriverImpl *impl) +{ + /* Set the function pointers */ + impl->OpenDevice = WINWAVEOUT_OpenDevice; + impl->ThreadInit = WINWAVEOUT_ThreadInit; + impl->PlayDevice = WINWAVEOUT_PlayDevice; + impl->WaitDevice = WINWAVEOUT_WaitDevice; + impl->WaitDone = WINWAVEOUT_WaitDone; + impl->GetDeviceBuf = WINWAVEOUT_GetDeviceBuf; + impl->CloseDevice = WINWAVEOUT_CloseDevice; + impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: Is this true? */ + + return 1; +} + +AudioBootStrap WINWAVEOUT_bootstrap = { + "waveout", WINDOWS_OS_NAME " WaveOut", + WINWAVEOUT_Available, WINWAVEOUT_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */