raze-gles/polymer/eduke32/source/jaudiolib/sdlout.c
2008-04-25 01:46:19 +00:00

275 lines
6.3 KiB
C

/*
* DirectSound output code for MultiVoc
* by Jonathon Fowler (jonof@edgenetwk.com)
*/
//-------------------------------------------------------------------------
/*
Duke Nukem Copyright (C) 1996, 2003 3D Realms Entertainment
This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
Duke Nukem 3D is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//-------------------------------------------------------------------------
#include "sdlout.h"
#include "sdl_inc.h"
#include <stdio.h>
#include <string.h>
#include "sdlayer.h"
#if defined(__WATCOMC__) || defined(_MSC_VER)
#include <malloc.h>
#endif
#ifndef RENDERTYPESDL
#error The SDL output module for AudioLib only works with the SDL interface.
#endif
static int(*_SDLSOUND_CallBack)(int) = NULL;
static int _SDLSOUND_BufferLength = 0;
static int _SDLSOUND_NumBuffers = 0;
static char *_SDLSOUND_MixBuffer = NULL;
static int SDLSOUND_Installed = FALSE;
int SDLSOUND_ErrorCode = SDLSOUND_Ok;
#define SDLSOUND_SetErrorCode( status ) \
SDLSOUND_ErrorCode = ( status );
static void isr(void *userdata, unsigned char *stream, int len);
/*
* DisableInterrupts
* Enter the critical section.
*/
int DisableInterrupts(void)
{
SDL_LockAudio();
return 0;
}
/*
* RestoreInterrupts
* Leave the critical section.
*/
int RestoreInterrupts(int a)
{
SDL_UnlockAudio();
return 0;
a=a;
}
/*
* SDLSOUND_ErrorString
* Returns a description of an error code.
*/
char *SDLSOUND_ErrorString(int errorcode)
{
switch (errorcode)
{
case SDLSOUND_Warning:
case SDLSOUND_Error:
return SDLSOUND_ErrorString(SDLSOUND_ErrorCode);
case SDLSOUND_Ok:
return "SDL Sound ok.";
default:
return "Unknown SDL sound error code.";
}
}
/*
* SDLSOUND_Init
* Initializes the SDL sound objects.
*/
int SDLSOUND_Init(int soundcard, int mixrate, int numchannels, int samplebits, int buffersize)
{
SDL_AudioSpec spec,got;
if (SDLSOUND_Installed)
{
SDLSOUND_Shutdown();
}
initprintf("Initializing SDL sound...\n");
initprintf(" - Requested sound format\n"
" Channels: %d\n"
" Sample rate: %dHz\n"
" Sample size: %d bits\n",
numchannels, mixrate, samplebits);
spec.freq = mixrate;
spec.format = (samplebits == 8 ? AUDIO_U8 : AUDIO_S16LSB);
spec.channels = (numchannels == 1 ? 1:2);
spec.samples = (buffersize >> (spec.channels-1)) >> (samplebits==16);
spec.callback = isr;
spec.userdata = NULL;
SDLSOUND_Installed = TRUE;
SDLSOUND_SetErrorCode(SDLSOUND_Ok);
return SDLSOUND_Ok;
}
/*
* SDLSOUND_Shutdown
* Shuts down SDL sound and it's associates.
*/
int SDLSOUND_Shutdown(void)
{
int i;
if (SDLSOUND_Installed) initprintf("Uninitializing SDL sound...\n");
SDLSOUND_Installed = FALSE;
SDLSOUND_StopPlayback();
SDLSOUND_SetErrorCode(SDLSOUND_Ok);
return SDLSOUND_Ok;
}
/*
* SDLSOUND_SetMixMode
* Bit of filler for the future.
*/
int SDLSOUND_SetMixMode(int mode)
{
return mode;
}
static void isr(void *userdata, unsigned char *stream, int len)
{
// otherwise we just service the interrupt
if (_DSOUND_CallBack)
{
p = _DSOUND_CallBack(rv-WAIT_OBJECT_0-1);
hr = IDirectSoundBuffer_Lock(lpDSBSecondary, p*_DSOUND_BufferLength, _DSOUND_BufferLength,
&lockptr, &lockbytes, &lockptr2, &lockbytes2, 0);
if (hr == DSERR_BUFFERLOST)
{
hr = IDirectSoundBuffer_Restore(lpDSBSecondary);
}
if (hr == DS_OK)
{
/*
#define copybuf(S,D,c) \
({ void *__S=(S), *__D=(D); int __c=(c); \
__asm__ __volatile__ ("rep; movsl" \
: "+S" (__S), "+D" (__D), "+c" (__c) : : "memory", "cc"); \
0; })
*/
//copybuf(_DSOUND_MixBuffer + p * _DSOUND_BufferLength, lockptr, _DSOUND_BufferLength >> 2);
memcpy(lockptr, _DSOUND_MixBuffer + p * _DSOUND_BufferLength, _DSOUND_BufferLength);
IDirectSoundBuffer_Unlock(lpDSBSecondary, lockptr, lockbytes, lockptr2, lockbytes2);
}
}
}
}
/*
* SDLSOUND_BeginBufferedPlayback
* Unpause SDL sound playback.
*/
int DSOUND_BeginBufferedPlayback(char *BufferStart, int(*CallBackFunc)(int), int buffersize, int numdivisions)
{
_SDLSOUND_CallBack = CallBackFunc;
_SDLSOUND_MixBuffer = BufferStart;
_SDLSOUND_BufferLength = buffersize/numdivisions;
_SDLSOUND_NumBuffers = numdivisions;
return SDLSOUND_Ok;
}
/*
* DSOUND_StopPlayback
* Halts the playback thread.
*/
int DSOUND_StopPlayback(void)
{
// DWORD exitcode;
BOOL t;
int i;
if (isrthread)
{
SetEvent(isrfinish);
initprintf("DirectSound: Waiting for sound thread to exit\n");
if (WaitForSingleObject(isrthread, 300) == WAIT_OBJECT_0)
initprintf("DirectSound: Sound thread has exited\n");
else
initprintf("DirectSound: Sound thread failed to exit!\n");
/*
while (1) {
if (!GetExitCodeThread(isrthread, &exitcode)) {
DSOUND_SetErrorCode(DSOUND_FailedGetExitCode);
return DSOUND_Warning;
}
if (exitcode != STILL_ACTIVE) break;
}*/
CloseHandle(isrthread);
isrthread = NULL;
}
if (isrfinish)
{
CloseHandle(isrfinish);
isrfinish = NULL;
}
if (lpDSBSecondary)
{
IDirectSoundBuffer_Stop(lpDSBSecondary);
}
if (hPosNotify)
{
for (i=0; i<_DSOUND_NumBuffers; i++)
{
if (hPosNotify[i]) CloseHandle(hPosNotify[i]);
}
free(hPosNotify);
hPosNotify = NULL;
}
return DSOUND_Ok;
}