Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Moved mme audio driver to 1.3 API.
Browse files Browse the repository at this point in the history
  • Loading branch information
icculus committed Oct 7, 2006
1 parent d6f6d84 commit cb96454
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 149 deletions.
273 changes: 131 additions & 142 deletions src/audio/mme/SDL_mmeaudio.c
Expand Up @@ -31,70 +31,12 @@


static BOOL inUse[NUM_BUFFERS]; static BOOL inUse[NUM_BUFFERS];


/* Audio driver functions */
static int MME_OpenAudio(_THIS, SDL_AudioSpec * spec);
static void MME_WaitAudio(_THIS);
static Uint8 *MME_GetAudioBuf(_THIS);
static void MME_PlayAudio(_THIS);
static void MME_WaitDone(_THIS);
static void MME_CloseAudio(_THIS);

/* Audio driver bootstrap functions */
static int static int
Audio_Available(void) MME_Available(void)
{ {
return (1); return 1;
} }


static void
Audio_DeleteDevice(SDL_AudioDevice * device)
{
if (device) {
if (device->hidden) {
SDL_free(device->hidden);
device->hidden = NULL;
}
SDL_free(device);
device = NULL;
}
}

static SDL_AudioDevice *
Audio_CreateDevice(int devindex)
{
SDL_AudioDevice *this;

/* Initialize all variables that we clean on shutdown */
this = SDL_malloc(sizeof(SDL_AudioDevice));
if (this) {
SDL_memset(this, 0, (sizeof *this));
this->hidden = 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 = MME_OpenAudio;
this->WaitAudio = MME_WaitAudio;
this->PlayAudio = MME_PlayAudio;
this->GetAudioBuf = MME_GetAudioBuf;
this->WaitDone = MME_WaitDone;
this->CloseAudio = MME_CloseAudio;
this->free = Audio_DeleteDevice;

return this;
}

AudioBootStrap MMEAUDIO_bootstrap = {
"waveout", "Tru64 MME WaveOut",
Audio_Available, Audio_CreateDevice, 0
};

static void static void
SetMMerror(char *function, MMRESULT code) SetMMerror(char *function, MMRESULT code)
{ {
Expand All @@ -108,7 +50,7 @@ SetMMerror(char *function, MMRESULT code)
} }


static void CALLBACK static void CALLBACK
MME_CALLBACK(HWAVEOUT hwo, MME_Callback(HWAVEOUT hwo,
UINT uMsg, DWORD dwInstance, LPARAM dwParam1, LPARAM dwParam2) UINT uMsg, DWORD dwInstance, LPARAM dwParam1, LPARAM dwParam2)
{ {
WAVEHDR *wp = (WAVEHDR *) dwParam1; WAVEHDR *wp = (WAVEHDR *) dwParam1;
Expand All @@ -118,116 +60,137 @@ MME_CALLBACK(HWAVEOUT hwo,
} }


static int static int
MME_OpenAudio(_THIS, SDL_AudioSpec * spec) MME_OpenDevice(_THIS, const char *devname, int iscapture)
{ {
int valid_format = 0;
MMRESULT result; MMRESULT result;
Uint8 *mixbuf = NULL;
int i; int i;


mixbuf = NULL; /* 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));


/* Set basic WAVE format parameters */ /* Set basic WAVE format parameters */
shm = mmeAllocMem(sizeof(*shm)); this->hidden->shm = mmeAllocMem(sizeof(*this->hidden->shm));
if (shm == NULL) { if (this->hidden->shm == NULL) {
SDL_SetError("Out of memory: shm"); MME_CloseDevice(this);
return (-1); SDL_OutOfMemory();
return 0;
} }
shm->sound = 0;
shm->wFmt.wf.wFormatTag = WAVE_FORMAT_PCM; memset(this->hidden->shm, '\0', sizeof (*this->hidden->shm));
this->hidden->shm->sound = 0;
this->hidden->shm->wFmt.wf.wFormatTag = WAVE_FORMAT_PCM;


/* Determine the audio parameters from the AudioSpec */ /* Determine the audio parameters from the AudioSpec */
switch (SDL_AUDIO_BITSIZE(spec->format)) { /* Try for a closest match on audio format */
case 8: for (test_format = SDL_FirstAudioFormat(this->spec.format);
/* Unsigned 8 bit audio data */ !valid_format && test_format;) {
spec->format = AUDIO_U8; valid_format = 1;
shm->wFmt.wBitsPerSample = 8; switch (test_format) {
break; case AUDIO_U8:
case 16: case AUDIO_S16:
/* Signed 16 bit audio data */ case AUDIO_S32:
spec->format = AUDIO_S16; break;
shm->wFmt.wBitsPerSample = 16; default:
break; valid_format = 0;
case 32: test_format = SDL_NextAudioFormat();
/* Signed 32 bit audio data */ }
spec->format = AUDIO_S32; }
shm->wFmt.wBitsPerSample = 32;
break; if (!valid_format) {
default: MME_CloseDevice(this);
SDL_SetError("Unsupported audio format"); SDL_SetError("Unsupported audio format");
return (-1); return 0;
} }


this->spec.format = test_format;
this->hidden->shm->wFmt.wBitsPerSample = SDL_AUDIO_BITSIZE(test_format);

/* !!! FIXME: Can this handle more than stereo? */ /* !!! FIXME: Can this handle more than stereo? */
shm->wFmt.wf.nChannels = spec->channels; this->hidden->shm->wFmt.wf.nChannels = this->spec.channels;
shm->wFmt.wf.nSamplesPerSec = spec->freq; this->hidden->shm->wFmt.wf.nSamplesPerSec = this->spec.freq;
shm->wFmt.wf.nBlockAlign = this->hidden->shm->wFmt.wf.nBlockAlign =
shm->wFmt.wf.nChannels * shm->wFmt.wBitsPerSample / 8; this->hidden->shm->wFmt.wf.nChannels *
shm->wFmt.wf.nAvgBytesPerSec = this->hidden->shm->wFmt.wBitsPerSample / 8;
shm->wFmt.wf.nSamplesPerSec * shm->wFmt.wf.nBlockAlign; this->hidden->shm->wFmt.wf.nAvgBytesPerSec =
this->hidden->shm->wFmt.wf.nSamplesPerSec *
this->hidden->shm->wFmt.wf.nBlockAlign;


/* Check the buffer size -- minimum of 1/4 second (word aligned) */ /* Check the buffer size -- minimum of 1/4 second (word aligned) */
if (spec->samples < (spec->freq / 4)) if (this->spec.samples < (this->spec.freq / 4))
spec->samples = ((spec->freq / 4) + 3) & ~3; this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;


/* Update the fragment size as size in bytes */ /* Update the fragment size as size in bytes */
SDL_CalculateAudioSpec(spec); SDL_CalculateAudioSpec(&this->spec);


/* Open the audio device */ /* Open the audio device */
result = waveOutOpen(&(shm->sound), result = waveOutOpen(&(this->hidden->shm->sound),
WAVE_MAPPER, WAVE_MAPPER,
&(shm->wFmt.wf), &(this->hidden->shm->wFmt.wf),
MME_CALLBACK, MME_Callback,
NULL, (CALLBACK_FUNCTION | WAVE_OPEN_SHAREABLE)); NULL, (CALLBACK_FUNCTION | WAVE_OPEN_SHAREABLE));
if (result != MMSYSERR_NOERROR) { if (result != MMSYSERR_NOERROR) {
MME_CloseDevice(this);
SetMMerror("waveOutOpen()", result); SetMMerror("waveOutOpen()", result);
return (-1); return 0;
} }


/* Create the sound buffers */ /* Create the sound buffers */
mixbuf = (Uint8 *) mmeAllocBuffer(NUM_BUFFERS * (spec->size)); mixbuf = (Uint8 *) mmeAllocBuffer(NUM_BUFFERS * (this->spec.size));
if (mixbuf == NULL) { if (mixbuf == NULL) {
SDL_SetError("Out of memory: mixbuf"); MME_CloseDevice(this);
return (-1); SDL_OutOfMemory();
return 0;
} }
this->hidden->mixbuf = mixbuf;


for (i = 0; i < NUM_BUFFERS; i++) { for (i = 0; i < NUM_BUFFERS; i++) {
shm->wHdr[i].lpData = &mixbuf[i * (spec->size)]; this->hidden->shm->wHdr[i].lpData = &mixbuf[i * (this->spec.size)];
shm->wHdr[i].dwBufferLength = spec->size; this->hidden->shm->wHdr[i].dwBufferLength = this->spec.size;
shm->wHdr[i].dwFlags = 0; this->hidden->shm->wHdr[i].dwFlags = 0;
shm->wHdr[i].dwUser = i; this->hidden->shm->wHdr[i].dwUser = i;
shm->wHdr[i].dwLoops = 0; /* loop control counter */ this->hidden->shm->wHdr[i].dwLoops = 0; /* loop control counter */
shm->wHdr[i].lpNext = NULL; /* reserved for driver */ this->hidden->shm->wHdr[i].lpNext = NULL; /* reserved for driver */
shm->wHdr[i].reserved = 0; this->hidden->shm->wHdr[i].reserved = 0;
inUse[i] = FALSE; inUse[i] = FALSE;
} }
next_buffer = 0; this->hidden->next_buffer = 0;
return 0;
return 1;
} }


static void static void
MME_WaitAudio(_THIS) MME_WaitDevice(_THIS)
{ {
while (inUse[next_buffer]) { while (inUse[this->hidden->next_buffer]) {
mmeWaitForCallbacks(); mmeWaitForCallbacks();
mmeProcessCallbacks(); mmeProcessCallbacks();
} }
} }


static Uint8 * static Uint8 *
MME_GetAudioBuf(_THIS) MME_GetDeviceBuf(_THIS)
{ {
Uint8 *retval; void *retval = this->hidden->shm->wHdr[this->hidden->next_buffer].lpData;

inUse[this->hidden->next_buffer] = TRUE;
inUse[next_buffer] = TRUE; return (Uint8 *) retval;
retval = (Uint8 *) (shm->wHdr[next_buffer].lpData);
return retval;
} }


static void static void
MME_PlayAudio(_THIS) MME_PlayDevice(_THIS)
{ {
/* Queue it up */ /* Queue it up */
waveOutWrite(shm->sound, &(shm->wHdr[next_buffer]), sizeof(WAVEHDR)); waveOutWrite(this->hidden->shm->sound,
next_buffer = (next_buffer + 1) % NUM_BUFFERS; &(this->hidden->shm->wHdr[this->hidden->next_buffer]),
sizeof (WAVEHDR));
this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
} }


static void static void
Expand All @@ -236,43 +199,69 @@ MME_WaitDone(_THIS)
MMRESULT result; MMRESULT result;
int i; int i;


if (shm->sound) { if (this->hidden->shm->sound) {
for (i = 0; i < NUM_BUFFERS; i++) for (i = 0; i < NUM_BUFFERS; i++)
while (inUse[i]) { while (inUse[i]) {
mmeWaitForCallbacks(); mmeWaitForCallbacks();
mmeProcessCallbacks(); mmeProcessCallbacks();
} }
result = waveOutReset(shm->sound); result = waveOutReset(this->hidden->shm->sound);
if (result != MMSYSERR_NOERROR) if (result != MMSYSERR_NOERROR)
SetMMerror("waveOutReset()", result); SetMMerror("waveOutReset()", result);
mmeProcessCallbacks(); mmeProcessCallbacks();
} }
} }


static void static void
MME_CloseAudio(_THIS) MME_CloseDevice(_THIS)
{ {
MMRESULT result; if (this->hidden != NULL) {
MMRESULT result;


if (mixbuf) { if (this->hidden->mixbuf) {
result = mmeFreeBuffer(mixbuf); result = mmeFreeBuffer(this->hidden->mixbuf);
if (result != MMSYSERR_NOERROR) if (result != MMSYSERR_NOERROR)
SetMMerror("mmeFreeBuffer", result); SetMMerror("mmeFreeBuffer", result);
mixbuf = NULL; this->hidden->mixbuf = NULL;
} }


if (shm) { if (this->hidden->shm) {
if (shm->sound) { if (this->hidden->shm->sound) {
result = waveOutClose(shm->sound); result = waveOutClose(this->hidden->shm->sound);
if (result != MMSYSERR_NOERROR)
SetMMerror("waveOutClose()", result);
mmeProcessCallbacks();
}
result = mmeFreeMem(this->hidden->shm);
if (result != MMSYSERR_NOERROR) if (result != MMSYSERR_NOERROR)
SetMMerror("waveOutClose()", result); SetMMerror("mmeFreeMem()", result);
mmeProcessCallbacks(); this->hidden->shm = NULL;
} }
result = mmeFreeMem(shm);
if (result != MMSYSERR_NOERROR) SDL_free(this->hidden);
SetMMerror("mmeFreeMem()", result); this->hidden = NULL;
shm = NULL;
} }
} }


static int
MME_Init(SDL_AudioDriverImpl *impl)
{
/* Set the function pointers */
impl->OpenDevice = MME_OpenDevice;
impl->WaitDevice = MME_WaitDevice;
impl->WaitDone = MME_WaitDone;
impl->PlayDevice = MME_PlayDevice;
impl->GetDeviceBuf = MME_GetDeviceBuf;
impl->CloseDevice = MME_CloseDevice;
impl->OnlyHasDefaultOutputDevice = 1;

return 1;
}

/* !!! FIXME: Windows "windib" driver is called waveout, too */
AudioBootStrap MMEAUDIO_bootstrap = {
"waveout", "Tru64 MME WaveOut",
MME_Available, MME_Init, 0
};

/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */
11 changes: 4 additions & 7 deletions src/audio/mme/SDL_mmeaudio.h
Expand Up @@ -23,8 +23,8 @@


/* Allow access to a raw mixing buffer */ /* Allow access to a raw mixing buffer */


#ifndef _SDL_lowaudio_h #ifndef _SDL_mmeaudio_h
#define _SDL_lowaudio_h #define _SDL_mmeaudio_h


#include "../SDL_sysaudio.h" #include "../SDL_sysaudio.h"


Expand All @@ -46,9 +46,6 @@ struct SDL_PrivateAudioData
int next_buffer; int next_buffer;
}; };


#define shm (this->hidden->shm) #endif /* _SDL_mmeaudio_h */
#define mixbuf (this->hidden->mixbuf)
#define next_buffer (this->hidden->next_buffer)
/* Old variable names */
#endif /* _SDL_lowaudio_h */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

0 comments on commit cb96454

Please sign in to comment.