mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-24 02:30:46 +00:00
Clean up DirectSound driver in audiolib
This includes a small patch from Nuke.YKT as well. git-svn-id: https://svn.eduke32.com/eduke32@7361 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
c757725e65
commit
425c183c67
2 changed files with 308 additions and 338 deletions
|
@ -24,75 +24,58 @@
|
|||
|
||||
#define NEED_MMSYSTEM_H
|
||||
#define NEED_DSOUND_H
|
||||
#include "windows_inc.h"
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
#include "driver_directsound.h"
|
||||
#include "multivoc.h"
|
||||
#include "windows_inc.h"
|
||||
|
||||
enum {
|
||||
DSErr_Warning = -2,
|
||||
DSErr_Error = -1,
|
||||
DSErr_Ok = 0,
|
||||
DSErr_Uninitialised,
|
||||
DSErr_DirectSoundCreate,
|
||||
DSErr_SetCooperativeLevel,
|
||||
DSErr_CreateSoundBuffer,
|
||||
DSErr_CreateSoundBufferSecondary,
|
||||
DSErr_SetFormat,
|
||||
DSErr_SetFormatSecondary,
|
||||
DSErr_Notify,
|
||||
DSErr_NotifyEvents,
|
||||
DSErr_SetNotificationPositions,
|
||||
DSErr_Play,
|
||||
DSErr_PlaySecondary,
|
||||
DSErr_CreateThread,
|
||||
DSErr_CreateMutex
|
||||
};
|
||||
#define MIXBUFFERPOSITIONS 8
|
||||
|
||||
static int32_t ErrorCode = DSErr_Ok;
|
||||
static int32_t Initialised = 0;
|
||||
static int32_t Playing = 0;
|
||||
static int32_t Initialised;
|
||||
static int32_t Playing;
|
||||
|
||||
static char *MixBuffer = NULL;
|
||||
static int32_t MixBufferSize = 0;
|
||||
static int32_t MixBufferCount = 0;
|
||||
static int32_t MixBufferCurrent = 0;
|
||||
static int32_t MixBufferUsed = 0;
|
||||
static void ( *MixCallBack )( void ) = NULL;
|
||||
static char * MixBuffer = NULL;
|
||||
static int32_t MixBufferSize;
|
||||
static int32_t MixBufferCount;
|
||||
static int32_t MixBufferCurrent;
|
||||
static int32_t MixBufferUsed;
|
||||
|
||||
static void (*MixCallBack)(void) = NULL;
|
||||
|
||||
static LPDIRECTSOUND lpds = NULL;
|
||||
static LPDIRECTSOUNDBUFFER lpdsbprimary = NULL, lpdsbsec = NULL;
|
||||
static LPDIRECTSOUNDNOTIFY lpdsnotify = NULL;
|
||||
static DSBPOSITIONNOTIFY notifyPositions[3] = { { 0,0 }, { 0,0 }, { 0,0 } };
|
||||
|
||||
static HANDLE mixThread = NULL;
|
||||
static HANDLE mutex = NULL;
|
||||
static HANDLE mutex = NULL;
|
||||
|
||||
static DSBPOSITIONNOTIFY notifyPositions[MIXBUFFERPOSITIONS + 1] = {};
|
||||
|
||||
static void FillBufferPortion(char * ptr, int32_t remaining)
|
||||
static void FillBufferPosition(char * ptr, int32_t remaining)
|
||||
{
|
||||
int32_t len = 0;
|
||||
char *sptr;
|
||||
|
||||
while (remaining >= len) {
|
||||
if (MixBufferUsed == MixBufferSize) {
|
||||
do
|
||||
{
|
||||
if (MixBufferUsed == MixBufferSize)
|
||||
{
|
||||
MixCallBack();
|
||||
|
||||
MixBufferUsed = 0;
|
||||
MixBufferCurrent++;
|
||||
if (MixBufferCurrent >= MixBufferCount) {
|
||||
|
||||
if (++MixBufferCurrent >= MixBufferCount)
|
||||
MixBufferCurrent -= MixBufferCount;
|
||||
}
|
||||
}
|
||||
|
||||
while (remaining >= len && MixBufferUsed < MixBufferSize) {
|
||||
sptr = MixBuffer + (MixBufferCurrent * MixBufferSize) + MixBufferUsed;
|
||||
do
|
||||
{
|
||||
char *sptr = MixBuffer + (MixBufferCurrent * MixBufferSize) + MixBufferUsed;
|
||||
|
||||
len = MixBufferSize - MixBufferUsed;
|
||||
if (remaining < len) {
|
||||
|
||||
if (remaining < len)
|
||||
len = remaining;
|
||||
}
|
||||
|
||||
memcpy(ptr, sptr, len);
|
||||
|
||||
|
@ -100,110 +83,301 @@ static void FillBufferPortion(char * ptr, int32_t remaining)
|
|||
MixBufferUsed += len;
|
||||
remaining -= len;
|
||||
}
|
||||
while (remaining >= len && MixBufferUsed < MixBufferSize);
|
||||
}
|
||||
while (remaining >= len);
|
||||
}
|
||||
|
||||
static void FillBuffer(int32_t bufnum)
|
||||
{
|
||||
HRESULT err;
|
||||
LPVOID ptr, ptr2;
|
||||
DWORD remaining, remaining2;
|
||||
int32_t retries = 1;
|
||||
|
||||
//initprintf( "DirectSound FillBuffer: filling %d\n", bufnum);
|
||||
|
||||
do {
|
||||
err = IDirectSoundBuffer_Lock(lpdsbsec,
|
||||
notifyPositions[bufnum].dwOffset,
|
||||
notifyPositions[1].dwOffset,
|
||||
&ptr, &remaining,
|
||||
&ptr2, &remaining2,
|
||||
0);
|
||||
if (FAILED(err)) {
|
||||
if (err == DSERR_BUFFERLOST) {
|
||||
err = IDirectSoundBuffer_Restore(lpdsbsec);
|
||||
if (FAILED(err)) {
|
||||
do
|
||||
{
|
||||
HRESULT err = IDirectSoundBuffer_Lock(lpdsbsec, notifyPositions[bufnum].dwOffset, notifyPositions[1].dwOffset,
|
||||
&ptr, &remaining, &ptr2, &remaining2, 0);
|
||||
if (FAILED(err))
|
||||
{
|
||||
if (err == DSERR_BUFFERLOST)
|
||||
{
|
||||
if (FAILED(err = IDirectSoundBuffer_Restore(lpdsbsec)))
|
||||
return;
|
||||
}
|
||||
|
||||
if (retries-- > 0) {
|
||||
if (retries-- > 0)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (MV_Printf)
|
||||
MV_Printf("DirectSound FillBuffer: err %x\n", (uint32_t) err);
|
||||
MV_Printf("DirectSound FillBuffer: err %x\n", (uint32_t)err);
|
||||
|
||||
return;
|
||||
}
|
||||
break;
|
||||
} while (1);
|
||||
}
|
||||
while (1);
|
||||
|
||||
if (ptr) {
|
||||
FillBufferPortion((char *) ptr, remaining);
|
||||
}
|
||||
if (ptr2) {
|
||||
FillBufferPortion((char *) ptr2, remaining2);
|
||||
}
|
||||
if (ptr && remaining)
|
||||
FillBufferPosition((char *)ptr, remaining);
|
||||
|
||||
if (ptr2 && remaining2)
|
||||
FillBufferPosition((char *)ptr2, remaining2);
|
||||
|
||||
IDirectSoundBuffer_Unlock(lpdsbsec, ptr, remaining, ptr2, remaining2);
|
||||
}
|
||||
|
||||
static DWORD WINAPI fillDataThread(LPVOID lpParameter)
|
||||
{
|
||||
DWORD waitret, waitret2;
|
||||
HANDLE handles[] = { handles[0] = notifyPositions[0].hEventNotify,
|
||||
handles[1] = notifyPositions[1].hEventNotify,
|
||||
handles[2] = notifyPositions[2].hEventNotify };
|
||||
|
||||
UNREFERENCED_PARAMETER(lpParameter);
|
||||
|
||||
do {
|
||||
waitret = WaitForMultipleObjects(3, handles, FALSE, INFINITE);
|
||||
switch (waitret) {
|
||||
case WAIT_OBJECT_0:
|
||||
case WAIT_OBJECT_0+1:
|
||||
waitret2 = WaitForSingleObject(mutex, INFINITE);
|
||||
if (waitret2 == WAIT_OBJECT_0) {
|
||||
FillBuffer(WAIT_OBJECT_0 + 1 - waitret);
|
||||
ReleaseMutex(mutex);
|
||||
} else {
|
||||
if (MV_Printf)
|
||||
MV_Printf( "DirectSound fillDataThread: wfso err %d\n", (int32_t) waitret2);
|
||||
}
|
||||
break;
|
||||
case WAIT_OBJECT_0+2:
|
||||
// initprintf( "DirectSound fillDataThread: exiting\n");
|
||||
ExitThread(0);
|
||||
break;
|
||||
default:
|
||||
if (MV_Printf)
|
||||
MV_Printf( "DirectSound fillDataThread: wfmo err %d\n", (int32_t) waitret);
|
||||
break;
|
||||
HANDLE handles[MIXBUFFERPOSITIONS+1];
|
||||
|
||||
for (int i = 0; i < ARRAY_SSIZE(handles); i++)
|
||||
handles[i] = notifyPositions[i].hEventNotify;
|
||||
|
||||
do
|
||||
{
|
||||
DWORD const waitret = WaitForMultipleObjects(MIXBUFFERPOSITIONS, handles, FALSE, INFINITE);
|
||||
|
||||
if (waitret >= WAIT_OBJECT_0 && waitret < WAIT_OBJECT_0+MIXBUFFERPOSITIONS)
|
||||
{
|
||||
DWORD const waitret2 = WaitForSingleObject(mutex, INFINITE);
|
||||
|
||||
if (waitret2 == WAIT_OBJECT_0)
|
||||
{
|
||||
FillBuffer((waitret + MIXBUFFERPOSITIONS - 1 - WAIT_OBJECT_0) % MIXBUFFERPOSITIONS);
|
||||
ReleaseMutex(mutex);
|
||||
}
|
||||
else if (MV_Printf)
|
||||
MV_Printf("DirectSound fillDataThread: wfso err %d\n", (int32_t)waitret2);
|
||||
}
|
||||
} while (1);
|
||||
else
|
||||
{
|
||||
switch (waitret)
|
||||
{
|
||||
case WAIT_OBJECT_0 + MIXBUFFERPOSITIONS:
|
||||
ExitThread(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (MV_Printf)
|
||||
MV_Printf("DirectSound fillDataThread: wfmo err %d\n", (int32_t)waitret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void TeardownDSound(HRESULT err)
|
||||
{
|
||||
if (FAILED(err))
|
||||
{
|
||||
if (MV_Printf)
|
||||
MV_Printf("Dying error: %x\n", (uint32_t)err);
|
||||
}
|
||||
|
||||
if (lpdsnotify)
|
||||
IDirectSoundNotify_Release(lpdsnotify), lpdsnotify = NULL;
|
||||
|
||||
for (int i = 0; i < MIXBUFFERPOSITIONS + 1; i++)
|
||||
{
|
||||
if (notifyPositions[i].hEventNotify)
|
||||
CloseHandle(notifyPositions[i].hEventNotify);
|
||||
notifyPositions[i].hEventNotify = 0;
|
||||
}
|
||||
|
||||
if (mutex)
|
||||
CloseHandle(mutex), mutex = NULL;
|
||||
|
||||
if (lpdsbsec)
|
||||
IDirectSoundBuffer_Release(lpdsbsec), lpdsbsec = NULL;
|
||||
|
||||
if (lpdsbprimary)
|
||||
IDirectSoundBuffer_Release(lpdsbprimary), lpdsbprimary = NULL;
|
||||
|
||||
if (lpds)
|
||||
IDirectSound_Release(lpds), lpds = NULL;
|
||||
}
|
||||
|
||||
#define DIRECTSOUND_ERROR(err, code) \
|
||||
do \
|
||||
{ \
|
||||
TeardownDSound(err); \
|
||||
ErrorCode = code; \
|
||||
return DSErr_Error; \
|
||||
} while (0)
|
||||
|
||||
int32_t DirectSoundDrv_PCM_Init(int32_t *mixrate, int32_t *numchannels, void * initdata)
|
||||
{
|
||||
HRESULT err;
|
||||
DSBUFFERDESC bufdesc = {};
|
||||
WAVEFORMATEX wfex = {};
|
||||
|
||||
if (Initialised)
|
||||
DirectSoundDrv_PCM_Shutdown();
|
||||
|
||||
if (FAILED(err = DirectSoundCreate(0, &lpds, 0)))
|
||||
DIRECTSOUND_ERROR(err, DSErr_DirectSoundCreate);
|
||||
|
||||
if (FAILED(err = IDirectSound_SetCooperativeLevel(lpds, (HWND) initdata, DSSCL_PRIORITY)))
|
||||
DIRECTSOUND_ERROR(err, DSErr_SetCooperativeLevel);
|
||||
|
||||
bufdesc.dwSize = sizeof(DSBUFFERDESC);
|
||||
bufdesc.dwFlags = DSBCAPS_LOCSOFTWARE | DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS;
|
||||
|
||||
if (FAILED(err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbprimary, 0)))
|
||||
DIRECTSOUND_ERROR(err, DSErr_CreateSoundBuffer);
|
||||
|
||||
wfex.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfex.nChannels = *numchannels;
|
||||
wfex.nSamplesPerSec = *mixrate;
|
||||
wfex.wBitsPerSample = 16;
|
||||
wfex.nBlockAlign = wfex.nChannels * wfex.wBitsPerSample / 8;
|
||||
wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;
|
||||
|
||||
if (FAILED(err = IDirectSoundBuffer_SetFormat(lpdsbprimary, &wfex)))
|
||||
DIRECTSOUND_ERROR(err, DSErr_SetFormat);
|
||||
|
||||
bufdesc.dwFlags = DSBCAPS_LOCSOFTWARE | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS;
|
||||
|
||||
bufdesc.dwBufferBytes = wfex.nBlockAlign * 2048 * 2;
|
||||
bufdesc.lpwfxFormat = &wfex;
|
||||
|
||||
if (FAILED(err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbsec, 0)))
|
||||
DIRECTSOUND_ERROR(err, DSErr_CreateSoundBufferSecondary);
|
||||
|
||||
if (FAILED(err = IDirectSoundBuffer_QueryInterface(lpdsbsec, &IID_IDirectSoundNotify, (LPVOID *)&lpdsnotify)))
|
||||
DIRECTSOUND_ERROR(err, DSErr_Notify);
|
||||
|
||||
for (int i = 0; i < MIXBUFFERPOSITIONS; i++)
|
||||
{
|
||||
notifyPositions[i].dwOffset = (bufdesc.dwBufferBytes/MIXBUFFERPOSITIONS)*i;
|
||||
notifyPositions[i].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (!notifyPositions[i].hEventNotify)
|
||||
DIRECTSOUND_ERROR(DS_OK, DSErr_NotifyEvents);
|
||||
}
|
||||
|
||||
notifyPositions[MIXBUFFERPOSITIONS].dwOffset = DSBPN_OFFSETSTOP;
|
||||
notifyPositions[MIXBUFFERPOSITIONS].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
|
||||
if (FAILED(err = IDirectSoundNotify_SetNotificationPositions(lpdsnotify, MIXBUFFERPOSITIONS+1, notifyPositions)))
|
||||
DIRECTSOUND_ERROR(err, DSErr_SetNotificationPositions);
|
||||
|
||||
if (FAILED(err = IDirectSoundBuffer_Play(lpdsbprimary, 0, 0, DSBPLAY_LOOPING)))
|
||||
DIRECTSOUND_ERROR(err, DSErr_Play);
|
||||
|
||||
if ((mutex = CreateMutex(0, FALSE, 0)) == NULL)
|
||||
DIRECTSOUND_ERROR(DS_OK, DSErr_CreateMutex);
|
||||
|
||||
Initialised = 1;
|
||||
|
||||
return DSErr_Ok;
|
||||
}
|
||||
|
||||
#undef DIRECTSOUND_ERROR
|
||||
|
||||
void DirectSoundDrv_PCM_Shutdown(void)
|
||||
{
|
||||
if (!Initialised)
|
||||
return;
|
||||
|
||||
DirectSoundDrv_PCM_StopPlayback();
|
||||
TeardownDSound(DS_OK);
|
||||
|
||||
Initialised = 0;
|
||||
}
|
||||
|
||||
int32_t DirectSoundDrv_PCM_BeginPlayback(char *BufferStart, int32_t BufferSize, int32_t NumDivisions, void (*CallBackFunc)(void))
|
||||
{
|
||||
if (!Initialised)
|
||||
{
|
||||
ErrorCode = DSErr_Uninitialised;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
DirectSoundDrv_PCM_StopPlayback();
|
||||
|
||||
MixBuffer = BufferStart;
|
||||
MixBufferSize = BufferSize;
|
||||
MixBufferCount = NumDivisions;
|
||||
MixBufferCurrent = 0;
|
||||
MixBufferUsed = 0;
|
||||
MixCallBack = CallBackFunc;
|
||||
|
||||
// prime the buffer
|
||||
FillBuffer(0);
|
||||
|
||||
if ((mixThread = CreateThread(NULL, 0, fillDataThread, 0, 0, 0)) == NULL)
|
||||
{
|
||||
ErrorCode = DSErr_CreateThread;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
SetThreadPriority(mixThread, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
|
||||
HRESULT err = IDirectSoundBuffer_Play(lpdsbsec, 0, 0, DSBPLAY_LOOPING);
|
||||
|
||||
if (FAILED(err))
|
||||
{
|
||||
ErrorCode = DSErr_PlaySecondary;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
Playing = 1;
|
||||
|
||||
return DSErr_Ok;
|
||||
}
|
||||
|
||||
void DirectSoundDrv_PCM_StopPlayback(void)
|
||||
{
|
||||
if (!Playing)
|
||||
return;
|
||||
|
||||
IDirectSoundBuffer_Stop(lpdsbsec);
|
||||
IDirectSoundBuffer_SetCurrentPosition(lpdsbsec, 0);
|
||||
|
||||
Playing = 0;
|
||||
}
|
||||
|
||||
void DirectSoundDrv_PCM_Lock(void)
|
||||
{
|
||||
DWORD const err = WaitForSingleObject(mutex, INFINITE);
|
||||
|
||||
if (err != WAIT_OBJECT_0)
|
||||
{
|
||||
if (MV_Printf)
|
||||
MV_Printf("DirectSound lock: wfso %d\n", (int32_t)err);
|
||||
}
|
||||
}
|
||||
|
||||
void DirectSoundDrv_PCM_Unlock(void)
|
||||
{
|
||||
ReleaseMutex(mutex);
|
||||
}
|
||||
|
||||
int32_t DirectSoundDrv_GetError(void)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
const char *DirectSoundDrv_ErrorString( int32_t ErrorNumber )
|
||||
const char *DirectSoundDrv_ErrorString(int32_t ErrorNumber)
|
||||
{
|
||||
const char *ErrorString;
|
||||
|
||||
switch( ErrorNumber )
|
||||
switch (ErrorNumber)
|
||||
{
|
||||
case DSErr_Warning :
|
||||
case DSErr_Error :
|
||||
ErrorString = DirectSoundDrv_ErrorString( ErrorCode );
|
||||
break;
|
||||
case DSErr_Warning:
|
||||
case DSErr_Error:
|
||||
ErrorString = DirectSoundDrv_ErrorString(ErrorCode);
|
||||
break;
|
||||
|
||||
case DSErr_Ok :
|
||||
ErrorString = "DirectSound ok.";
|
||||
break;
|
||||
case DSErr_Ok:
|
||||
ErrorString = "DirectSound ok.";
|
||||
break;
|
||||
|
||||
case DSErr_Uninitialised:
|
||||
ErrorString = "DirectSound uninitialised.";
|
||||
|
@ -267,229 +441,4 @@ const char *DirectSoundDrv_ErrorString( int32_t ErrorNumber )
|
|||
}
|
||||
|
||||
return ErrorString;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void TeardownDSound(HRESULT err)
|
||||
{
|
||||
if (FAILED(err)) {
|
||||
if (MV_Printf)
|
||||
MV_Printf( "Dying error: %x\n", (uint32_t) err);
|
||||
}
|
||||
|
||||
if (lpdsnotify) IDirectSoundNotify_Release(lpdsnotify);
|
||||
if (notifyPositions[0].hEventNotify) CloseHandle(notifyPositions[0].hEventNotify);
|
||||
if (notifyPositions[1].hEventNotify) CloseHandle(notifyPositions[1].hEventNotify);
|
||||
if (notifyPositions[2].hEventNotify) CloseHandle(notifyPositions[2].hEventNotify);
|
||||
if (mutex) CloseHandle(mutex);
|
||||
if (lpdsbsec) IDirectSoundBuffer_Release(lpdsbsec);
|
||||
if (lpdsbprimary) IDirectSoundBuffer_Release(lpdsbprimary);
|
||||
if (lpds) IDirectSound_Release(lpds);
|
||||
notifyPositions[0].hEventNotify =
|
||||
notifyPositions[1].hEventNotify =
|
||||
notifyPositions[2].hEventNotify = 0;
|
||||
mutex = NULL;
|
||||
lpdsnotify = NULL;
|
||||
lpdsbsec = NULL;
|
||||
lpdsbprimary = NULL;
|
||||
lpds = NULL;
|
||||
}
|
||||
|
||||
int32_t DirectSoundDrv_PCM_Init(int32_t *mixrate, int32_t *numchannels, void * initdata)
|
||||
{
|
||||
HRESULT err;
|
||||
DSBUFFERDESC bufdesc;
|
||||
WAVEFORMATEX wfex;
|
||||
|
||||
if (Initialised) {
|
||||
DirectSoundDrv_PCM_Shutdown();
|
||||
}
|
||||
|
||||
err = DirectSoundCreate(0, &lpds, 0);
|
||||
if (FAILED( err )) {
|
||||
ErrorCode = DSErr_DirectSoundCreate;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
err = IDirectSound_SetCooperativeLevel(lpds, (HWND) initdata, DSSCL_PRIORITY);
|
||||
if (FAILED( err )) {
|
||||
TeardownDSound(err);
|
||||
ErrorCode = DSErr_SetCooperativeLevel;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
memset(&bufdesc, 0, sizeof(DSBUFFERDESC));
|
||||
bufdesc.dwSize = sizeof(DSBUFFERDESC);
|
||||
bufdesc.dwFlags = DSBCAPS_LOCSOFTWARE |
|
||||
DSBCAPS_PRIMARYBUFFER |
|
||||
DSBCAPS_GETCURRENTPOSITION2 |
|
||||
DSBCAPS_STICKYFOCUS ;
|
||||
|
||||
err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbprimary, 0);
|
||||
if (FAILED( err )) {
|
||||
TeardownDSound(err);
|
||||
ErrorCode = DSErr_CreateSoundBuffer;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
memset(&wfex, 0, sizeof(WAVEFORMATEX));
|
||||
wfex.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfex.nChannels = *numchannels;
|
||||
wfex.nSamplesPerSec = *mixrate;
|
||||
wfex.wBitsPerSample = 16;
|
||||
wfex.nBlockAlign = wfex.nChannels * wfex.wBitsPerSample / 8;
|
||||
wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;
|
||||
|
||||
err = IDirectSoundBuffer_SetFormat(lpdsbprimary, &wfex);
|
||||
if (FAILED( err )) {
|
||||
TeardownDSound(err);
|
||||
ErrorCode = DSErr_SetFormat;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
bufdesc.dwFlags = DSBCAPS_LOCSOFTWARE |
|
||||
DSBCAPS_CTRLPOSITIONNOTIFY |
|
||||
DSBCAPS_GETCURRENTPOSITION2 |
|
||||
DSBCAPS_STICKYFOCUS ;
|
||||
bufdesc.dwBufferBytes = wfex.nBlockAlign * 2560 * 2;
|
||||
bufdesc.lpwfxFormat = &wfex;
|
||||
|
||||
err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbsec, 0);
|
||||
if (FAILED( err )) {
|
||||
TeardownDSound(err);
|
||||
ErrorCode = DSErr_SetFormatSecondary;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
err = IDirectSoundBuffer_QueryInterface(lpdsbsec, &IID_IDirectSoundNotify,
|
||||
(LPVOID *) &lpdsnotify);
|
||||
if (FAILED( err )) {
|
||||
TeardownDSound(err);
|
||||
ErrorCode = DSErr_Notify;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
notifyPositions[0].dwOffset = 0;
|
||||
notifyPositions[0].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
notifyPositions[1].dwOffset = bufdesc.dwBufferBytes / 2;
|
||||
notifyPositions[1].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
notifyPositions[2].dwOffset = DSBPN_OFFSETSTOP;
|
||||
notifyPositions[2].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (!notifyPositions[0].hEventNotify ||
|
||||
!notifyPositions[1].hEventNotify ||
|
||||
!notifyPositions[2].hEventNotify) {
|
||||
TeardownDSound(DS_OK);
|
||||
ErrorCode = DSErr_NotifyEvents;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
err = IDirectSoundNotify_SetNotificationPositions(lpdsnotify, 3, notifyPositions);
|
||||
if (FAILED( err )) {
|
||||
TeardownDSound(err);
|
||||
ErrorCode = DSErr_SetNotificationPositions;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
err = IDirectSoundBuffer_Play(lpdsbprimary, 0, 0, DSBPLAY_LOOPING);
|
||||
if (FAILED( err )) {
|
||||
TeardownDSound(err);
|
||||
ErrorCode = DSErr_Play;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
mutex = CreateMutex(0, FALSE, 0);
|
||||
if (!mutex) {
|
||||
TeardownDSound(DS_OK);
|
||||
ErrorCode = DSErr_CreateMutex;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
Initialised = 1;
|
||||
|
||||
// initprintf("DirectSound Init: yay\n");
|
||||
|
||||
return DSErr_Ok;
|
||||
}
|
||||
|
||||
void DirectSoundDrv_PCM_Shutdown(void)
|
||||
{
|
||||
if (!Initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
DirectSoundDrv_PCM_StopPlayback();
|
||||
|
||||
TeardownDSound(DS_OK);
|
||||
|
||||
Initialised = 0;
|
||||
}
|
||||
|
||||
int32_t DirectSoundDrv_PCM_BeginPlayback(char *BufferStart, int32_t BufferSize,
|
||||
int32_t NumDivisions, void ( *CallBackFunc )( void ) )
|
||||
{
|
||||
HRESULT err;
|
||||
|
||||
if (!Initialised) {
|
||||
ErrorCode = DSErr_Uninitialised;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
DirectSoundDrv_PCM_StopPlayback();
|
||||
|
||||
MixBuffer = BufferStart;
|
||||
MixBufferSize = BufferSize;
|
||||
MixBufferCount = NumDivisions;
|
||||
MixBufferCurrent = 0;
|
||||
MixBufferUsed = 0;
|
||||
MixCallBack = CallBackFunc;
|
||||
|
||||
// prime the buffer
|
||||
FillBuffer(0);
|
||||
|
||||
mixThread = CreateThread(NULL, 0, fillDataThread, 0, 0, 0);
|
||||
if (!mixThread) {
|
||||
ErrorCode = DSErr_CreateThread;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
SetThreadPriority(mixThread, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
|
||||
err = IDirectSoundBuffer_Play(lpdsbsec, 0, 0, DSBPLAY_LOOPING);
|
||||
if (FAILED( err )) {
|
||||
ErrorCode = DSErr_PlaySecondary;
|
||||
return DSErr_Error;
|
||||
}
|
||||
|
||||
Playing = 1;
|
||||
|
||||
return DSErr_Ok;
|
||||
}
|
||||
|
||||
void DirectSoundDrv_PCM_StopPlayback(void)
|
||||
{
|
||||
if (!Playing) {
|
||||
return;
|
||||
}
|
||||
|
||||
IDirectSoundBuffer_Stop(lpdsbsec);
|
||||
IDirectSoundBuffer_SetCurrentPosition(lpdsbsec, 0);
|
||||
|
||||
Playing = 0;
|
||||
}
|
||||
|
||||
void DirectSoundDrv_PCM_Lock(void)
|
||||
{
|
||||
DWORD err;
|
||||
|
||||
err = WaitForSingleObject(mutex, INFINITE);
|
||||
if (err != WAIT_OBJECT_0) {
|
||||
if (MV_Printf)
|
||||
MV_Printf( "DirectSound lock: wfso %d\n", (int32_t) err);
|
||||
}
|
||||
}
|
||||
|
||||
void DirectSoundDrv_PCM_Unlock(void)
|
||||
{
|
||||
ReleaseMutex(mutex);
|
||||
}
|
||||
|
|
|
@ -20,12 +20,33 @@
|
|||
|
||||
#include "inttypes.h"
|
||||
|
||||
enum
|
||||
{
|
||||
DSErr_Warning = -2,
|
||||
DSErr_Error = -1,
|
||||
DSErr_Ok = 0,
|
||||
DSErr_Uninitialised,
|
||||
DSErr_DirectSoundCreate,
|
||||
DSErr_SetCooperativeLevel,
|
||||
DSErr_CreateSoundBuffer,
|
||||
DSErr_CreateSoundBufferSecondary,
|
||||
DSErr_SetFormat,
|
||||
DSErr_SetFormatSecondary,
|
||||
DSErr_Notify,
|
||||
DSErr_NotifyEvents,
|
||||
DSErr_SetNotificationPositions,
|
||||
DSErr_Play,
|
||||
DSErr_PlaySecondary,
|
||||
DSErr_CreateThread,
|
||||
DSErr_CreateMutex
|
||||
};
|
||||
|
||||
int32_t DirectSoundDrv_GetError(void);
|
||||
const char *DirectSoundDrv_ErrorString( int32_t ErrorNumber );
|
||||
int32_t DirectSoundDrv_PCM_Init(int32_t *mixrate, int32_t *numchannels, void * initdata);
|
||||
void DirectSoundDrv_PCM_Shutdown(void);
|
||||
int32_t DirectSoundDrv_PCM_BeginPlayback(char *BufferStart, int32_t BufferSize,
|
||||
int32_t NumDivisions, void ( *CallBackFunc )( void ) );
|
||||
void DirectSoundDrv_PCM_StopPlayback(void);
|
||||
void DirectSoundDrv_PCM_Lock(void);
|
||||
void DirectSoundDrv_PCM_Unlock(void);
|
||||
const char *DirectSoundDrv_ErrorString(int32_t ErrorNumber);
|
||||
|
||||
int32_t DirectSoundDrv_PCM_Init(int32_t *mixrate, int32_t *numchannels, void *initdata);
|
||||
int32_t DirectSoundDrv_PCM_BeginPlayback(char *BufferStart, int32_t BufferSize, int32_t NumDivisions, void (*CallBackFunc)(void));
|
||||
void DirectSoundDrv_PCM_StopPlayback(void);
|
||||
void DirectSoundDrv_PCM_Lock(void);
|
||||
void DirectSoundDrv_PCM_Unlock(void);
|
||||
void DirectSoundDrv_PCM_Shutdown(void);
|
||||
|
|
Loading…
Reference in a new issue