mirror of
https://github.com/UberGames/ioef.git
synced 2024-11-24 05:01:40 +00:00
* OpenAL support, from BlackAura aka Stuart Dalton <badcdev@gmail.com>
+ An abstract codec system, simplifying support for new formats + Changes versus BlackAura's patch: o Consolidated the OpenAL parts into one file o Changed the function naming scheme to more closely resemble Q3 o Changed the interface to fall back on the "base" sound system if loading OpenAL fails + This is enabled on Linux and MinGW for now, but should work on the other *nixs with appropriate additions to the Makefile + NOT enabled on OS X or MSVC Windows builds + Probably breaks the Windows build again * Retabulated sdl_snd.c and made the messages less verbose since there do not seem to be many having problems with SDL sound now
This commit is contained in:
parent
79ceef93cc
commit
84c4f21082
14 changed files with 3813 additions and 703 deletions
344
code/client/qal.c
Normal file
344
code/client/qal.c
Normal file
|
@ -0,0 +1,344 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Dynamically loads OpenAL
|
||||||
|
|
||||||
|
#if USE_OPENAL
|
||||||
|
|
||||||
|
#include "qal.h"
|
||||||
|
|
||||||
|
#if defined _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#define OBJTYPE HMODULE
|
||||||
|
#define OBJLOAD(x) LoadLibrary(x)
|
||||||
|
#define SYMLOAD(x,y) GetProcAddress(x,y)
|
||||||
|
#define OBJFREE(x) FreeLibrary(x)
|
||||||
|
|
||||||
|
#elif defined __linux__ || defined __FreeBSD__
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#define OBJTYPE void *
|
||||||
|
#define OBJLOAD(x) dlopen(x, RTLD_LAZY | RTLD_GLOBAL)
|
||||||
|
#define SYMLOAD(x,y) dlsym(x,y)
|
||||||
|
#define OBJFREE(x) dlclose(x)
|
||||||
|
#else
|
||||||
|
|
||||||
|
#error "Your platform has no lib loading code or it is disabled"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LPALENABLE qalEnable;
|
||||||
|
LPALDISABLE qalDisable;
|
||||||
|
LPALISENABLED qalIsEnabled;
|
||||||
|
LPALGETSTRING qalGetString;
|
||||||
|
LPALGETBOOLEANV qalGetBooleanv;
|
||||||
|
LPALGETINTEGERV qalGetIntegerv;
|
||||||
|
LPALGETFLOATV qalGetFloatv;
|
||||||
|
LPALGETDOUBLEV qalGetDoublev;
|
||||||
|
LPALGETBOOLEAN qalGetBoolean;
|
||||||
|
LPALGETINTEGER qalGetInteger;
|
||||||
|
LPALGETFLOAT qalGetFloat;
|
||||||
|
LPALGETDOUBLE qalGetDouble;
|
||||||
|
LPALGETERROR qalGetError;
|
||||||
|
LPALISEXTENSIONPRESENT qalIsExtensionPresent;
|
||||||
|
LPALGETPROCADDRESS qalGetProcAddress;
|
||||||
|
LPALGETENUMVALUE qalGetEnumValue;
|
||||||
|
LPALLISTENERF qalListenerf;
|
||||||
|
LPALLISTENER3F qalListener3f;
|
||||||
|
LPALLISTENERFV qalListenerfv;
|
||||||
|
LPALLISTENERI qalListeneri;
|
||||||
|
LPALGETLISTENERF qalGetListenerf;
|
||||||
|
LPALGETLISTENER3F qalGetListener3f;
|
||||||
|
LPALGETLISTENERFV qalGetListenerfv;
|
||||||
|
LPALGETLISTENERI qalGetListeneri;
|
||||||
|
LPALGENSOURCES qalGenSources;
|
||||||
|
LPALDELETESOURCES qalDeleteSources;
|
||||||
|
LPALISSOURCE qalIsSource;
|
||||||
|
LPALSOURCEF qalSourcef;
|
||||||
|
LPALSOURCE3F qalSource3f;
|
||||||
|
LPALSOURCEFV qalSourcefv;
|
||||||
|
LPALSOURCEI qalSourcei;
|
||||||
|
LPALGETSOURCEF qalGetSourcef;
|
||||||
|
LPALGETSOURCE3F qalGetSource3f;
|
||||||
|
LPALGETSOURCEFV qalGetSourcefv;
|
||||||
|
LPALGETSOURCEI qalGetSourcei;
|
||||||
|
LPALSOURCEPLAYV qalSourcePlayv;
|
||||||
|
LPALSOURCESTOPV qalSourceStopv;
|
||||||
|
LPALSOURCEREWINDV qalSourceRewindv;
|
||||||
|
LPALSOURCEPAUSEV qalSourcePausev;
|
||||||
|
LPALSOURCEPLAY qalSourcePlay;
|
||||||
|
LPALSOURCESTOP qalSourceStop;
|
||||||
|
LPALSOURCEREWIND qalSourceRewind;
|
||||||
|
LPALSOURCEPAUSE qalSourcePause;
|
||||||
|
LPALSOURCEQUEUEBUFFERS qalSourceQueueBuffers;
|
||||||
|
LPALSOURCEUNQUEUEBUFFERS qalSourceUnqueueBuffers;
|
||||||
|
LPALGENBUFFERS qalGenBuffers;
|
||||||
|
LPALDELETEBUFFERS qalDeleteBuffers;
|
||||||
|
LPALISBUFFER qalIsBuffer;
|
||||||
|
LPALBUFFERDATA qalBufferData;
|
||||||
|
LPALGETBUFFERF qalGetBufferf;
|
||||||
|
LPALGETBUFFERI qalGetBufferi;
|
||||||
|
LPALDOPPLERFACTOR qalDopplerFactor;
|
||||||
|
LPALDOPPLERVELOCITY qalDopplerVelocity;
|
||||||
|
LPALDISTANCEMODEL qalDistanceModel;
|
||||||
|
|
||||||
|
LPALCCREATECONTEXT qalcCreateContext;
|
||||||
|
LPALCMAKECONTEXTCURRENT qalcMakeContextCurrent;
|
||||||
|
LPALCPROCESSCONTEXT qalcProcessContext;
|
||||||
|
LPALCSUSPENDCONTEXT qalcSuspendContext;
|
||||||
|
LPALCDESTROYCONTEXT qalcDestroyContext;
|
||||||
|
LPALCGETCURRENTCONTEXT qalcGetCurrentContext;
|
||||||
|
LPALCGETCONTEXTSDEVICE qalcGetContextsDevice;
|
||||||
|
LPALCOPENDEVICE qalcOpenDevice;
|
||||||
|
LPALCCLOSEDEVICE qalcCloseDevice;
|
||||||
|
LPALCGETERROR qalcGetError;
|
||||||
|
LPALCISEXTENSIONPRESENT qalcIsExtensionPresent;
|
||||||
|
LPALCGETPROCADDRESS qalcGetProcAddress;
|
||||||
|
LPALCGETENUMVALUE qalcGetEnumValue;
|
||||||
|
LPALCGETSTRING qalcGetString;
|
||||||
|
LPALCGETINTEGERV qalcGetIntegerv;
|
||||||
|
|
||||||
|
static OBJTYPE OpenALLib = NULL;
|
||||||
|
|
||||||
|
static qboolean alinit_fail = qfalse;
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GPA
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static void *GPA(char *str)
|
||||||
|
{
|
||||||
|
void *rv;
|
||||||
|
|
||||||
|
rv = SYMLOAD(OpenALLib, str);
|
||||||
|
if(!rv)
|
||||||
|
{
|
||||||
|
Com_Printf( " Can't load symbol %s\n", str);
|
||||||
|
alinit_fail = qtrue;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Com_DPrintf( " Loaded symbol %s (0x%08X)\n", str, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
QAL_Init
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
qboolean QAL_Init(const char *libname)
|
||||||
|
{
|
||||||
|
if(OpenALLib)
|
||||||
|
return qtrue;
|
||||||
|
|
||||||
|
Com_Printf( "Loading \"%s\"...\n", libname);
|
||||||
|
if( (OpenALLib = OBJLOAD(libname)) == 0 )
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return qfalse;
|
||||||
|
#else
|
||||||
|
char fn[1024];
|
||||||
|
getcwd(fn, sizeof(fn));
|
||||||
|
strncat(fn, "/", sizeof(fn));
|
||||||
|
strncat(fn, libname, sizeof(fn));
|
||||||
|
|
||||||
|
if( (OpenALLib = OBJLOAD(fn)) == 0 )
|
||||||
|
{
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
alinit_fail = qfalse;
|
||||||
|
|
||||||
|
qalEnable = GPA("alEnable");
|
||||||
|
qalDisable = GPA("alDisable");
|
||||||
|
qalIsEnabled = GPA("alIsEnabled");
|
||||||
|
qalGetString = GPA("alGetString");
|
||||||
|
qalGetBooleanv = GPA("alGetBooleanv");
|
||||||
|
qalGetIntegerv = GPA("alGetIntegerv");
|
||||||
|
qalGetFloatv = GPA("alGetFloatv");
|
||||||
|
qalGetDoublev = GPA("alGetDoublev");
|
||||||
|
qalGetBoolean = GPA("alGetBoolean");
|
||||||
|
qalGetInteger = GPA("alGetInteger");
|
||||||
|
qalGetFloat = GPA("alGetFloat");
|
||||||
|
qalGetDouble = GPA("alGetDouble");
|
||||||
|
qalGetError = GPA("alGetError");
|
||||||
|
qalIsExtensionPresent = GPA("alIsExtensionPresent");
|
||||||
|
qalGetProcAddress = GPA("alGetProcAddress");
|
||||||
|
qalGetEnumValue = GPA("alGetEnumValue");
|
||||||
|
qalListenerf = GPA("alListenerf");
|
||||||
|
qalListener3f = GPA("alListener3f");
|
||||||
|
qalListenerfv = GPA("alListenerfv");
|
||||||
|
qalListeneri = GPA("alListeneri");
|
||||||
|
qalGetListenerf = GPA("alGetListenerf");
|
||||||
|
qalGetListener3f = GPA("alGetListener3f");
|
||||||
|
qalGetListenerfv = GPA("alGetListenerfv");
|
||||||
|
qalGetListeneri = GPA("alGetListeneri");
|
||||||
|
qalGenSources = GPA("alGenSources");
|
||||||
|
qalDeleteSources = GPA("alDeleteSources");
|
||||||
|
qalIsSource = GPA("alIsSource");
|
||||||
|
qalSourcef = GPA("alSourcef");
|
||||||
|
qalSource3f = GPA("alSource3f");
|
||||||
|
qalSourcefv = GPA("alSourcefv");
|
||||||
|
qalSourcei = GPA("alSourcei");
|
||||||
|
qalGetSourcef = GPA("alGetSourcef");
|
||||||
|
qalGetSource3f = GPA("alGetSource3f");
|
||||||
|
qalGetSourcefv = GPA("alGetSourcefv");
|
||||||
|
qalGetSourcei = GPA("alGetSourcei");
|
||||||
|
qalSourcePlayv = GPA("alSourcePlayv");
|
||||||
|
qalSourceStopv = GPA("alSourceStopv");
|
||||||
|
qalSourceRewindv = GPA("alSourceRewindv");
|
||||||
|
qalSourcePausev = GPA("alSourcePausev");
|
||||||
|
qalSourcePlay = GPA("alSourcePlay");
|
||||||
|
qalSourceStop = GPA("alSourceStop");
|
||||||
|
qalSourceRewind = GPA("alSourceRewind");
|
||||||
|
qalSourcePause = GPA("alSourcePause");
|
||||||
|
qalSourceQueueBuffers = GPA("alSourceQueueBuffers");
|
||||||
|
qalSourceUnqueueBuffers = GPA("alSourceUnqueueBuffers");
|
||||||
|
qalGenBuffers = GPA("alGenBuffers");
|
||||||
|
qalDeleteBuffers = GPA("alDeleteBuffers");
|
||||||
|
qalIsBuffer = GPA("alIsBuffer");
|
||||||
|
qalBufferData = GPA("alBufferData");
|
||||||
|
qalGetBufferf = GPA("alGetBufferf");
|
||||||
|
qalGetBufferi = GPA("alGetBufferi");
|
||||||
|
qalDopplerFactor = GPA("alDopplerFactor");
|
||||||
|
qalDopplerVelocity = GPA("alDopplerVelocity");
|
||||||
|
qalDistanceModel = GPA("alDistanceModel");
|
||||||
|
|
||||||
|
qalcCreateContext = GPA("alcCreateContext");
|
||||||
|
qalcMakeContextCurrent = GPA("alcMakeContextCurrent");
|
||||||
|
qalcProcessContext = GPA("alcProcessContext");
|
||||||
|
qalcSuspendContext = GPA("alcSuspendContext");
|
||||||
|
qalcDestroyContext = GPA("alcDestroyContext");
|
||||||
|
qalcGetCurrentContext = GPA("alcGetCurrentContext");
|
||||||
|
qalcGetContextsDevice = GPA("alcGetContextsDevice");
|
||||||
|
qalcOpenDevice = GPA("alcOpenDevice");
|
||||||
|
qalcCloseDevice = GPA("alcCloseDevice");
|
||||||
|
qalcGetError = GPA("alcGetError");
|
||||||
|
qalcIsExtensionPresent = GPA("alcIsExtensionPresent");
|
||||||
|
qalcGetProcAddress = GPA("alcGetProcAddress");
|
||||||
|
qalcGetEnumValue = GPA("alcGetEnumValue");
|
||||||
|
qalcGetString = GPA("alcGetString");
|
||||||
|
qalcGetIntegerv = GPA("alcGetIntegerv");
|
||||||
|
|
||||||
|
if(alinit_fail)
|
||||||
|
{
|
||||||
|
QAL_Shutdown();
|
||||||
|
Com_Printf( " One or more symbols not found\n");
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
QAL_Shutdown
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void QAL_Shutdown( void )
|
||||||
|
{
|
||||||
|
if(OpenALLib)
|
||||||
|
{
|
||||||
|
OBJFREE(OpenALLib);
|
||||||
|
OpenALLib = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
qalEnable = NULL;
|
||||||
|
qalDisable = NULL;
|
||||||
|
qalIsEnabled = NULL;
|
||||||
|
qalGetString = NULL;
|
||||||
|
qalGetBooleanv = NULL;
|
||||||
|
qalGetIntegerv = NULL;
|
||||||
|
qalGetFloatv = NULL;
|
||||||
|
qalGetDoublev = NULL;
|
||||||
|
qalGetBoolean = NULL;
|
||||||
|
qalGetInteger = NULL;
|
||||||
|
qalGetFloat = NULL;
|
||||||
|
qalGetDouble = NULL;
|
||||||
|
qalGetError = NULL;
|
||||||
|
qalIsExtensionPresent = NULL;
|
||||||
|
qalGetProcAddress = NULL;
|
||||||
|
qalGetEnumValue = NULL;
|
||||||
|
qalListenerf = NULL;
|
||||||
|
qalListener3f = NULL;
|
||||||
|
qalListenerfv = NULL;
|
||||||
|
qalListeneri = NULL;
|
||||||
|
qalGetListenerf = NULL;
|
||||||
|
qalGetListener3f = NULL;
|
||||||
|
qalGetListenerfv = NULL;
|
||||||
|
qalGetListeneri = NULL;
|
||||||
|
qalGenSources = NULL;
|
||||||
|
qalDeleteSources = NULL;
|
||||||
|
qalIsSource = NULL;
|
||||||
|
qalSourcef = NULL;
|
||||||
|
qalSource3f = NULL;
|
||||||
|
qalSourcefv = NULL;
|
||||||
|
qalSourcei = NULL;
|
||||||
|
qalGetSourcef = NULL;
|
||||||
|
qalGetSource3f = NULL;
|
||||||
|
qalGetSourcefv = NULL;
|
||||||
|
qalGetSourcei = NULL;
|
||||||
|
qalSourcePlayv = NULL;
|
||||||
|
qalSourceStopv = NULL;
|
||||||
|
qalSourceRewindv = NULL;
|
||||||
|
qalSourcePausev = NULL;
|
||||||
|
qalSourcePlay = NULL;
|
||||||
|
qalSourceStop = NULL;
|
||||||
|
qalSourceRewind = NULL;
|
||||||
|
qalSourcePause = NULL;
|
||||||
|
qalSourceQueueBuffers = NULL;
|
||||||
|
qalSourceUnqueueBuffers = NULL;
|
||||||
|
qalGenBuffers = NULL;
|
||||||
|
qalDeleteBuffers = NULL;
|
||||||
|
qalIsBuffer = NULL;
|
||||||
|
qalBufferData = NULL;
|
||||||
|
qalGetBufferf = NULL;
|
||||||
|
qalGetBufferi = NULL;
|
||||||
|
qalDopplerFactor = NULL;
|
||||||
|
qalDopplerVelocity = NULL;
|
||||||
|
qalDistanceModel = NULL;
|
||||||
|
|
||||||
|
qalcCreateContext = NULL;
|
||||||
|
qalcMakeContextCurrent = NULL;
|
||||||
|
qalcProcessContext = NULL;
|
||||||
|
qalcSuspendContext = NULL;
|
||||||
|
qalcDestroyContext = NULL;
|
||||||
|
qalcGetCurrentContext = NULL;
|
||||||
|
qalcGetContextsDevice = NULL;
|
||||||
|
qalcOpenDevice = NULL;
|
||||||
|
qalcCloseDevice = NULL;
|
||||||
|
qalcGetError = NULL;
|
||||||
|
qalcIsExtensionPresent = NULL;
|
||||||
|
qalcGetProcAddress = NULL;
|
||||||
|
qalcGetEnumValue = NULL;
|
||||||
|
qalcGetString = NULL;
|
||||||
|
qalcGetIntegerv = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
134
code/client/qal.h
Normal file
134
code/client/qal.h
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __QAL_H__
|
||||||
|
#define __QAL_H__
|
||||||
|
|
||||||
|
#include "../qcommon/q_shared.h"
|
||||||
|
#include "../qcommon/qcommon.h"
|
||||||
|
|
||||||
|
#define AL_NO_PROTOTYPES
|
||||||
|
#define ALC_NO_PROTOTYPES
|
||||||
|
#include <AL/al.h>
|
||||||
|
#include <AL/alc.h>
|
||||||
|
|
||||||
|
extern LPALENABLE qalEnable;
|
||||||
|
extern LPALDISABLE qalDisable;
|
||||||
|
extern LPALISENABLED qalIsEnabled;
|
||||||
|
extern LPALGETSTRING qalGetString;
|
||||||
|
extern LPALGETBOOLEANV qalGetBooleanv;
|
||||||
|
extern LPALGETINTEGERV qalGetIntegerv;
|
||||||
|
extern LPALGETFLOATV qalGetFloatv;
|
||||||
|
extern LPALGETDOUBLEV qalGetDoublev;
|
||||||
|
extern LPALGETBOOLEAN qalGetBoolean;
|
||||||
|
extern LPALGETINTEGER qalGetInteger;
|
||||||
|
extern LPALGETFLOAT qalGetFloat;
|
||||||
|
extern LPALGETDOUBLE qalGetDouble;
|
||||||
|
extern LPALGETERROR qalGetError;
|
||||||
|
extern LPALISEXTENSIONPRESENT qalIsExtensionPresent;
|
||||||
|
extern LPALGETPROCADDRESS qalGetProcAddress;
|
||||||
|
extern LPALGETENUMVALUE qalGetEnumValue;
|
||||||
|
extern LPALLISTENERF qalListenerf;
|
||||||
|
extern LPALLISTENER3F qalListener3f;
|
||||||
|
extern LPALLISTENERFV qalListenerfv;
|
||||||
|
extern LPALLISTENERI qalListeneri;
|
||||||
|
extern LPALLISTENER3I qalListener3i;
|
||||||
|
extern LPALLISTENERIV qalListeneriv;
|
||||||
|
extern LPALGETLISTENERF qalGetListenerf;
|
||||||
|
extern LPALGETLISTENER3F qalGetListener3f;
|
||||||
|
extern LPALGETLISTENERFV qalGetListenerfv;
|
||||||
|
extern LPALGETLISTENERI qalGetListeneri;
|
||||||
|
extern LPALGETLISTENER3I qalGetListener3i;
|
||||||
|
extern LPALGETLISTENERIV qalGetListeneriv;
|
||||||
|
extern LPALGENSOURCES qalGenSources;
|
||||||
|
extern LPALDELETESOURCES qalDeleteSources;
|
||||||
|
extern LPALISSOURCE qalIsSource;
|
||||||
|
extern LPALSOURCEF qalSourcef;
|
||||||
|
extern LPALSOURCE3F qalSource3f;
|
||||||
|
extern LPALSOURCEFV qalSourcefv;
|
||||||
|
extern LPALSOURCEI qalSourcei;
|
||||||
|
extern LPALSOURCE3I qalSource3i;
|
||||||
|
extern LPALSOURCEIV qalSourceiv;
|
||||||
|
extern LPALGETSOURCEF qalGetSourcef;
|
||||||
|
extern LPALGETSOURCE3F qalGetSource3f;
|
||||||
|
extern LPALGETSOURCEFV qalGetSourcefv;
|
||||||
|
extern LPALGETSOURCEI qalGetSourcei;
|
||||||
|
extern LPALGETSOURCE3I qalGetSource3i;
|
||||||
|
extern LPALGETSOURCEIV qalGetSourceiv;
|
||||||
|
extern LPALSOURCEPLAYV qalSourcePlayv;
|
||||||
|
extern LPALSOURCESTOPV qalSourceStopv;
|
||||||
|
extern LPALSOURCEREWINDV qalSourceRewindv;
|
||||||
|
extern LPALSOURCEPAUSEV qalSourcePausev;
|
||||||
|
extern LPALSOURCEPLAY qalSourcePlay;
|
||||||
|
extern LPALSOURCESTOP qalSourceStop;
|
||||||
|
extern LPALSOURCEREWIND qalSourceRewind;
|
||||||
|
extern LPALSOURCEPAUSE qalSourcePause;
|
||||||
|
extern LPALSOURCEQUEUEBUFFERS qalSourceQueueBuffers;
|
||||||
|
extern LPALSOURCEUNQUEUEBUFFERS qalSourceUnqueueBuffers;
|
||||||
|
extern LPALGENBUFFERS qalGenBuffers;
|
||||||
|
extern LPALDELETEBUFFERS qalDeleteBuffers;
|
||||||
|
extern LPALISBUFFER qalIsBuffer;
|
||||||
|
extern LPALBUFFERDATA qalBufferData;
|
||||||
|
extern LPALBUFFERF qalBufferf;
|
||||||
|
extern LPALBUFFER3F qalBuffer3f;
|
||||||
|
extern LPALBUFFERFV qalBufferfv;
|
||||||
|
extern LPALBUFFERF qalBufferi;
|
||||||
|
extern LPALBUFFER3F qalBuffer3i;
|
||||||
|
extern LPALBUFFERFV qalBufferiv;
|
||||||
|
extern LPALGETBUFFERF qalGetBufferf;
|
||||||
|
extern LPALGETBUFFER3F qalGetBuffer3f;
|
||||||
|
extern LPALGETBUFFERFV qalGetBufferfv;
|
||||||
|
extern LPALGETBUFFERI qalGetBufferi;
|
||||||
|
extern LPALGETBUFFER3I qalGetBuffer3i;
|
||||||
|
extern LPALGETBUFFERIV qalGetBufferiv;
|
||||||
|
extern LPALDOPPLERFACTOR qalDopplerFactor;
|
||||||
|
extern LPALDOPPLERVELOCITY qalDopplerVelocity;
|
||||||
|
extern LPALSPEEDOFSOUND qalSpeedOfSound;
|
||||||
|
extern LPALDISTANCEMODEL qalDistanceModel;
|
||||||
|
|
||||||
|
extern LPALCCREATECONTEXT qalcCreateContext;
|
||||||
|
extern LPALCMAKECONTEXTCURRENT qalcMakeContextCurrent;
|
||||||
|
extern LPALCPROCESSCONTEXT qalcProcessContext;
|
||||||
|
extern LPALCSUSPENDCONTEXT qalcSuspendContext;
|
||||||
|
extern LPALCDESTROYCONTEXT qalcDestroyContext;
|
||||||
|
extern LPALCGETCURRENTCONTEXT qalcGetCurrentContext;
|
||||||
|
extern LPALCGETCONTEXTSDEVICE qalcGetContextsDevice;
|
||||||
|
extern LPALCOPENDEVICE qalcOpenDevice;
|
||||||
|
extern LPALCCLOSEDEVICE qalcCloseDevice;
|
||||||
|
extern LPALCGETERROR qalcGetError;
|
||||||
|
extern LPALCISEXTENSIONPRESENT qalcIsExtensionPresent;
|
||||||
|
extern LPALCGETPROCADDRESS qalcGetProcAddress;
|
||||||
|
extern LPALCGETENUMVALUE qalcGetEnumValue;
|
||||||
|
extern LPALCGETSTRING qalcGetString;
|
||||||
|
extern LPALCGETINTEGERV qalcGetIntegerv;
|
||||||
|
extern LPALCCAPTUREOPENDEVICE qalcCaptureOpenDevice;
|
||||||
|
extern LPALCCAPTURECLOSEDEVICE qalcCaptureCloseDevice;
|
||||||
|
extern LPALCCAPTURESTART qalcCaptureStart;
|
||||||
|
extern LPALCCAPTURESTOP qalcCaptureStop;
|
||||||
|
extern LPALCCAPTURESAMPLES qalcCaptureSamples;
|
||||||
|
|
||||||
|
qboolean QAL_Init(const char *libname);
|
||||||
|
void QAL_Shutdown( void );
|
||||||
|
|
||||||
|
#endif // __QAL_H__
|
226
code/client/snd_codec.c
Normal file
226
code/client/snd_codec.c
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "client.h"
|
||||||
|
#include "snd_codec.h"
|
||||||
|
|
||||||
|
static snd_codec_t *codecs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_FileExtension
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static char *S_FileExtension(const char *fni)
|
||||||
|
{
|
||||||
|
char *fn = (char *)fni;
|
||||||
|
char *eptr = NULL;
|
||||||
|
while(*fn)
|
||||||
|
{
|
||||||
|
if(*fn == '.')
|
||||||
|
eptr = fn;
|
||||||
|
fn++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_FindCodecForFile
|
||||||
|
|
||||||
|
Select an appropriate codec for a file based on its extension
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static snd_codec_t *S_FindCodecForFile(const char *filename)
|
||||||
|
{
|
||||||
|
char *ext = S_FileExtension(filename);
|
||||||
|
snd_codec_t *codec = codecs;
|
||||||
|
|
||||||
|
if(!ext)
|
||||||
|
{
|
||||||
|
// No extension - auto-detect
|
||||||
|
while(codec)
|
||||||
|
{
|
||||||
|
char fn[MAX_QPATH];
|
||||||
|
Q_strncpyz(fn, filename, sizeof(fn) - 4);
|
||||||
|
COM_DefaultExtension(fn, sizeof(fn), codec->ext);
|
||||||
|
|
||||||
|
// Check it exists
|
||||||
|
if(FS_ReadFile(fn, NULL) != -1)
|
||||||
|
return codec;
|
||||||
|
|
||||||
|
// Nope. Next!
|
||||||
|
codec = codec->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothin'
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(codec)
|
||||||
|
{
|
||||||
|
if(!Q_stricmp(ext, codec->ext))
|
||||||
|
return codec;
|
||||||
|
codec = codec->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_CodecInit
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_CodecInit()
|
||||||
|
{
|
||||||
|
codecs = NULL;
|
||||||
|
S_CodecRegister(&wav_codec);
|
||||||
|
#ifdef USE_CODEC_VORBIS
|
||||||
|
S_CodecRegister(&ogg_codec);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_CodecShutdown
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_CodecShutdown()
|
||||||
|
{
|
||||||
|
codecs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_CodecRegister
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_CodecRegister(snd_codec_t *codec)
|
||||||
|
{
|
||||||
|
codec->next = codecs;
|
||||||
|
codecs = codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_CodecLoad
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void *S_CodecLoad(const char *filename, snd_info_t *info)
|
||||||
|
{
|
||||||
|
snd_codec_t *codec;
|
||||||
|
char fn[MAX_QPATH];
|
||||||
|
|
||||||
|
codec = S_FindCodecForFile(filename);
|
||||||
|
if(!codec)
|
||||||
|
{
|
||||||
|
Com_Printf("Unknown extension for %s\n", filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(fn, filename, sizeof(fn));
|
||||||
|
COM_DefaultExtension(fn, sizeof(fn), codec->ext);
|
||||||
|
|
||||||
|
return codec->load(fn, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_CodecOpenStream
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
snd_stream_t *S_CodecOpenStream(const char *filename)
|
||||||
|
{
|
||||||
|
snd_codec_t *codec;
|
||||||
|
char fn[MAX_QPATH];
|
||||||
|
|
||||||
|
codec = S_FindCodecForFile(filename);
|
||||||
|
if(!codec)
|
||||||
|
{
|
||||||
|
Com_Printf("Unknown extension for %s\n", filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(fn, filename, sizeof(fn));
|
||||||
|
COM_DefaultExtension(fn, sizeof(fn), codec->ext);
|
||||||
|
|
||||||
|
return codec->open(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void S_CodecCloseStream(snd_stream_t *stream)
|
||||||
|
{
|
||||||
|
stream->codec->close(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
int S_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
|
||||||
|
{
|
||||||
|
return stream->codec->read(stream, bytes, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
// Util functions (used by codecs)
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_CodecUtilOpen
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
snd_stream_t *S_CodecUtilOpen(const char *filename, snd_codec_t *codec)
|
||||||
|
{
|
||||||
|
snd_stream_t *stream;
|
||||||
|
fileHandle_t hnd;
|
||||||
|
|
||||||
|
// Try to open the file
|
||||||
|
FS_FOpenFileRead(filename, &hnd, qtrue);
|
||||||
|
if(!hnd)
|
||||||
|
{
|
||||||
|
Com_Printf("Can't read sound file %s\n", filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a stream
|
||||||
|
stream = Z_Malloc(sizeof(snd_stream_t));
|
||||||
|
if(!stream)
|
||||||
|
{
|
||||||
|
FS_FCloseFile(hnd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy over, return
|
||||||
|
stream->codec = codec;
|
||||||
|
stream->file = hnd;
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_CodecUtilClose
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_CodecUtilClose(snd_stream_t *stream)
|
||||||
|
{
|
||||||
|
FS_FCloseFile(stream->file);
|
||||||
|
Z_Free(stream);
|
||||||
|
}
|
97
code/client/snd_codec.h
Normal file
97
code/client/snd_codec.h
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SND_CODEC_H_
|
||||||
|
#define _SND_CODEC_H_
|
||||||
|
|
||||||
|
#include "../qcommon/q_shared.h"
|
||||||
|
#include "../qcommon/qcommon.h"
|
||||||
|
|
||||||
|
typedef struct snd_info_s
|
||||||
|
{
|
||||||
|
int rate;
|
||||||
|
int width;
|
||||||
|
int channels;
|
||||||
|
int samples;
|
||||||
|
int size;
|
||||||
|
int dataofs;
|
||||||
|
} snd_info_t;
|
||||||
|
|
||||||
|
typedef struct snd_codec_s snd_codec_t;
|
||||||
|
|
||||||
|
typedef struct snd_stream_s
|
||||||
|
{
|
||||||
|
snd_codec_t *codec;
|
||||||
|
fileHandle_t file;
|
||||||
|
snd_info_t info;
|
||||||
|
int pos;
|
||||||
|
void *ptr;
|
||||||
|
} snd_stream_t;
|
||||||
|
|
||||||
|
// Codec functions
|
||||||
|
typedef void *(*CODEC_LOAD)(const char *filename, snd_info_t *info);
|
||||||
|
typedef snd_stream_t *(*CODEC_OPEN)(const char *filename);
|
||||||
|
typedef int (*CODEC_READ)(snd_stream_t *stream, int bytes, void *buffer);
|
||||||
|
typedef void (*CODEC_CLOSE)(snd_stream_t *stream);
|
||||||
|
|
||||||
|
// Codec data structure
|
||||||
|
struct snd_codec_s
|
||||||
|
{
|
||||||
|
char *ext;
|
||||||
|
CODEC_LOAD load;
|
||||||
|
CODEC_OPEN open;
|
||||||
|
CODEC_READ read;
|
||||||
|
CODEC_CLOSE close;
|
||||||
|
snd_codec_t *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Codec management
|
||||||
|
void S_CodecInit( void );
|
||||||
|
void S_CodecShutdown( void );
|
||||||
|
void S_CodecRegister(snd_codec_t *codec);
|
||||||
|
void *S_CodecLoad(const char *filename, snd_info_t *info);
|
||||||
|
snd_stream_t *S_CodecOpenStream(const char *filename);
|
||||||
|
void S_CodecCloseStream(snd_stream_t *stream);
|
||||||
|
int S_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer);
|
||||||
|
|
||||||
|
// Util functions (used by codecs)
|
||||||
|
snd_stream_t *S_CodecUtilOpen(const char *filename, snd_codec_t *codec);
|
||||||
|
void S_CodecUtilClose(snd_stream_t *stream);
|
||||||
|
|
||||||
|
// WAV Codec
|
||||||
|
extern snd_codec_t wav_codec;
|
||||||
|
void *S_WAV_CodecLoad(const char *filename, snd_info_t *info);
|
||||||
|
snd_stream_t *S_WAV_CodecOpenStream(const char *filename);
|
||||||
|
void S_WAV_CodecCloseStream(snd_stream_t *stream);
|
||||||
|
int S_WAV_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer);
|
||||||
|
|
||||||
|
// Ogg Vorbis codec
|
||||||
|
#ifdef USE_CODEC_VORBIS
|
||||||
|
extern snd_codec_t ogg_codec;
|
||||||
|
void *S_OGG_CodecLoad(const char *filename, snd_info_t *info);
|
||||||
|
snd_stream_t *S_OGG_CodecOpenStream(const char *filename);
|
||||||
|
void S_OGG_CodecCloseStream(snd_stream_t *stream);
|
||||||
|
int S_OGG_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer);
|
||||||
|
#endif // USE_CODEC_VORBIS
|
||||||
|
|
||||||
|
#endif // !_SND_CODEC_H_
|
307
code/client/snd_codec_wav.c
Normal file
307
code/client/snd_codec_wav.c
Normal file
|
@ -0,0 +1,307 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "client.h"
|
||||||
|
#include "snd_codec.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
FGetLittleLong
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static int FGetLittleLong( fileHandle_t f ) {
|
||||||
|
int v;
|
||||||
|
|
||||||
|
FS_Read( &v, sizeof(v), f );
|
||||||
|
|
||||||
|
return LittleLong( v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
FGetLittleShort
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static int FGetLittleShort( fileHandle_t f ) {
|
||||||
|
short v;
|
||||||
|
|
||||||
|
FS_Read( &v, sizeof(v), f );
|
||||||
|
|
||||||
|
return LittleShort( v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_ReadChunkInfo
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static int S_ReadChunkInfo(fileHandle_t f, char *name)
|
||||||
|
{
|
||||||
|
int len, r;
|
||||||
|
|
||||||
|
name[4] = 0;
|
||||||
|
|
||||||
|
r = FS_Read(name, 4, f);
|
||||||
|
if(r != 4)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
len = FGetLittleLong(f);
|
||||||
|
if(len < 0 || len > 0xffffffff)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
//FIXME: 11/11/05 <tim@ngus.net>
|
||||||
|
// I'm not sure I understand why this needs to be padded.
|
||||||
|
// Surely this results in reading past the end of the data?
|
||||||
|
//len = (len + 1 ) & ~1; // pad to word boundary
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_SkipChunk
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static void S_SkipChunk(fileHandle_t f, int length)
|
||||||
|
{
|
||||||
|
byte buffer[32*1024];
|
||||||
|
|
||||||
|
while(length > 0)
|
||||||
|
{
|
||||||
|
int toread = length;
|
||||||
|
if(toread > sizeof(buffer))
|
||||||
|
toread = sizeof(buffer);
|
||||||
|
FS_Read(buffer, toread, f);
|
||||||
|
length -= toread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_FindWavChunk
|
||||||
|
|
||||||
|
Returns the length of the data in the chunk, or 0 if not found
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static int S_FindWavChunk( fileHandle_t f, char *chunk ) {
|
||||||
|
char name[5];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
// This is a bit dangerous...
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
len = S_ReadChunkInfo(f, name);
|
||||||
|
|
||||||
|
// Read failure?
|
||||||
|
if(len == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// If this is the right chunk, return
|
||||||
|
if(!strcmp(name, chunk))
|
||||||
|
return len;
|
||||||
|
|
||||||
|
// Not the right chunk - skip it
|
||||||
|
S_SkipChunk(f, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_ByteSwapRawSamples
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static void S_ByteSwapRawSamples( int samples, int width, int s_channels, const byte *data ) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ( width != 2 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( LittleShort( 256 ) == 256 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( s_channels == 2 ) {
|
||||||
|
samples <<= 1;
|
||||||
|
}
|
||||||
|
for ( i = 0 ; i < samples ; i++ ) {
|
||||||
|
((short *)data)[i] = LittleShort( ((short *)data)[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_ReadWavHeader
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static qboolean S_ReadWavHeader(fileHandle_t file, snd_info_t *info)
|
||||||
|
{
|
||||||
|
char dump[16];
|
||||||
|
int wav_format;
|
||||||
|
int fmtlen = 0;
|
||||||
|
|
||||||
|
// skip the riff wav header
|
||||||
|
FS_Read(dump, 12, file);
|
||||||
|
|
||||||
|
// Scan for the format chunk
|
||||||
|
if((fmtlen = S_FindWavChunk(file, "fmt ")) == 0)
|
||||||
|
{
|
||||||
|
Com_Printf("No fmt chunk\n");
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the parameters
|
||||||
|
wav_format = FGetLittleShort(file);
|
||||||
|
info->channels = FGetLittleShort(file);
|
||||||
|
info->rate = FGetLittleLong(file);
|
||||||
|
FGetLittleLong(file);
|
||||||
|
FGetLittleShort(file);
|
||||||
|
info->width = FGetLittleShort(file) / 8;
|
||||||
|
info->dataofs = 0;
|
||||||
|
|
||||||
|
// Skip the rest of the format chunk if required
|
||||||
|
if(fmtlen > 16)
|
||||||
|
{
|
||||||
|
fmtlen -= 16;
|
||||||
|
S_SkipChunk(file, fmtlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan for the data chunk
|
||||||
|
if( (info->size = S_FindWavChunk(file, "data")) == 0)
|
||||||
|
{
|
||||||
|
Com_Printf("No data chunk\n");
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
info->samples = (info->size / info->width) / info->channels;
|
||||||
|
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WAV codec
|
||||||
|
snd_codec_t wav_codec =
|
||||||
|
{
|
||||||
|
".wav",
|
||||||
|
S_WAV_CodecLoad,
|
||||||
|
S_WAV_CodecOpenStream,
|
||||||
|
S_WAV_CodecReadStream,
|
||||||
|
S_WAV_CodecCloseStream,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_WAV_CodecLoad
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void *S_WAV_CodecLoad(const char *filename, snd_info_t *info)
|
||||||
|
{
|
||||||
|
fileHandle_t file;
|
||||||
|
void *buffer;
|
||||||
|
|
||||||
|
// Try to open the file
|
||||||
|
FS_FOpenFileRead(filename, &file, qtrue);
|
||||||
|
if(!file)
|
||||||
|
{
|
||||||
|
Com_Printf("Can't read sound file %s\n", filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the RIFF header
|
||||||
|
if(!S_ReadWavHeader(file, info))
|
||||||
|
{
|
||||||
|
FS_FCloseFile(file);
|
||||||
|
Com_Printf("Can't understand wav file %s\n", filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate some memory
|
||||||
|
buffer = Z_Malloc(info->size);
|
||||||
|
if(!buffer)
|
||||||
|
{
|
||||||
|
FS_FCloseFile(file);
|
||||||
|
Com_Printf("Out of memory reading %s\n", filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read, byteswap
|
||||||
|
FS_Read(buffer, info->size, file);
|
||||||
|
S_ByteSwapRawSamples(info->samples, info->width, info->channels, (byte *)buffer);
|
||||||
|
|
||||||
|
// Close and return
|
||||||
|
FS_FCloseFile(file);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_WAV_CodecOpenStream
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
snd_stream_t *S_WAV_CodecOpenStream(const char *filename)
|
||||||
|
{
|
||||||
|
snd_stream_t *rv;
|
||||||
|
|
||||||
|
// Open
|
||||||
|
rv = S_CodecUtilOpen(filename, &wav_codec);
|
||||||
|
if(!rv)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Read the RIFF header
|
||||||
|
if(!S_ReadWavHeader(rv->file, &rv->info))
|
||||||
|
{
|
||||||
|
S_CodecUtilClose(rv);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_WAV_CodecCloseStream
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_WAV_CodecCloseStream(snd_stream_t *stream)
|
||||||
|
{
|
||||||
|
S_CodecUtilClose(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_WAV_CodecReadStream
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
int S_WAV_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
|
||||||
|
{
|
||||||
|
int remaining = stream->info.size - stream->pos;
|
||||||
|
int samples;
|
||||||
|
|
||||||
|
if(remaining <= 0)
|
||||||
|
return 0;
|
||||||
|
if(bytes > remaining)
|
||||||
|
bytes = remaining;
|
||||||
|
stream->pos += bytes;
|
||||||
|
samples = (bytes / stream->info.width) / stream->info.channels;
|
||||||
|
FS_Read(buffer, bytes, stream->file);
|
||||||
|
S_ByteSwapRawSamples(samples, stream->info.width, stream->info.channels, buffer);
|
||||||
|
return bytes;
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "snd_local.h"
|
#include "snd_local.h"
|
||||||
|
#include "snd_codec.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
|
||||||
void S_Play_f(void);
|
void S_Play_f(void);
|
||||||
|
@ -37,13 +38,11 @@ void S_SoundList_f(void);
|
||||||
void S_Music_f(void);
|
void S_Music_f(void);
|
||||||
|
|
||||||
void S_Update_( void );
|
void S_Update_( void );
|
||||||
void S_StopAllSounds(void);
|
|
||||||
void S_UpdateBackgroundTrack( void );
|
void S_UpdateBackgroundTrack( void );
|
||||||
|
void S_Base_StopAllSounds(void);
|
||||||
|
void S_Base_StopBackgroundTrack( void );
|
||||||
|
|
||||||
static fileHandle_t s_backgroundFile;
|
snd_stream_t *s_backgroundStream = NULL;
|
||||||
static wavinfo_t s_backgroundInfo;
|
|
||||||
//int s_nextWavChunk;
|
|
||||||
static int s_backgroundSamples;
|
|
||||||
static char s_backgroundLoop[MAX_QPATH];
|
static char s_backgroundLoop[MAX_QPATH];
|
||||||
//static char s_backgroundMusic[MAX_QPATH]; //TTimo: unused
|
//static char s_backgroundMusic[MAX_QPATH]; //TTimo: unused
|
||||||
|
|
||||||
|
@ -82,15 +81,11 @@ int s_numSfx = 0;
|
||||||
#define LOOP_HASH 128
|
#define LOOP_HASH 128
|
||||||
static sfx_t *sfxHash[LOOP_HASH];
|
static sfx_t *sfxHash[LOOP_HASH];
|
||||||
|
|
||||||
cvar_t *s_volume;
|
|
||||||
cvar_t *s_testsound;
|
cvar_t *s_testsound;
|
||||||
cvar_t *s_khz;
|
cvar_t *s_khz;
|
||||||
cvar_t *s_show;
|
cvar_t *s_show;
|
||||||
cvar_t *s_mixahead;
|
cvar_t *s_mixahead;
|
||||||
cvar_t *s_mixPreStep;
|
cvar_t *s_mixPreStep;
|
||||||
cvar_t *s_musicVolume;
|
|
||||||
cvar_t *s_separation;
|
|
||||||
cvar_t *s_doppler;
|
|
||||||
|
|
||||||
static loopSound_t loopSounds[MAX_GENTITIES];
|
static loopSound_t loopSounds[MAX_GENTITIES];
|
||||||
static channel_t *freelist = NULL;
|
static channel_t *freelist = NULL;
|
||||||
|
@ -104,7 +99,7 @@ portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
|
||||||
// ====================================================================
|
// ====================================================================
|
||||||
|
|
||||||
|
|
||||||
void S_SoundInfo_f(void) {
|
void S_Base_SoundInfo(void) {
|
||||||
Com_Printf("----- Sound Info -----\n" );
|
Com_Printf("----- Sound Info -----\n" );
|
||||||
if (!s_soundStarted) {
|
if (!s_soundStarted) {
|
||||||
Com_Printf ("sound system not started\n");
|
Com_Printf ("sound system not started\n");
|
||||||
|
@ -115,7 +110,7 @@ void S_SoundInfo_f(void) {
|
||||||
Com_Printf("%5d submission_chunk\n", dma.submission_chunk);
|
Com_Printf("%5d submission_chunk\n", dma.submission_chunk);
|
||||||
Com_Printf("%5d speed\n", dma.speed);
|
Com_Printf("%5d speed\n", dma.speed);
|
||||||
Com_Printf("0x%x dma buffer\n", dma.buffer);
|
Com_Printf("0x%x dma buffer\n", dma.buffer);
|
||||||
if ( s_backgroundFile ) {
|
if ( s_backgroundStream ) {
|
||||||
Com_Printf("Background file: %s\n", s_backgroundLoop );
|
Com_Printf("Background file: %s\n", s_backgroundLoop );
|
||||||
} else {
|
} else {
|
||||||
Com_Printf("No background file.\n" );
|
Com_Printf("No background file.\n" );
|
||||||
|
@ -125,64 +120,37 @@ void S_SoundInfo_f(void) {
|
||||||
Com_Printf("----------------------\n" );
|
Com_Printf("----------------------\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
=================
|
||||||
S_Init
|
S_Base_SoundList
|
||||||
================
|
=================
|
||||||
*/
|
*/
|
||||||
void S_Init( void ) {
|
void S_Base_SoundList( void ) {
|
||||||
cvar_t *cv;
|
int i;
|
||||||
qboolean r;
|
sfx_t *sfx;
|
||||||
|
int size, total;
|
||||||
|
char type[4][16];
|
||||||
|
char mem[2][16];
|
||||||
|
|
||||||
Com_Printf("\n------- sound initialization -------\n");
|
strcpy(type[0], "16bit");
|
||||||
|
strcpy(type[1], "adpcm");
|
||||||
s_volume = Cvar_Get ("s_volume", "0.8", CVAR_ARCHIVE);
|
strcpy(type[2], "daub4");
|
||||||
s_musicVolume = Cvar_Get ("s_musicvolume", "0.25", CVAR_ARCHIVE);
|
strcpy(type[3], "mulaw");
|
||||||
s_separation = Cvar_Get ("s_separation", "0.5", CVAR_ARCHIVE);
|
strcpy(mem[0], "paged out");
|
||||||
s_doppler = Cvar_Get ("s_doppler", "1", CVAR_ARCHIVE);
|
strcpy(mem[1], "resident ");
|
||||||
s_khz = Cvar_Get ("s_khz", "22", CVAR_ARCHIVE);
|
total = 0;
|
||||||
s_mixahead = Cvar_Get ("s_mixahead", "0.2", CVAR_ARCHIVE);
|
for (sfx=s_knownSfx, i=0 ; i<s_numSfx ; i++, sfx++) {
|
||||||
|
size = sfx->soundLength;
|
||||||
s_mixPreStep = Cvar_Get ("s_mixPreStep", "0.05", CVAR_ARCHIVE);
|
total += size;
|
||||||
s_show = Cvar_Get ("s_show", "0", CVAR_CHEAT);
|
Com_Printf("%6i[%s] : %s[%s]\n", size, type[sfx->soundCompressionMethod],
|
||||||
s_testsound = Cvar_Get ("s_testsound", "0", CVAR_CHEAT);
|
sfx->soundName, mem[sfx->inMemory] );
|
||||||
|
|
||||||
cv = Cvar_Get ("s_initsound", "1", 0);
|
|
||||||
if ( !cv->integer ) {
|
|
||||||
Com_Printf ("not initializing.\n");
|
|
||||||
Com_Printf("------------------------------------\n");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
Com_Printf ("Total resident: %i\n", total);
|
||||||
Cmd_AddCommand("play", S_Play_f);
|
S_DisplayFreeMemory();
|
||||||
Cmd_AddCommand("music", S_Music_f);
|
|
||||||
Cmd_AddCommand("s_list", S_SoundList_f);
|
|
||||||
Cmd_AddCommand("s_info", S_SoundInfo_f);
|
|
||||||
Cmd_AddCommand("s_stop", S_StopAllSounds);
|
|
||||||
|
|
||||||
r = SNDDMA_Init();
|
|
||||||
Com_Printf("------------------------------------\n");
|
|
||||||
|
|
||||||
if ( r ) {
|
|
||||||
s_soundStarted = 1;
|
|
||||||
s_soundMuted = 1;
|
|
||||||
// s_numSfx = 0;
|
|
||||||
|
|
||||||
Com_Memset(sfxHash, 0, sizeof(sfx_t *)*LOOP_HASH);
|
|
||||||
|
|
||||||
s_soundtime = 0;
|
|
||||||
s_paintedtime = 0;
|
|
||||||
|
|
||||||
S_StopAllSounds ();
|
|
||||||
|
|
||||||
S_SoundInfo_f();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void S_ChannelFree(channel_t *v) {
|
void S_ChannelFree(channel_t *v) {
|
||||||
v->thesfx = NULL;
|
v->thesfx = NULL;
|
||||||
*(channel_t **)v = freelist;
|
*(channel_t **)v = freelist;
|
||||||
|
@ -217,25 +185,6 @@ void S_ChannelSetup( void ) {
|
||||||
Com_DPrintf("Channel memory manager started\n");
|
Com_DPrintf("Channel memory manager started\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// =======================================================================
|
|
||||||
// Shutdown sound engine
|
|
||||||
// =======================================================================
|
|
||||||
|
|
||||||
void S_Shutdown( void ) {
|
|
||||||
if ( !s_soundStarted ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SNDDMA_Shutdown();
|
|
||||||
|
|
||||||
s_soundStarted = 0;
|
|
||||||
|
|
||||||
Cmd_RemoveCommand("play");
|
|
||||||
Cmd_RemoveCommand("music");
|
|
||||||
Cmd_RemoveCommand("stopsound");
|
|
||||||
Cmd_RemoveCommand("soundlist");
|
|
||||||
Cmd_RemoveCommand("soundinfo");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// =======================================================================
|
// =======================================================================
|
||||||
|
@ -352,32 +301,11 @@ This is called when the hunk is cleared and the sounds
|
||||||
are no longer valid.
|
are no longer valid.
|
||||||
===================
|
===================
|
||||||
*/
|
*/
|
||||||
void S_DisableSounds( void ) {
|
void S_Base_DisableSounds( void ) {
|
||||||
S_StopAllSounds();
|
S_Base_StopAllSounds();
|
||||||
s_soundMuted = qtrue;
|
s_soundMuted = qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
S_BeginRegistration
|
|
||||||
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void S_BeginRegistration( void ) {
|
|
||||||
s_soundMuted = qfalse; // we can play again
|
|
||||||
|
|
||||||
if (s_numSfx == 0) {
|
|
||||||
SND_setup();
|
|
||||||
|
|
||||||
s_numSfx = 0;
|
|
||||||
Com_Memset( s_knownSfx, 0, sizeof( s_knownSfx ) );
|
|
||||||
Com_Memset(sfxHash, 0, sizeof(sfx_t *)*LOOP_HASH);
|
|
||||||
|
|
||||||
S_RegisterSound("sound/feedback/hit.wav", qfalse); // changed to a sound in baseq3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
S_RegisterSound
|
S_RegisterSound
|
||||||
|
@ -385,7 +313,7 @@ S_RegisterSound
|
||||||
Creates a default buzz sound if the file can't be loaded
|
Creates a default buzz sound if the file can't be loaded
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
sfxHandle_t S_RegisterSound( const char *name, qboolean compressed ) {
|
sfxHandle_t S_Base_RegisterSound( const char *name, qboolean compressed ) {
|
||||||
sfx_t *sfx;
|
sfx_t *sfx;
|
||||||
|
|
||||||
compressed = qfalse;
|
compressed = qfalse;
|
||||||
|
@ -420,6 +348,26 @@ sfxHandle_t S_RegisterSound( const char *name, qboolean compressed ) {
|
||||||
return sfx - s_knownSfx;
|
return sfx - s_knownSfx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
S_BeginRegistration
|
||||||
|
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void S_Base_BeginRegistration( void ) {
|
||||||
|
s_soundMuted = qfalse; // we can play again
|
||||||
|
|
||||||
|
if (s_numSfx == 0) {
|
||||||
|
SND_setup();
|
||||||
|
|
||||||
|
s_numSfx = 0;
|
||||||
|
Com_Memset( s_knownSfx, 0, sizeof( s_knownSfx ) );
|
||||||
|
Com_Memset(sfxHash, 0, sizeof(sfx_t *)*LOOP_HASH);
|
||||||
|
|
||||||
|
S_Base_RegisterSound("sound/feedback/hit.wav", qfalse); // changed to a sound in baseq3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void S_memoryLoad(sfx_t *sfx) {
|
void S_memoryLoad(sfx_t *sfx) {
|
||||||
// load the sound file
|
// load the sound file
|
||||||
if ( !S_LoadSound ( sfx ) ) {
|
if ( !S_LoadSound ( sfx ) ) {
|
||||||
|
@ -470,8 +418,6 @@ void S_SpatializeOrigin (vec3_t origin, int master_vol, int *left_vol, int *righ
|
||||||
{
|
{
|
||||||
rscale = 0.5 * (1.0 + dot);
|
rscale = 0.5 * (1.0 + dot);
|
||||||
lscale = 0.5 * (1.0 - dot);
|
lscale = 0.5 * (1.0 - dot);
|
||||||
//rscale = s_separation->value + ( 1.0 - s_separation->value ) * dot;
|
|
||||||
//lscale = s_separation->value - ( 1.0 - s_separation->value ) * dot;
|
|
||||||
if ( rscale < 0 ) {
|
if ( rscale < 0 ) {
|
||||||
rscale = 0;
|
rscale = 0;
|
||||||
}
|
}
|
||||||
|
@ -505,7 +451,7 @@ if pos is NULL, the sound will be dynamically sourced from the entity
|
||||||
Entchannel 0 will never override a playing sound
|
Entchannel 0 will never override a playing sound
|
||||||
====================
|
====================
|
||||||
*/
|
*/
|
||||||
void S_StartSound(vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfxHandle ) {
|
void S_Base_StartSound(vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfxHandle ) {
|
||||||
channel_t *ch;
|
channel_t *ch;
|
||||||
sfx_t *sfx;
|
sfx_t *sfx;
|
||||||
int i, oldest, chosen, time;
|
int i, oldest, chosen, time;
|
||||||
|
@ -626,7 +572,7 @@ void S_StartSound(vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfxH
|
||||||
S_StartLocalSound
|
S_StartLocalSound
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void S_StartLocalSound( sfxHandle_t sfxHandle, int channelNum ) {
|
void S_Base_StartLocalSound( sfxHandle_t sfxHandle, int channelNum ) {
|
||||||
if ( !s_soundStarted || s_soundMuted ) {
|
if ( !s_soundStarted || s_soundMuted ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -636,7 +582,7 @@ void S_StartLocalSound( sfxHandle_t sfxHandle, int channelNum ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
S_StartSound (NULL, listener_number, channelNum, sfxHandle );
|
S_Base_StartSound (NULL, listener_number, channelNum, sfxHandle );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -648,7 +594,7 @@ If we are about to perform file access, clear the buffer
|
||||||
so sound doesn't stutter.
|
so sound doesn't stutter.
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void S_ClearSoundBuffer( void ) {
|
void S_Base_ClearSoundBuffer( void ) {
|
||||||
int clear;
|
int clear;
|
||||||
|
|
||||||
if (!s_soundStarted)
|
if (!s_soundStarted)
|
||||||
|
@ -683,15 +629,15 @@ void S_ClearSoundBuffer( void ) {
|
||||||
S_StopAllSounds
|
S_StopAllSounds
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void S_StopAllSounds(void) {
|
void S_Base_StopAllSounds(void) {
|
||||||
if ( !s_soundStarted ) {
|
if ( !s_soundStarted ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop the background music
|
// stop the background music
|
||||||
S_StopBackgroundTrack();
|
S_Base_StopBackgroundTrack();
|
||||||
|
|
||||||
S_ClearSoundBuffer ();
|
S_Base_ClearSoundBuffer ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -702,7 +648,7 @@ continuous looping sounds are added each frame
|
||||||
==============================================================
|
==============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void S_StopLoopingSound(int entityNum) {
|
void S_Base_StopLoopingSound(int entityNum) {
|
||||||
loopSounds[entityNum].active = qfalse;
|
loopSounds[entityNum].active = qfalse;
|
||||||
// loopSounds[entityNum].sfx = 0;
|
// loopSounds[entityNum].sfx = 0;
|
||||||
loopSounds[entityNum].kill = qfalse;
|
loopSounds[entityNum].kill = qfalse;
|
||||||
|
@ -714,12 +660,12 @@ S_ClearLoopingSounds
|
||||||
|
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void S_ClearLoopingSounds( qboolean killall ) {
|
void S_Base_ClearLoopingSounds( qboolean killall ) {
|
||||||
int i;
|
int i;
|
||||||
for ( i = 0 ; i < MAX_GENTITIES ; i++) {
|
for ( i = 0 ; i < MAX_GENTITIES ; i++) {
|
||||||
if (killall || loopSounds[i].kill == qtrue || (loopSounds[i].sfx && loopSounds[i].sfx->soundLength == 0)) {
|
if (killall || loopSounds[i].kill == qtrue || (loopSounds[i].sfx && loopSounds[i].sfx->soundLength == 0)) {
|
||||||
loopSounds[i].kill = qfalse;
|
loopSounds[i].kill = qfalse;
|
||||||
S_StopLoopingSound(i);
|
S_Base_StopLoopingSound(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
numLoopChannels = 0;
|
numLoopChannels = 0;
|
||||||
|
@ -733,7 +679,7 @@ Called during entity generation for a frame
|
||||||
Include velocity in case I get around to doing doppler...
|
Include velocity in case I get around to doing doppler...
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void S_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfxHandle ) {
|
void S_Base_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfxHandle ) {
|
||||||
sfx_t *sfx;
|
sfx_t *sfx;
|
||||||
|
|
||||||
if ( !s_soundStarted || s_soundMuted ) {
|
if ( !s_soundStarted || s_soundMuted ) {
|
||||||
|
@ -796,7 +742,7 @@ Called during entity generation for a frame
|
||||||
Include velocity in case I get around to doing doppler...
|
Include velocity in case I get around to doing doppler...
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void S_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfxHandle ) {
|
void S_Base_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfxHandle ) {
|
||||||
sfx_t *sfx;
|
sfx_t *sfx;
|
||||||
|
|
||||||
if ( !s_soundStarted || s_soundMuted ) {
|
if ( !s_soundStarted || s_soundMuted ) {
|
||||||
|
@ -947,7 +893,7 @@ S_RawSamples
|
||||||
Music streaming
|
Music streaming
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
void S_RawSamples( int samples, int rate, int width, int s_channels, const byte *data, float volume ) {
|
void S_Base_RawSamples( int samples, int rate, int width, int s_channels, const byte *data, float volume ) {
|
||||||
int i;
|
int i;
|
||||||
int src, dst;
|
int src, dst;
|
||||||
float scale;
|
float scale;
|
||||||
|
@ -1051,7 +997,7 @@ S_UpdateEntityPosition
|
||||||
let the sound system know where an entity currently is
|
let the sound system know where an entity currently is
|
||||||
======================
|
======================
|
||||||
*/
|
*/
|
||||||
void S_UpdateEntityPosition( int entityNum, const vec3_t origin ) {
|
void S_Base_UpdateEntityPosition( int entityNum, const vec3_t origin ) {
|
||||||
if ( entityNum < 0 || entityNum > MAX_GENTITIES ) {
|
if ( entityNum < 0 || entityNum > MAX_GENTITIES ) {
|
||||||
Com_Error( ERR_DROP, "S_UpdateEntityPosition: bad entitynum %i", entityNum );
|
Com_Error( ERR_DROP, "S_UpdateEntityPosition: bad entitynum %i", entityNum );
|
||||||
}
|
}
|
||||||
|
@ -1066,7 +1012,7 @@ S_Respatialize
|
||||||
Change the volumes of all the playing sounds for changes in their positions
|
Change the volumes of all the playing sounds for changes in their positions
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
void S_Respatialize( int entityNum, const vec3_t head, vec3_t axis[3], int inwater ) {
|
void S_Base_Respatialize( int entityNum, const vec3_t head, vec3_t axis[3], int inwater ) {
|
||||||
int i;
|
int i;
|
||||||
channel_t *ch;
|
channel_t *ch;
|
||||||
vec3_t origin;
|
vec3_t origin;
|
||||||
|
@ -1151,7 +1097,7 @@ S_Update
|
||||||
Called once each time through the main loop
|
Called once each time through the main loop
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
void S_Update( void ) {
|
void S_Base_Update( void ) {
|
||||||
int i;
|
int i;
|
||||||
int total;
|
int total;
|
||||||
channel_t *ch;
|
channel_t *ch;
|
||||||
|
@ -1204,7 +1150,7 @@ void S_GetSoundtime(void)
|
||||||
{ // time to chop things off to avoid 32 bit limits
|
{ // time to chop things off to avoid 32 bit limits
|
||||||
buffers = 0;
|
buffers = 0;
|
||||||
s_paintedtime = fullsamples;
|
s_paintedtime = fullsamples;
|
||||||
S_StopAllSounds ();
|
S_Base_StopAllSounds ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oldsamplepos = samplepos;
|
oldsamplepos = samplepos;
|
||||||
|
@ -1289,73 +1235,6 @@ void S_Update_(void) {
|
||||||
lastTime = thisTime;
|
lastTime = thisTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
===============================================================================
|
|
||||||
|
|
||||||
console functions
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
void S_Play_f( void ) {
|
|
||||||
int i;
|
|
||||||
sfxHandle_t h;
|
|
||||||
char name[256];
|
|
||||||
|
|
||||||
i = 1;
|
|
||||||
while ( i<Cmd_Argc() ) {
|
|
||||||
if ( !Q_strrchr(Cmd_Argv(i), '.') ) {
|
|
||||||
Com_sprintf( name, sizeof(name), "%s.wav", Cmd_Argv(1) );
|
|
||||||
} else {
|
|
||||||
Q_strncpyz( name, Cmd_Argv(i), sizeof(name) );
|
|
||||||
}
|
|
||||||
h = S_RegisterSound( name, qfalse );
|
|
||||||
if( h ) {
|
|
||||||
S_StartLocalSound( h, CHAN_LOCAL_SOUND );
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void S_Music_f( void ) {
|
|
||||||
int c;
|
|
||||||
|
|
||||||
c = Cmd_Argc();
|
|
||||||
|
|
||||||
if ( c == 2 ) {
|
|
||||||
S_StartBackgroundTrack( Cmd_Argv(1), Cmd_Argv(1) );
|
|
||||||
s_backgroundLoop[0] = 0;
|
|
||||||
} else if ( c == 3 ) {
|
|
||||||
S_StartBackgroundTrack( Cmd_Argv(1), Cmd_Argv(2) );
|
|
||||||
} else {
|
|
||||||
Com_Printf ("music <musicfile> [loopfile]\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void S_SoundList_f( void ) {
|
|
||||||
int i;
|
|
||||||
sfx_t *sfx;
|
|
||||||
int size, total;
|
|
||||||
char type[4][16];
|
|
||||||
char mem[2][16];
|
|
||||||
|
|
||||||
strcpy(type[0], "16bit");
|
|
||||||
strcpy(type[1], "adpcm");
|
|
||||||
strcpy(type[2], "daub4");
|
|
||||||
strcpy(type[3], "mulaw");
|
|
||||||
strcpy(mem[0], "paged out");
|
|
||||||
strcpy(mem[1], "resident ");
|
|
||||||
total = 0;
|
|
||||||
for (sfx=s_knownSfx, i=0 ; i<s_numSfx ; i++, sfx++) {
|
|
||||||
size = sfx->soundLength;
|
|
||||||
total += size;
|
|
||||||
Com_Printf("%6i[%s] : %s[%s]\n", size, type[sfx->soundCompressionMethod], sfx->soundName, mem[sfx->inMemory] );
|
|
||||||
}
|
|
||||||
Com_Printf ("Total resident: %i\n", total);
|
|
||||||
S_DisplayFreeMemory();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1366,61 +1245,16 @@ background music functions
|
||||||
===============================================================================
|
===============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int FGetLittleLong( fileHandle_t f ) {
|
|
||||||
int v;
|
|
||||||
|
|
||||||
FS_Read( &v, sizeof(v), f );
|
|
||||||
|
|
||||||
return LittleLong( v);
|
|
||||||
}
|
|
||||||
|
|
||||||
int FGetLittleShort( fileHandle_t f ) {
|
|
||||||
short v;
|
|
||||||
|
|
||||||
FS_Read( &v, sizeof(v), f );
|
|
||||||
|
|
||||||
return LittleShort( v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns the length of the data in the chunk, or 0 if not found
|
|
||||||
int S_FindWavChunk( fileHandle_t f, char *chunk ) {
|
|
||||||
char name[5];
|
|
||||||
int len;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
name[4] = 0;
|
|
||||||
len = 0;
|
|
||||||
r = FS_Read( name, 4, f );
|
|
||||||
if ( r != 4 ) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
len = FGetLittleLong( f );
|
|
||||||
if ( len < 0 || len > 0xfffffff ) {
|
|
||||||
len = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
len = (len + 1 ) & ~1; // pad to word boundary
|
|
||||||
// s_nextWavChunk += len + 8;
|
|
||||||
|
|
||||||
if ( strcmp( name, chunk ) ) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
======================
|
======================
|
||||||
S_StopBackgroundTrack
|
S_StopBackgroundTrack
|
||||||
======================
|
======================
|
||||||
*/
|
*/
|
||||||
void S_StopBackgroundTrack( void ) {
|
void S_Base_StopBackgroundTrack( void ) {
|
||||||
if ( !s_backgroundFile ) {
|
if(!s_backgroundStream)
|
||||||
return;
|
return;
|
||||||
}
|
S_CodecCloseStream(s_backgroundStream);
|
||||||
Sys_EndStreamedFile( s_backgroundFile );
|
s_backgroundStream = NULL;
|
||||||
FS_FCloseFile( s_backgroundFile );
|
|
||||||
s_backgroundFile = 0;
|
|
||||||
s_rawend = 0;
|
s_rawend = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1429,11 +1263,7 @@ void S_StopBackgroundTrack( void ) {
|
||||||
S_StartBackgroundTrack
|
S_StartBackgroundTrack
|
||||||
======================
|
======================
|
||||||
*/
|
*/
|
||||||
void S_StartBackgroundTrack( const char *intro, const char *loop ){
|
void S_Base_StartBackgroundTrack( const char *intro, const char *loop ){
|
||||||
int len;
|
|
||||||
char dump[16];
|
|
||||||
char name[MAX_QPATH];
|
|
||||||
|
|
||||||
if ( !intro ) {
|
if ( !intro ) {
|
||||||
intro = "";
|
intro = "";
|
||||||
}
|
}
|
||||||
|
@ -1442,77 +1272,34 @@ void S_StartBackgroundTrack( const char *intro, const char *loop ){
|
||||||
}
|
}
|
||||||
Com_DPrintf( "S_StartBackgroundTrack( %s, %s )\n", intro, loop );
|
Com_DPrintf( "S_StartBackgroundTrack( %s, %s )\n", intro, loop );
|
||||||
|
|
||||||
Q_strncpyz( name, intro, sizeof( name ) - 4 );
|
|
||||||
COM_DefaultExtension( name, sizeof( name ), ".wav" );
|
|
||||||
|
|
||||||
if ( !intro[0] ) {
|
if ( !intro[0] ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_strncpyz( s_backgroundLoop, loop, sizeof( s_backgroundLoop ) );
|
if( !loop ) {
|
||||||
|
s_backgroundLoop[0] = 0;
|
||||||
|
} else {
|
||||||
|
Q_strncpyz( s_backgroundLoop, loop, sizeof( s_backgroundLoop ) );
|
||||||
|
}
|
||||||
|
|
||||||
// close the background track, but DON'T reset s_rawend
|
// close the background track, but DON'T reset s_rawend
|
||||||
// if restarting the same back ground track
|
// if restarting the same back ground track
|
||||||
if ( s_backgroundFile ) {
|
if(s_backgroundStream)
|
||||||
Sys_EndStreamedFile( s_backgroundFile );
|
{
|
||||||
FS_FCloseFile( s_backgroundFile );
|
S_CodecCloseStream(s_backgroundStream);
|
||||||
s_backgroundFile = 0;
|
s_backgroundStream = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Open stream
|
||||||
// open up a wav file and get all the info
|
s_backgroundStream = S_CodecOpenStream(intro);
|
||||||
//
|
if(!s_backgroundStream) {
|
||||||
FS_FOpenFileRead( name, &s_backgroundFile, qtrue );
|
Com_Printf( S_COLOR_YELLOW "WARNING: couldn't open music file %s\n", intro );
|
||||||
if ( !s_backgroundFile ) {
|
|
||||||
Com_Printf( S_COLOR_YELLOW "WARNING: couldn't open music file %s\n", name );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip the riff wav header
|
if(s_backgroundStream->info.channels != 2 || s_backgroundStream->info.rate != 22050) {
|
||||||
|
Com_Printf(S_COLOR_YELLOW "WARNING: music file %s is not 22k stereo\n", intro );
|
||||||
FS_Read(dump, 12, s_backgroundFile);
|
|
||||||
|
|
||||||
if ( !S_FindWavChunk( s_backgroundFile, "fmt " ) ) {
|
|
||||||
Com_Printf( "No fmt chunk in %s\n", name );
|
|
||||||
FS_FCloseFile( s_backgroundFile );
|
|
||||||
s_backgroundFile = 0;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// save name for soundinfo
|
|
||||||
s_backgroundInfo.format = FGetLittleShort( s_backgroundFile );
|
|
||||||
s_backgroundInfo.channels = FGetLittleShort( s_backgroundFile );
|
|
||||||
s_backgroundInfo.rate = FGetLittleLong( s_backgroundFile );
|
|
||||||
FGetLittleLong( s_backgroundFile );
|
|
||||||
FGetLittleShort( s_backgroundFile );
|
|
||||||
s_backgroundInfo.width = FGetLittleShort( s_backgroundFile ) / 8;
|
|
||||||
|
|
||||||
if ( s_backgroundInfo.format != WAV_FORMAT_PCM ) {
|
|
||||||
FS_FCloseFile( s_backgroundFile );
|
|
||||||
s_backgroundFile = 0;
|
|
||||||
Com_Printf("Not a microsoft PCM format wav: %s\n", name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( s_backgroundInfo.channels != 2 || s_backgroundInfo.rate != 22050 ) {
|
|
||||||
Com_Printf(S_COLOR_YELLOW "WARNING: music file %s is not 22k stereo\n", name );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ( len = S_FindWavChunk( s_backgroundFile, "data" ) ) == 0 ) {
|
|
||||||
FS_FCloseFile( s_backgroundFile );
|
|
||||||
s_backgroundFile = 0;
|
|
||||||
Com_Printf("No data chunk in %s\n", name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_backgroundInfo.samples = len / (s_backgroundInfo.width * s_backgroundInfo.channels);
|
|
||||||
|
|
||||||
s_backgroundSamples = s_backgroundInfo.samples;
|
|
||||||
|
|
||||||
//
|
|
||||||
// start the background streaming
|
|
||||||
//
|
|
||||||
Sys_BeginStreamedFile( s_backgroundFile, 0x10000 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1528,7 +1315,7 @@ void S_UpdateBackgroundTrack( void ) {
|
||||||
int r;
|
int r;
|
||||||
static float musicVolume = 0.5f;
|
static float musicVolume = 0.5f;
|
||||||
|
|
||||||
if ( !s_backgroundFile ) {
|
if(!s_backgroundStream) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1549,50 +1336,47 @@ void S_UpdateBackgroundTrack( void ) {
|
||||||
bufferSamples = MAX_RAW_SAMPLES - (s_rawend - s_soundtime);
|
bufferSamples = MAX_RAW_SAMPLES - (s_rawend - s_soundtime);
|
||||||
|
|
||||||
// decide how much data needs to be read from the file
|
// decide how much data needs to be read from the file
|
||||||
fileSamples = bufferSamples * s_backgroundInfo.rate / dma.speed;
|
fileSamples = bufferSamples * s_backgroundStream->info.rate / dma.speed;
|
||||||
|
|
||||||
// don't try and read past the end of the file
|
|
||||||
if ( fileSamples > s_backgroundSamples ) {
|
|
||||||
fileSamples = s_backgroundSamples;
|
|
||||||
}
|
|
||||||
|
|
||||||
// our max buffer size
|
// our max buffer size
|
||||||
fileBytes = fileSamples * (s_backgroundInfo.width * s_backgroundInfo.channels);
|
fileBytes = fileSamples * (s_backgroundStream->info.width * s_backgroundStream->info.channels);
|
||||||
if ( fileBytes > sizeof(raw) ) {
|
if ( fileBytes > sizeof(raw) ) {
|
||||||
fileBytes = sizeof(raw);
|
fileBytes = sizeof(raw);
|
||||||
fileSamples = fileBytes / (s_backgroundInfo.width * s_backgroundInfo.channels);
|
fileSamples = fileBytes / (s_backgroundStream->info.width * s_backgroundStream->info.channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = Sys_StreamedRead( raw, 1, fileBytes, s_backgroundFile );
|
// Read
|
||||||
if ( r != fileBytes ) {
|
r = S_CodecReadStream(s_backgroundStream, fileBytes, raw);
|
||||||
Com_Printf("StreamedRead failure on music track\n");
|
if(r < fileBytes)
|
||||||
S_StopBackgroundTrack();
|
{
|
||||||
return;
|
fileBytes = r;
|
||||||
|
fileSamples = r / (s_backgroundStream->info.width * s_backgroundStream->info.channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
// byte swap if needed
|
if(r > 0)
|
||||||
S_ByteSwapRawSamples( fileSamples, s_backgroundInfo.width, s_backgroundInfo.channels, raw );
|
{
|
||||||
|
// add to raw buffer
|
||||||
// add to raw buffer
|
S_Base_RawSamples( fileSamples, s_backgroundStream->info.rate,
|
||||||
S_RawSamples( fileSamples, s_backgroundInfo.rate,
|
s_backgroundStream->info.width, s_backgroundStream->info.channels, raw, musicVolume );
|
||||||
s_backgroundInfo.width, s_backgroundInfo.channels, raw, musicVolume );
|
}
|
||||||
|
else
|
||||||
s_backgroundSamples -= fileSamples;
|
{
|
||||||
if ( !s_backgroundSamples ) {
|
|
||||||
// loop
|
// loop
|
||||||
if (s_backgroundLoop[0]) {
|
if(s_backgroundLoop[0])
|
||||||
Sys_EndStreamedFile( s_backgroundFile );
|
{
|
||||||
FS_FCloseFile( s_backgroundFile );
|
S_CodecCloseStream(s_backgroundStream);
|
||||||
s_backgroundFile = 0;
|
s_backgroundStream = NULL;
|
||||||
S_StartBackgroundTrack( s_backgroundLoop, s_backgroundLoop );
|
S_Base_StartBackgroundTrack( s_backgroundLoop, s_backgroundLoop );
|
||||||
if ( !s_backgroundFile ) {
|
if(!s_backgroundStream)
|
||||||
return; // loop failed to restart
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
else
|
||||||
s_backgroundFile = 0;
|
{
|
||||||
|
S_Base_StopBackgroundTrack();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1632,3 +1416,78 @@ void S_FreeOldestSound( void ) {
|
||||||
sfx->inMemory = qfalse;
|
sfx->inMemory = qfalse;
|
||||||
sfx->soundData = NULL;
|
sfx->soundData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// Shutdown sound engine
|
||||||
|
// =======================================================================
|
||||||
|
|
||||||
|
void S_Base_Shutdown( void ) {
|
||||||
|
if ( !s_soundStarted ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SNDDMA_Shutdown();
|
||||||
|
|
||||||
|
s_soundStarted = 0;
|
||||||
|
|
||||||
|
Cmd_RemoveCommand("s_info");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
S_Init
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
qboolean S_Base_Init( soundInterface_t *si ) {
|
||||||
|
qboolean r;
|
||||||
|
|
||||||
|
if( !si ) {
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_khz = Cvar_Get ("s_khz", "22", CVAR_ARCHIVE);
|
||||||
|
s_mixahead = Cvar_Get ("s_mixahead", "0.2", CVAR_ARCHIVE);
|
||||||
|
s_mixPreStep = Cvar_Get ("s_mixPreStep", "0.05", CVAR_ARCHIVE);
|
||||||
|
s_show = Cvar_Get ("s_show", "0", CVAR_CHEAT);
|
||||||
|
s_testsound = Cvar_Get ("s_testsound", "0", CVAR_CHEAT);
|
||||||
|
|
||||||
|
r = SNDDMA_Init();
|
||||||
|
|
||||||
|
if ( r ) {
|
||||||
|
s_soundStarted = 1;
|
||||||
|
s_soundMuted = 1;
|
||||||
|
// s_numSfx = 0;
|
||||||
|
|
||||||
|
Com_Memset(sfxHash, 0, sizeof(sfx_t *)*LOOP_HASH);
|
||||||
|
|
||||||
|
s_soundtime = 0;
|
||||||
|
s_paintedtime = 0;
|
||||||
|
|
||||||
|
S_Base_StopAllSounds( );
|
||||||
|
} else {
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
si->Shutdown = S_Base_Shutdown;
|
||||||
|
si->StartSound = S_Base_StartSound;
|
||||||
|
si->StartLocalSound = S_Base_StartLocalSound;
|
||||||
|
si->StartBackgroundTrack = S_Base_StartBackgroundTrack;
|
||||||
|
si->StopBackgroundTrack = S_Base_StopBackgroundTrack;
|
||||||
|
si->RawSamples = S_Base_RawSamples;
|
||||||
|
si->StopAllSounds = S_Base_StopAllSounds;
|
||||||
|
si->ClearLoopingSounds = S_Base_ClearLoopingSounds;
|
||||||
|
si->AddLoopingSound = S_Base_AddLoopingSound;
|
||||||
|
si->AddRealLoopingSound = S_Base_AddRealLoopingSound;
|
||||||
|
si->StopLoopingSound = S_Base_StopLoopingSound;
|
||||||
|
si->Respatialize = S_Base_Respatialize;
|
||||||
|
si->UpdateEntityPosition = S_Base_UpdateEntityPosition;
|
||||||
|
si->Update = S_Base_Update;
|
||||||
|
si->DisableSounds = S_Base_DisableSounds;
|
||||||
|
si->BeginRegistration = S_Base_BeginRegistration;
|
||||||
|
si->RegisterSound = S_Base_RegisterSound;
|
||||||
|
si->ClearSoundBuffer = S_Base_ClearSoundBuffer;
|
||||||
|
si->SoundInfo = S_Base_SoundInfo;
|
||||||
|
si->SoundList = S_Base_SoundList;
|
||||||
|
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
|
|
@ -117,6 +117,31 @@ typedef struct {
|
||||||
int dataofs; // chunk starts this many bytes from file start
|
int dataofs; // chunk starts this many bytes from file start
|
||||||
} wavinfo_t;
|
} wavinfo_t;
|
||||||
|
|
||||||
|
// Interface between Q3 sound "api" and the sound backend
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
void (*Shutdown)(void);
|
||||||
|
void (*StartSound)( vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx );
|
||||||
|
void (*StartLocalSound)( sfxHandle_t sfx, int channelNum );
|
||||||
|
void (*StartBackgroundTrack)( const char *intro, const char *loop );
|
||||||
|
void (*StopBackgroundTrack)( void );
|
||||||
|
void (*RawSamples)(int samples, int rate, int width, int channels, const byte *data, float volume);
|
||||||
|
void (*StopAllSounds)( void );
|
||||||
|
void (*ClearLoopingSounds)( qboolean killall );
|
||||||
|
void (*AddLoopingSound)( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
|
||||||
|
void (*AddRealLoopingSound)( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
|
||||||
|
void (*StopLoopingSound)(int entityNum );
|
||||||
|
void (*Respatialize)( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater );
|
||||||
|
void (*UpdateEntityPosition)( int entityNum, const vec3_t origin );
|
||||||
|
void (*Update)( void );
|
||||||
|
void (*DisableSounds)( void );
|
||||||
|
void (*BeginRegistration)( void );
|
||||||
|
sfxHandle_t (*RegisterSound)( const char *sample, qboolean compressed );
|
||||||
|
void (*ClearSoundBuffer)( void );
|
||||||
|
void (*SoundInfo)( void );
|
||||||
|
void (*SoundList)( void );
|
||||||
|
} soundInterface_t;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
====================================================================
|
====================================================================
|
||||||
|
@ -157,14 +182,11 @@ extern dma_t dma;
|
||||||
#define MAX_RAW_SAMPLES 16384
|
#define MAX_RAW_SAMPLES 16384
|
||||||
extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
|
extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
|
||||||
|
|
||||||
extern cvar_t *s_volume;
|
extern cvar_t *s_volume;
|
||||||
extern cvar_t *s_nosound;
|
extern cvar_t *s_musicVolume;
|
||||||
extern cvar_t *s_khz;
|
extern cvar_t *s_doppler;
|
||||||
extern cvar_t *s_show;
|
|
||||||
extern cvar_t *s_mixahead;
|
|
||||||
|
|
||||||
extern cvar_t *s_testsound;
|
extern cvar_t *s_testsound;
|
||||||
extern cvar_t *s_separation;
|
|
||||||
|
|
||||||
qboolean S_LoadSound( sfx_t *sfx );
|
qboolean S_LoadSound( sfx_t *sfx );
|
||||||
|
|
||||||
|
@ -204,3 +226,18 @@ extern short *sfxScratchBuffer;
|
||||||
extern sfx_t *sfxScratchPointer;
|
extern sfx_t *sfxScratchPointer;
|
||||||
extern int sfxScratchIndex;
|
extern int sfxScratchIndex;
|
||||||
|
|
||||||
|
qboolean S_Base_Init( soundInterface_t *si );
|
||||||
|
|
||||||
|
// OpenAL stuff
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SRCPRI_AMBIENT = 0, // Ambient sound effects
|
||||||
|
SRCPRI_ENTITY, // Entity sound effects
|
||||||
|
SRCPRI_ONESHOT, // One-shot sounds
|
||||||
|
SRCPRI_LOCAL, // Local sounds
|
||||||
|
SRCPRI_STREAM // Streams (music, cutscenes)
|
||||||
|
} alSrcPriority_t;
|
||||||
|
|
||||||
|
typedef int srcHandle_t;
|
||||||
|
|
||||||
|
qboolean S_AL_Init( soundInterface_t *si );
|
||||||
|
|
433
code/client/snd_main.c
Normal file
433
code/client/snd_main.c
Normal file
|
@ -0,0 +1,433 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code 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.
|
||||||
|
|
||||||
|
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "client.h"
|
||||||
|
#include "snd_codec.h"
|
||||||
|
#include "snd_local.h"
|
||||||
|
#include "snd_public.h"
|
||||||
|
|
||||||
|
cvar_t *s_volume;
|
||||||
|
cvar_t *s_musicVolume;
|
||||||
|
cvar_t *s_doppler;
|
||||||
|
|
||||||
|
static soundInterface_t si;
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_ValidateInterface
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static qboolean S_ValidSoundInterface( soundInterface_t *si )
|
||||||
|
{
|
||||||
|
if( !si->Shutdown ) return qfalse;
|
||||||
|
if( !si->StartSound ) return qfalse;
|
||||||
|
if( !si->StartLocalSound ) return qfalse;
|
||||||
|
if( !si->StartBackgroundTrack ) return qfalse;
|
||||||
|
if( !si->StopBackgroundTrack ) return qfalse;
|
||||||
|
if( !si->RawSamples ) return qfalse;
|
||||||
|
if( !si->StopAllSounds ) return qfalse;
|
||||||
|
if( !si->ClearLoopingSounds ) return qfalse;
|
||||||
|
if( !si->AddLoopingSound ) return qfalse;
|
||||||
|
if( !si->AddRealLoopingSound ) return qfalse;
|
||||||
|
if( !si->StopLoopingSound ) return qfalse;
|
||||||
|
if( !si->Respatialize ) return qfalse;
|
||||||
|
if( !si->UpdateEntityPosition ) return qfalse;
|
||||||
|
if( !si->Update ) return qfalse;
|
||||||
|
if( !si->DisableSounds ) return qfalse;
|
||||||
|
if( !si->BeginRegistration ) return qfalse;
|
||||||
|
if( !si->RegisterSound ) return qfalse;
|
||||||
|
if( !si->ClearSoundBuffer ) return qfalse;
|
||||||
|
if( !si->SoundInfo ) return qfalse;
|
||||||
|
if( !si->SoundList ) return qfalse;
|
||||||
|
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_StartSound
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_StartSound( vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx )
|
||||||
|
{
|
||||||
|
if( si.StartSound ) {
|
||||||
|
si.StartSound( origin, entnum, entchannel, sfx );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_StartLocalSound
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_StartLocalSound( sfxHandle_t sfx, int channelNum )
|
||||||
|
{
|
||||||
|
if( si.StartLocalSound ) {
|
||||||
|
si.StartLocalSound( sfx, channelNum );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_StartBackgroundTrack
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_StartBackgroundTrack( const char *intro, const char *loop )
|
||||||
|
{
|
||||||
|
if( si.StartBackgroundTrack ) {
|
||||||
|
si.StartBackgroundTrack( intro, loop );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_StopBackgroundTrack
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_StopBackgroundTrack( void )
|
||||||
|
{
|
||||||
|
if( si.StopBackgroundTrack ) {
|
||||||
|
si.StopBackgroundTrack( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_RawSamples
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_RawSamples (int samples, int rate, int width, int channels,
|
||||||
|
const byte *data, float volume)
|
||||||
|
{
|
||||||
|
if( si.RawSamples ) {
|
||||||
|
si.RawSamples( samples, rate, width, channels, data, volume );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_StopAllSounds
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_StopAllSounds( void )
|
||||||
|
{
|
||||||
|
if( si.StopAllSounds ) {
|
||||||
|
si.StopAllSounds( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_ClearLoopingSounds
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_ClearLoopingSounds( qboolean killall )
|
||||||
|
{
|
||||||
|
if( si.ClearLoopingSounds ) {
|
||||||
|
si.ClearLoopingSounds( killall );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_AddLoopingSound
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_AddLoopingSound( int entityNum, const vec3_t origin,
|
||||||
|
const vec3_t velocity, sfxHandle_t sfx )
|
||||||
|
{
|
||||||
|
if( si.AddLoopingSound ) {
|
||||||
|
si.AddLoopingSound( entityNum, origin, velocity, sfx );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_AddRealLoopingSound
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_AddRealLoopingSound( int entityNum, const vec3_t origin,
|
||||||
|
const vec3_t velocity, sfxHandle_t sfx )
|
||||||
|
{
|
||||||
|
if( si.AddRealLoopingSound ) {
|
||||||
|
si.AddRealLoopingSound( entityNum, origin, velocity, sfx );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_StopLoopingSound
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_StopLoopingSound( int entityNum )
|
||||||
|
{
|
||||||
|
if( si.StopLoopingSound ) {
|
||||||
|
si.StopLoopingSound( entityNum );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_Respatialize
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_Respatialize( int entityNum, const vec3_t origin,
|
||||||
|
vec3_t axis[3], int inwater )
|
||||||
|
{
|
||||||
|
if( si.Respatialize ) {
|
||||||
|
si.Respatialize( entityNum, origin, axis, inwater );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_UpdateEntityPosition
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_UpdateEntityPosition( int entityNum, const vec3_t origin )
|
||||||
|
{
|
||||||
|
if( si.UpdateEntityPosition ) {
|
||||||
|
si.UpdateEntityPosition( entityNum, origin );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_Update
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_Update( void )
|
||||||
|
{
|
||||||
|
if( si.Update ) {
|
||||||
|
si.Update( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_DisableSounds
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_DisableSounds( void )
|
||||||
|
{
|
||||||
|
if( si.DisableSounds ) {
|
||||||
|
si.DisableSounds( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_BeginRegistration
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_BeginRegistration( void )
|
||||||
|
{
|
||||||
|
if( si.BeginRegistration ) {
|
||||||
|
si.BeginRegistration( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_RegisterSound
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
sfxHandle_t S_RegisterSound( const char *sample, qboolean compressed )
|
||||||
|
{
|
||||||
|
if( si.RegisterSound ) {
|
||||||
|
return si.RegisterSound( sample, compressed );
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_ClearSoundBuffer
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_ClearSoundBuffer( void )
|
||||||
|
{
|
||||||
|
if( si.ClearSoundBuffer ) {
|
||||||
|
si.ClearSoundBuffer( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_SoundInfo
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_SoundInfo( void )
|
||||||
|
{
|
||||||
|
if( si.SoundInfo ) {
|
||||||
|
si.SoundInfo( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_SoundList
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_SoundList( void )
|
||||||
|
{
|
||||||
|
if( si.SoundList ) {
|
||||||
|
si.SoundList( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_Play_f
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_Play_f( void ) {
|
||||||
|
int i;
|
||||||
|
sfxHandle_t h;
|
||||||
|
char name[256];
|
||||||
|
|
||||||
|
if( !si.RegisterSound || !si.StartLocalSound ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 1;
|
||||||
|
while ( i<Cmd_Argc() ) {
|
||||||
|
if ( !Q_strrchr(Cmd_Argv(i), '.') ) {
|
||||||
|
Com_sprintf( name, sizeof(name), "%s.wav", Cmd_Argv(1) );
|
||||||
|
} else {
|
||||||
|
Q_strncpyz( name, Cmd_Argv(i), sizeof(name) );
|
||||||
|
}
|
||||||
|
h = si.RegisterSound( name, qfalse );
|
||||||
|
if( h ) {
|
||||||
|
si.StartLocalSound( h, CHAN_LOCAL_SOUND );
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_Music_f
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_Music_f( void ) {
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if( !si.StartBackgroundTrack ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = Cmd_Argc();
|
||||||
|
|
||||||
|
if ( c == 2 ) {
|
||||||
|
si.StartBackgroundTrack( Cmd_Argv(1), NULL );
|
||||||
|
} else if ( c == 3 ) {
|
||||||
|
si.StartBackgroundTrack( Cmd_Argv(1), Cmd_Argv(2) );
|
||||||
|
} else {
|
||||||
|
Com_Printf ("music <musicfile> [loopfile]\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_Init
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_Init( void )
|
||||||
|
{
|
||||||
|
cvar_t *cv;
|
||||||
|
qboolean started = qfalse;
|
||||||
|
|
||||||
|
Com_Printf( "------ Initializing Sound ------\n" );
|
||||||
|
|
||||||
|
s_volume = Cvar_Get( "s_volume", "0.8", CVAR_ARCHIVE );
|
||||||
|
s_musicVolume = Cvar_Get( "s_musicvolume", "0.25", CVAR_ARCHIVE );
|
||||||
|
s_doppler = Cvar_Get( "s_doppler", "1", CVAR_ARCHIVE );
|
||||||
|
|
||||||
|
cv = Cvar_Get( "s_initsound", "1", 0 );
|
||||||
|
if( !cv->integer ) {
|
||||||
|
Com_Printf( "Sound disabled.\n" );
|
||||||
|
} else {
|
||||||
|
|
||||||
|
S_CodecInit( );
|
||||||
|
|
||||||
|
Cmd_AddCommand( "play", S_Play_f );
|
||||||
|
Cmd_AddCommand( "music", S_Music_f );
|
||||||
|
Cmd_AddCommand( "s_list", S_SoundList );
|
||||||
|
Cmd_AddCommand( "s_stop", S_StopAllSounds );
|
||||||
|
Cmd_AddCommand( "s_info", S_SoundInfo );
|
||||||
|
|
||||||
|
cv = Cvar_Get( "s_useOpenAL", "1", CVAR_ARCHIVE );
|
||||||
|
if( cv->integer ) {
|
||||||
|
//OpenAL
|
||||||
|
started = S_AL_Init( &si );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !started ) {
|
||||||
|
started = S_Base_Init( &si );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( started ) {
|
||||||
|
if( !S_ValidSoundInterface( &si ) ) {
|
||||||
|
Com_Error( ERR_FATAL, "Sound interface invalid." );
|
||||||
|
}
|
||||||
|
|
||||||
|
S_SoundInfo( );
|
||||||
|
Com_Printf( "Sound intialization successful.\n" );
|
||||||
|
} else {
|
||||||
|
Com_Printf( "Sound intialization failed.\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Com_Printf( "--------------------------------\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_Shutdown
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void S_Shutdown( void )
|
||||||
|
{
|
||||||
|
if( si.Shutdown ) {
|
||||||
|
si.Shutdown( );
|
||||||
|
}
|
||||||
|
|
||||||
|
Com_Memset( &si, 0, sizeof( soundInterface_t ) );
|
||||||
|
|
||||||
|
Cmd_RemoveCommand( "play" );
|
||||||
|
Cmd_RemoveCommand( "music");
|
||||||
|
Cmd_RemoveCommand( "s_list" );
|
||||||
|
Cmd_RemoveCommand( "s_stop" );
|
||||||
|
Cmd_RemoveCommand( "s_info" );
|
||||||
|
|
||||||
|
S_CodecShutdown( );
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "snd_local.h"
|
#include "snd_local.h"
|
||||||
|
#include "snd_codec.h"
|
||||||
|
|
||||||
#define DEF_COMSOUNDMEGS "8"
|
#define DEF_COMSOUNDMEGS "8"
|
||||||
|
|
||||||
|
@ -99,137 +100,6 @@ void SND_setup(void) {
|
||||||
Com_Printf("Sound memory manager started\n");
|
Com_Printf("Sound memory manager started\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
===============================================================================
|
|
||||||
|
|
||||||
WAV loading
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
static byte *data_p;
|
|
||||||
static byte *iff_end;
|
|
||||||
static byte *last_chunk;
|
|
||||||
static byte *iff_data;
|
|
||||||
static int iff_chunk_len;
|
|
||||||
|
|
||||||
static short GetLittleShort(void)
|
|
||||||
{
|
|
||||||
short val = 0;
|
|
||||||
val = *data_p;
|
|
||||||
val = val + (*(data_p+1)<<8);
|
|
||||||
data_p += 2;
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int GetLittleLong(void)
|
|
||||||
{
|
|
||||||
int val = 0;
|
|
||||||
val = *data_p;
|
|
||||||
val = val + (*(data_p+1)<<8);
|
|
||||||
val = val + (*(data_p+2)<<16);
|
|
||||||
val = val + (*(data_p+3)<<24);
|
|
||||||
data_p += 4;
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void FindNextChunk(char *name)
|
|
||||||
{
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
data_p=last_chunk;
|
|
||||||
|
|
||||||
if (data_p >= iff_end)
|
|
||||||
{ // didn't find the chunk
|
|
||||||
data_p = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
data_p += 4;
|
|
||||||
iff_chunk_len = GetLittleLong();
|
|
||||||
if (iff_chunk_len < 0)
|
|
||||||
{
|
|
||||||
data_p = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
data_p -= 8;
|
|
||||||
last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
|
|
||||||
if (!strncmp((char *)data_p, name, 4))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void FindChunk(char *name)
|
|
||||||
{
|
|
||||||
last_chunk = iff_data;
|
|
||||||
FindNextChunk (name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
============
|
|
||||||
GetWavinfo
|
|
||||||
============
|
|
||||||
*/
|
|
||||||
static wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
|
|
||||||
{
|
|
||||||
wavinfo_t info;
|
|
||||||
|
|
||||||
Com_Memset (&info, 0, sizeof(info));
|
|
||||||
|
|
||||||
if (!wav)
|
|
||||||
return info;
|
|
||||||
|
|
||||||
iff_data = wav;
|
|
||||||
iff_end = wav + wavlength;
|
|
||||||
|
|
||||||
// find "RIFF" chunk
|
|
||||||
FindChunk("RIFF");
|
|
||||||
if (!(data_p && !strncmp((char *)data_p+8, "WAVE", 4)))
|
|
||||||
{
|
|
||||||
Com_Printf("Missing RIFF/WAVE chunks\n");
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get "fmt " chunk
|
|
||||||
iff_data = data_p + 12;
|
|
||||||
// DumpChunks ();
|
|
||||||
|
|
||||||
FindChunk("fmt ");
|
|
||||||
if (!data_p)
|
|
||||||
{
|
|
||||||
Com_Printf("Missing fmt chunk\n");
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
data_p += 8;
|
|
||||||
info.format = GetLittleShort();
|
|
||||||
info.channels = GetLittleShort();
|
|
||||||
info.rate = GetLittleLong();
|
|
||||||
data_p += 4+2;
|
|
||||||
info.width = GetLittleShort() / 8;
|
|
||||||
|
|
||||||
if (info.format != 1)
|
|
||||||
{
|
|
||||||
Com_Printf("Microsoft PCM format only\n");
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// find data chunk
|
|
||||||
FindChunk("data");
|
|
||||||
if (!data_p)
|
|
||||||
{
|
|
||||||
Com_Printf("Missing data chunk\n");
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
data_p += 4;
|
|
||||||
info.samples = GetLittleLong () / info.width;
|
|
||||||
info.dataofs = data_p - wav;
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
ResampleSfx
|
ResampleSfx
|
||||||
|
@ -315,7 +185,6 @@ static int ResampleSfxRaw( short *sfx, int inrate, int inwidth, int samples, byt
|
||||||
return outcount;
|
return outcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -330,8 +199,8 @@ qboolean S_LoadSound( sfx_t *sfx )
|
||||||
{
|
{
|
||||||
byte *data;
|
byte *data;
|
||||||
short *samples;
|
short *samples;
|
||||||
wavinfo_t info;
|
snd_info_t info;
|
||||||
int size;
|
// int size;
|
||||||
|
|
||||||
// player specific sounds are never directly loaded
|
// player specific sounds are never directly loaded
|
||||||
if ( sfx->soundName[0] == '*') {
|
if ( sfx->soundName[0] == '*') {
|
||||||
|
@ -339,17 +208,9 @@ qboolean S_LoadSound( sfx_t *sfx )
|
||||||
}
|
}
|
||||||
|
|
||||||
// load it in
|
// load it in
|
||||||
size = FS_ReadFile( sfx->soundName, (void **)&data );
|
data = S_CodecLoad(sfx->soundName, &info);
|
||||||
if ( !data ) {
|
if(!data)
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
|
||||||
|
|
||||||
info = GetWavinfo( sfx->soundName, data, size );
|
|
||||||
if ( info.channels != 1 ) {
|
|
||||||
Com_Printf ("%s is a stereo wav file\n", sfx->soundName);
|
|
||||||
FS_FreeFile (data);
|
|
||||||
return qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( info.width == 1 ) {
|
if ( info.width == 1 ) {
|
||||||
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is a 8 bit wav file\n", sfx->soundName);
|
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is a 8 bit wav file\n", sfx->soundName);
|
||||||
|
@ -372,7 +233,7 @@ qboolean S_LoadSound( sfx_t *sfx )
|
||||||
if( sfx->soundCompressed == qtrue) {
|
if( sfx->soundCompressed == qtrue) {
|
||||||
sfx->soundCompressionMethod = 1;
|
sfx->soundCompressionMethod = 1;
|
||||||
sfx->soundData = NULL;
|
sfx->soundData = NULL;
|
||||||
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
|
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, data + info.dataofs );
|
||||||
S_AdpcmEncodeSound(sfx, samples);
|
S_AdpcmEncodeSound(sfx, samples);
|
||||||
#if 0
|
#if 0
|
||||||
} else if (info.samples>(SND_CHUNK_SIZE*16) && info.width >1) {
|
} else if (info.samples>(SND_CHUNK_SIZE*16) && info.width >1) {
|
||||||
|
@ -394,7 +255,7 @@ qboolean S_LoadSound( sfx_t *sfx )
|
||||||
}
|
}
|
||||||
|
|
||||||
Hunk_FreeTempMemory(samples);
|
Hunk_FreeTempMemory(samples);
|
||||||
FS_FreeFile( data );
|
Z_Free(data);
|
||||||
|
|
||||||
return qtrue;
|
return qtrue;
|
||||||
}
|
}
|
||||||
|
|
1567
code/client/snd_openal.c
Normal file
1567
code/client/snd_openal.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -999,6 +999,13 @@
|
||||||
};
|
};
|
||||||
012AD9A500868211C697A10E = {
|
012AD9A500868211C697A10E = {
|
||||||
children = (
|
children = (
|
||||||
|
92847F3509279B370056BC59,
|
||||||
|
92847F3609279B370056BC59,
|
||||||
|
92847F3709279B370056BC59,
|
||||||
|
92847F3809279B370056BC59,
|
||||||
|
92847F3909279B370056BC59,
|
||||||
|
92847F3A09279B370056BC59,
|
||||||
|
92847F3B09279B370056BC59,
|
||||||
9260378009101A6C0018EAE6,
|
9260378009101A6C0018EAE6,
|
||||||
012AD9A600868211C697A10E,
|
012AD9A600868211C697A10E,
|
||||||
012AD9A700868211C697A10E,
|
012AD9A700868211C697A10E,
|
||||||
|
@ -6764,6 +6771,8 @@
|
||||||
9260377A09101A3B0018EAE6,
|
9260377A09101A3B0018EAE6,
|
||||||
9260378109101A6C0018EAE6,
|
9260378109101A6C0018EAE6,
|
||||||
9292851809192BA800286DE9,
|
9292851809192BA800286DE9,
|
||||||
|
92847F3D09279B370056BC59,
|
||||||
|
92847F4009279B370056BC59,
|
||||||
);
|
);
|
||||||
isa = PBXHeadersBuildPhase;
|
isa = PBXHeadersBuildPhase;
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -6919,6 +6928,11 @@
|
||||||
4F23A81D08F4FA8F00CB90D3,
|
4F23A81D08F4FA8F00CB90D3,
|
||||||
92603767091019D30018EAE6,
|
92603767091019D30018EAE6,
|
||||||
92603768091019D30018EAE6,
|
92603768091019D30018EAE6,
|
||||||
|
92847F3C09279B370056BC59,
|
||||||
|
92847F3E09279B370056BC59,
|
||||||
|
92847F3F09279B370056BC59,
|
||||||
|
92847F4109279B370056BC59,
|
||||||
|
92847F4209279B370056BC59,
|
||||||
);
|
);
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -7775,6 +7789,8 @@
|
||||||
9260377B09101A3B0018EAE6,
|
9260377B09101A3B0018EAE6,
|
||||||
9260378209101A6C0018EAE6,
|
9260378209101A6C0018EAE6,
|
||||||
9292851909192BA800286DE9,
|
9292851909192BA800286DE9,
|
||||||
|
92847F4409279B370056BC59,
|
||||||
|
92847F4709279B370056BC59,
|
||||||
);
|
);
|
||||||
isa = PBXHeadersBuildPhase;
|
isa = PBXHeadersBuildPhase;
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -8260,6 +8276,11 @@
|
||||||
4F23A81508F4FA8F00CB90D3,
|
4F23A81508F4FA8F00CB90D3,
|
||||||
9260376B091019D30018EAE6,
|
9260376B091019D30018EAE6,
|
||||||
9260376C091019D30018EAE6,
|
9260376C091019D30018EAE6,
|
||||||
|
92847F4309279B370056BC59,
|
||||||
|
92847F4509279B370056BC59,
|
||||||
|
92847F4609279B370056BC59,
|
||||||
|
92847F4809279B370056BC59,
|
||||||
|
92847F4909279B370056BC59,
|
||||||
);
|
);
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -10932,6 +10953,146 @@
|
||||||
settings = {
|
settings = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
92847F3509279B370056BC59 = {
|
||||||
|
fileEncoding = 30;
|
||||||
|
isa = PBXFileReference;
|
||||||
|
lastKnownFileType = sourcecode.c.c;
|
||||||
|
path = qal.c;
|
||||||
|
refType = 4;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
92847F3609279B370056BC59 = {
|
||||||
|
fileEncoding = 30;
|
||||||
|
isa = PBXFileReference;
|
||||||
|
lastKnownFileType = sourcecode.c.h;
|
||||||
|
path = qal.h;
|
||||||
|
refType = 4;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
92847F3709279B370056BC59 = {
|
||||||
|
fileEncoding = 30;
|
||||||
|
isa = PBXFileReference;
|
||||||
|
lastKnownFileType = sourcecode.c.c;
|
||||||
|
path = snd_codec_wav.c;
|
||||||
|
refType = 4;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
92847F3809279B370056BC59 = {
|
||||||
|
fileEncoding = 30;
|
||||||
|
isa = PBXFileReference;
|
||||||
|
lastKnownFileType = sourcecode.c.c;
|
||||||
|
path = snd_codec.c;
|
||||||
|
refType = 4;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
92847F3909279B370056BC59 = {
|
||||||
|
fileEncoding = 30;
|
||||||
|
isa = PBXFileReference;
|
||||||
|
lastKnownFileType = sourcecode.c.h;
|
||||||
|
path = snd_codec.h;
|
||||||
|
refType = 4;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
92847F3A09279B370056BC59 = {
|
||||||
|
fileEncoding = 30;
|
||||||
|
isa = PBXFileReference;
|
||||||
|
lastKnownFileType = sourcecode.c.c;
|
||||||
|
path = snd_main.c;
|
||||||
|
refType = 4;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
92847F3B09279B370056BC59 = {
|
||||||
|
fileEncoding = 30;
|
||||||
|
isa = PBXFileReference;
|
||||||
|
lastKnownFileType = sourcecode.c.c;
|
||||||
|
path = snd_openal.c;
|
||||||
|
refType = 4;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
92847F3C09279B370056BC59 = {
|
||||||
|
fileRef = 92847F3509279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
92847F3D09279B370056BC59 = {
|
||||||
|
fileRef = 92847F3609279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
92847F3E09279B370056BC59 = {
|
||||||
|
fileRef = 92847F3709279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
92847F3F09279B370056BC59 = {
|
||||||
|
fileRef = 92847F3809279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
92847F4009279B370056BC59 = {
|
||||||
|
fileRef = 92847F3909279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
92847F4109279B370056BC59 = {
|
||||||
|
fileRef = 92847F3A09279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
92847F4209279B370056BC59 = {
|
||||||
|
fileRef = 92847F3B09279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
92847F4309279B370056BC59 = {
|
||||||
|
fileRef = 92847F3509279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
92847F4409279B370056BC59 = {
|
||||||
|
fileRef = 92847F3609279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
92847F4509279B370056BC59 = {
|
||||||
|
fileRef = 92847F3709279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
92847F4609279B370056BC59 = {
|
||||||
|
fileRef = 92847F3809279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
92847F4709279B370056BC59 = {
|
||||||
|
fileRef = 92847F3909279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
92847F4809279B370056BC59 = {
|
||||||
|
fileRef = 92847F3A09279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
92847F4909279B370056BC59 = {
|
||||||
|
fileRef = 92847F3B09279B370056BC59;
|
||||||
|
isa = PBXBuildFile;
|
||||||
|
settings = {
|
||||||
|
};
|
||||||
|
};
|
||||||
9292851709192BA800286DE9 = {
|
9292851709192BA800286DE9 = {
|
||||||
fileEncoding = 30;
|
fileEncoding = 30;
|
||||||
isa = PBXFileReference;
|
isa = PBXFileReference;
|
||||||
|
|
|
@ -47,6 +47,10 @@ ifndef USE_SDL
|
||||||
USE_SDL=1
|
USE_SDL=1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifndef USE_OPENAL
|
||||||
|
USE_OPENAL=1
|
||||||
|
endif
|
||||||
|
|
||||||
ifndef BUILD_CLIENT
|
ifndef BUILD_CLIENT
|
||||||
BUILD_CLIENT=1
|
BUILD_CLIENT=1
|
||||||
endif
|
endif
|
||||||
|
@ -115,6 +119,10 @@ ifeq ($(PLATFORM),linux)
|
||||||
|
|
||||||
BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes
|
BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes
|
||||||
|
|
||||||
|
ifeq ($(USE_OPENAL),1)
|
||||||
|
BASE_CFLAGS += -DUSE_OPENAL=1
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_SDL),1)
|
ifeq ($(USE_SDL),1)
|
||||||
BASE_CFLAGS += -DUSE_SDL_VIDEO=1 -DUSE_SDL_SOUND=1 $(shell sdl-config --cflags)
|
BASE_CFLAGS += -DUSE_SDL_VIDEO=1 -DUSE_SDL_SOUND=1 $(shell sdl-config --cflags)
|
||||||
GL_CFLAGS =
|
GL_CFLAGS =
|
||||||
|
@ -214,6 +222,10 @@ ifeq ($(PLATFORM),mingw32)
|
||||||
|
|
||||||
BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes
|
BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes
|
||||||
|
|
||||||
|
ifeq ($(USE_OPENAL),1)
|
||||||
|
BASE_CFLAGS += -DUSE_OPENAL=1
|
||||||
|
endif
|
||||||
|
|
||||||
DX_CFLAGS = -I$(DXSDK_DIR)/Include
|
DX_CFLAGS = -I$(DXSDK_DIR)/Include
|
||||||
|
|
||||||
GL_CFLAGS =
|
GL_CFLAGS =
|
||||||
|
@ -620,6 +632,13 @@ Q3OBJ = \
|
||||||
$(B)/client/snd_mix.o \
|
$(B)/client/snd_mix.o \
|
||||||
$(B)/client/snd_wavelet.o \
|
$(B)/client/snd_wavelet.o \
|
||||||
\
|
\
|
||||||
|
$(B)/client/snd_main.o \
|
||||||
|
$(B)/client/snd_codec.o \
|
||||||
|
$(B)/client/snd_codec_wav.o \
|
||||||
|
\
|
||||||
|
$(B)/client/qal.o \
|
||||||
|
$(B)/client/snd_openal.o \
|
||||||
|
\
|
||||||
$(B)/client/sv_bot.o \
|
$(B)/client/sv_bot.o \
|
||||||
$(B)/client/sv_ccmds.o \
|
$(B)/client/sv_ccmds.o \
|
||||||
$(B)/client/sv_client.o \
|
$(B)/client/sv_client.o \
|
||||||
|
@ -891,6 +910,14 @@ $(B)/client/snd_dma.o : $(CDIR)/snd_dma.c; $(DO_CC)
|
||||||
$(B)/client/snd_mem.o : $(CDIR)/snd_mem.c; $(DO_CC)
|
$(B)/client/snd_mem.o : $(CDIR)/snd_mem.c; $(DO_CC)
|
||||||
$(B)/client/snd_mix.o : $(CDIR)/snd_mix.c; $(DO_CC)
|
$(B)/client/snd_mix.o : $(CDIR)/snd_mix.c; $(DO_CC)
|
||||||
$(B)/client/snd_wavelet.o : $(CDIR)/snd_wavelet.c; $(DO_CC)
|
$(B)/client/snd_wavelet.o : $(CDIR)/snd_wavelet.c; $(DO_CC)
|
||||||
|
|
||||||
|
$(B)/client/snd_main.o : $(CDIR)/snd_main.c; $(DO_CC)
|
||||||
|
$(B)/client/snd_codec.o : $(CDIR)/snd_codec.c; $(DO_CC)
|
||||||
|
$(B)/client/snd_codec_wav.o : $(CDIR)/snd_codec_wav.c; $(DO_CC)
|
||||||
|
|
||||||
|
$(B)/client/qal.o : $(CDIR)/qal.c; $(DO_CC)
|
||||||
|
$(B)/client/snd_openal.o : $(CDIR)/snd_openal.c; $(DO_CC)
|
||||||
|
|
||||||
$(B)/client/sv_bot.o : $(SDIR)/sv_bot.c; $(DO_CC)
|
$(B)/client/sv_bot.o : $(SDIR)/sv_bot.c; $(DO_CC)
|
||||||
$(B)/client/sv_client.o : $(SDIR)/sv_client.c; $(DO_CC)
|
$(B)/client/sv_client.o : $(SDIR)/sv_client.c; $(DO_CC)
|
||||||
$(B)/client/sv_ccmds.o : $(SDIR)/sv_ccmds.c; $(DO_CC)
|
$(B)/client/sv_ccmds.o : $(SDIR)/sv_ccmds.c; $(DO_CC)
|
||||||
|
|
|
@ -56,233 +56,285 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#include "../qcommon/q_shared.h"
|
#include "../qcommon/q_shared.h"
|
||||||
#include "../client/snd_local.h"
|
#include "../client/snd_local.h"
|
||||||
|
|
||||||
int snd_inited=0;
|
qboolean snd_inited = qfalse;
|
||||||
|
|
||||||
cvar_t *sndbits;
|
cvar_t *s_sdlBits;
|
||||||
cvar_t *sndspeed;
|
cvar_t *s_sdlSpeed;
|
||||||
cvar_t *sndchannels;
|
cvar_t *s_sdlChannels;
|
||||||
cvar_t *snddevice;
|
cvar_t *s_sdlDevSamps;
|
||||||
cvar_t *sdldevsamps;
|
cvar_t *s_sdlMixSamps;
|
||||||
cvar_t *sdlmixsamps;
|
|
||||||
|
|
||||||
static qboolean use_custom_memset = qfalse;
|
static qboolean use_custom_memset = qfalse;
|
||||||
// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
Snd_Memset
|
||||||
|
|
||||||
|
https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371
|
||||||
|
|
||||||
|
<TTimo> some shitty mess with DMA buffers
|
||||||
|
<TTimo> the mmap'ing permissions were write only
|
||||||
|
<TTimo> and glibc optimized for mmx would do memcpy with a prefetch and a read
|
||||||
|
<TTimo> causing segfaults
|
||||||
|
<TTimo> some other systems would not let you mmap the DMA with read permissions
|
||||||
|
<TTimo> so I think I ended up attempting opening with read/write, then try write only
|
||||||
|
<TTimo> and use my own copy instead of the glibc crap
|
||||||
|
===============
|
||||||
|
*/
|
||||||
void Snd_Memset (void* dest, const int val, const size_t count)
|
void Snd_Memset (void* dest, const int val, const size_t count)
|
||||||
{
|
{
|
||||||
int *pDest;
|
int *pDest;
|
||||||
int i, iterate;
|
int i, iterate;
|
||||||
|
|
||||||
if (!use_custom_memset)
|
if (!use_custom_memset)
|
||||||
{
|
{
|
||||||
Com_Memset(dest,val,count);
|
Com_Memset(dest,val,count);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
iterate = count / sizeof(int);
|
iterate = count / sizeof(int);
|
||||||
pDest = (int*)dest;
|
pDest = (int*)dest;
|
||||||
for(i=0; i<iterate; i++)
|
for(i=0; i<iterate; i++)
|
||||||
{
|
{
|
||||||
pDest[i] = val;
|
pDest[i] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The audio callback. All the magic happens here. */
|
/* The audio callback. All the magic happens here. */
|
||||||
static int dmapos = 0;
|
static int dmapos = 0;
|
||||||
static int dmasize = 0;
|
static int dmasize = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
sdl_audio_callback
|
||||||
|
===============
|
||||||
|
*/
|
||||||
static void sdl_audio_callback(void *userdata, Uint8 *stream, int len)
|
static void sdl_audio_callback(void *userdata, Uint8 *stream, int len)
|
||||||
{
|
{
|
||||||
int pos = (dmapos * (dma.samplebits/8));
|
int pos = (dmapos * (dma.samplebits/8));
|
||||||
if (pos >= dmasize)
|
if (pos >= dmasize)
|
||||||
dmapos = pos = 0;
|
dmapos = pos = 0;
|
||||||
|
|
||||||
if (!snd_inited) /* shouldn't happen, but just in case... */
|
if (!snd_inited) /* shouldn't happen, but just in case... */
|
||||||
{
|
{
|
||||||
memset(stream, '\0', len);
|
memset(stream, '\0', len);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int tobufend = dmasize - pos; /* bytes to buffer's end. */
|
int tobufend = dmasize - pos; /* bytes to buffer's end. */
|
||||||
int len1 = len;
|
int len1 = len;
|
||||||
int len2 = 0;
|
int len2 = 0;
|
||||||
|
|
||||||
if (len1 > tobufend)
|
if (len1 > tobufend)
|
||||||
{
|
{
|
||||||
len1 = tobufend;
|
len1 = tobufend;
|
||||||
len2 = len - len1;
|
len2 = len - len1;
|
||||||
}
|
}
|
||||||
memcpy(stream, dma.buffer + pos, len1);
|
memcpy(stream, dma.buffer + pos, len1);
|
||||||
if (len2 <= 0)
|
if (len2 <= 0)
|
||||||
dmapos += (len1 / (dma.samplebits/8));
|
dmapos += (len1 / (dma.samplebits/8));
|
||||||
else /* wraparound? */
|
else /* wraparound? */
|
||||||
{
|
{
|
||||||
memcpy(stream+len1, dma.buffer, len2);
|
memcpy(stream+len1, dma.buffer, len2);
|
||||||
dmapos = (len2 / (dma.samplebits/8));
|
dmapos = (len2 / (dma.samplebits/8));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (dmapos >= dmasize)
|
|
||||||
dmapos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_audiospec(const char *str, const SDL_AudioSpec *spec)
|
|
||||||
{
|
|
||||||
Com_Printf("%s:\n", str);
|
|
||||||
|
|
||||||
// I'm sorry this is nasty.
|
|
||||||
#define PRINT_AUDIO_FMT(x) \
|
|
||||||
if (spec->format == x) Com_Printf("Format: %s\n", #x); else
|
|
||||||
PRINT_AUDIO_FMT(AUDIO_U8)
|
|
||||||
PRINT_AUDIO_FMT(AUDIO_S8)
|
|
||||||
PRINT_AUDIO_FMT(AUDIO_U16LSB)
|
|
||||||
PRINT_AUDIO_FMT(AUDIO_S16LSB)
|
|
||||||
PRINT_AUDIO_FMT(AUDIO_U16MSB)
|
|
||||||
PRINT_AUDIO_FMT(AUDIO_S16MSB)
|
|
||||||
Com_Printf("Format: UNKNOWN\n");
|
|
||||||
#undef PRINT_AUDIO_FMT
|
|
||||||
|
|
||||||
Com_Printf("Freq: %d\n", (int) spec->freq);
|
|
||||||
Com_Printf("Samples: %d\n", (int) spec->samples);
|
|
||||||
Com_Printf("Channels: %d\n", (int) spec->channels);
|
|
||||||
Com_Printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
qboolean SNDDMA_Init(void)
|
|
||||||
{
|
|
||||||
char drivername[128];
|
|
||||||
SDL_AudioSpec desired;
|
|
||||||
SDL_AudioSpec obtained;
|
|
||||||
int tmp;
|
|
||||||
|
|
||||||
if (snd_inited)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
Com_Printf("SDL Audio driver initializing...\n");
|
|
||||||
|
|
||||||
if (!snddevice) {
|
|
||||||
sndbits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE);
|
|
||||||
sndspeed = Cvar_Get("sndspeed", "0", CVAR_ARCHIVE);
|
|
||||||
sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE);
|
|
||||||
snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE);
|
|
||||||
sdldevsamps = Cvar_Get("sdldevsamps", "0", CVAR_ARCHIVE);
|
|
||||||
sdlmixsamps = Cvar_Get("sdlmixsamps", "0", CVAR_ARCHIVE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SDL_WasInit(SDL_INIT_AUDIO))
|
if (dmapos >= dmasize)
|
||||||
{
|
dmapos = 0;
|
||||||
Com_Printf("Calling SDL_Init(SDL_INIT_AUDIO)...\n");
|
|
||||||
if (SDL_Init(SDL_INIT_AUDIO) == -1)
|
|
||||||
{
|
|
||||||
Com_Printf("SDL_Init(SDL_INIT_AUDIO) failed: %s\n", SDL_GetError());
|
|
||||||
return qfalse;
|
|
||||||
}
|
|
||||||
Com_Printf("SDL_Init(SDL_INIT_AUDIO) passed.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SDL_AudioDriverName(drivername, sizeof (drivername)) == NULL)
|
|
||||||
strcpy(drivername, "(UNKNOWN)");
|
|
||||||
Com_Printf("SDL audio driver is \"%s\"\n", drivername);
|
|
||||||
|
|
||||||
memset(&desired, '\0', sizeof (desired));
|
|
||||||
memset(&obtained, '\0', sizeof (obtained));
|
|
||||||
|
|
||||||
tmp = ((int) sndbits->value);
|
|
||||||
if ((tmp != 16) && (tmp != 8))
|
|
||||||
tmp = 16;
|
|
||||||
|
|
||||||
desired.freq = (int) sndspeed->value;
|
|
||||||
if(!desired.freq) desired.freq = 22050;
|
|
||||||
desired.format = ((tmp == 16) ? AUDIO_S16SYS : AUDIO_U8);
|
|
||||||
|
|
||||||
// I dunno if this is the best idea, but I'll give it a try...
|
|
||||||
// should probably check a cvar for this...
|
|
||||||
if (sdldevsamps->value)
|
|
||||||
desired.samples = sdldevsamps->value;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// just pick a sane default.
|
|
||||||
if (desired.freq <= 11025)
|
|
||||||
desired.samples = 256;
|
|
||||||
else if (desired.freq <= 22050)
|
|
||||||
desired.samples = 512;
|
|
||||||
else if (desired.freq <= 44100)
|
|
||||||
desired.samples = 1024;
|
|
||||||
else
|
|
||||||
desired.samples = 2048; // (*shrug*)
|
|
||||||
}
|
|
||||||
|
|
||||||
desired.channels = (int) sndchannels->value;
|
|
||||||
desired.callback = sdl_audio_callback;
|
|
||||||
|
|
||||||
print_audiospec("Format we requested from SDL audio device", &desired);
|
|
||||||
|
|
||||||
if (SDL_OpenAudio(&desired, &obtained) == -1)
|
|
||||||
{
|
|
||||||
Com_Printf("SDL_OpenAudio() failed: %s\n", SDL_GetError());
|
|
||||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
|
||||||
return qfalse;
|
|
||||||
} // if
|
|
||||||
|
|
||||||
print_audiospec("Format we actually got", &obtained);
|
|
||||||
|
|
||||||
// dma.samples needs to be big, or id's mixer will just refuse to
|
|
||||||
// work at all; we need to keep it significantly bigger than the
|
|
||||||
// amount of SDL callback samples, and just copy a little each time
|
|
||||||
// the callback runs.
|
|
||||||
// 32768 is what the OSS driver filled in here on my system. I don't
|
|
||||||
// know if it's a good value overall, but at least we know it's
|
|
||||||
// reasonable...this is why I let the user override.
|
|
||||||
tmp = sdlmixsamps->value;
|
|
||||||
if (!tmp)
|
|
||||||
tmp = (obtained.samples * obtained.channels) * 10;
|
|
||||||
|
|
||||||
if (tmp & (tmp - 1)) // not a power of two? Seems to confuse something.
|
|
||||||
{
|
|
||||||
int val = 1;
|
|
||||||
while (val < tmp)
|
|
||||||
val <<= 1;
|
|
||||||
|
|
||||||
Com_Printf("WARNING: sdlmixsamps wasn't a power of two (%d),"
|
|
||||||
" so we made it one (%d).\n", tmp, val);
|
|
||||||
tmp = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
dmapos = 0;
|
|
||||||
dma.samplebits = obtained.format & 0xFF; // first byte of format is bits.
|
|
||||||
dma.channels = obtained.channels;
|
|
||||||
dma.samples = tmp;
|
|
||||||
dma.submission_chunk = 1;
|
|
||||||
dma.speed = obtained.freq;
|
|
||||||
dmasize = (dma.samples * (dma.samplebits/8));
|
|
||||||
dma.buffer = calloc(1, dmasize);
|
|
||||||
|
|
||||||
Com_Printf("Starting SDL audio callback...\n");
|
|
||||||
SDL_PauseAudio(0); // start callback.
|
|
||||||
|
|
||||||
Com_Printf("SDL audio initialized.\n");
|
|
||||||
snd_inited = 1;
|
|
||||||
return qtrue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SNDDMA_GetDMAPos(void)
|
static struct
|
||||||
{
|
{
|
||||||
return dmapos;
|
Uint16 enumFormat;
|
||||||
}
|
char *stringFormat;
|
||||||
|
} formatToStringTable[ ] =
|
||||||
|
{
|
||||||
|
{ AUDIO_U8, "AUDIO_U8" },
|
||||||
|
{ AUDIO_S8, "AUDIO_S8" },
|
||||||
|
{ AUDIO_U16LSB, "AUDIO_U16LSB" },
|
||||||
|
{ AUDIO_S16LSB, "AUDIO_S16LSB" },
|
||||||
|
{ AUDIO_U16MSB, "AUDIO_U16MSB" },
|
||||||
|
{ AUDIO_S16MSB, "AUDIO_S16MSB" }
|
||||||
|
};
|
||||||
|
|
||||||
void SNDDMA_Shutdown(void)
|
static int formatToStringTableSize =
|
||||||
|
sizeof( formatToStringTable ) / sizeof( formatToStringTable[ 0 ] );
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
print_audiospec
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static void print_audiospec(const char *str, const SDL_AudioSpec *spec)
|
||||||
{
|
{
|
||||||
Com_Printf("Closing SDL audio device...\n");
|
int i;
|
||||||
SDL_PauseAudio(1);
|
char *fmt = NULL;
|
||||||
SDL_CloseAudio();
|
|
||||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
Com_Printf("%s:\n", str);
|
||||||
free(dma.buffer);
|
|
||||||
dma.buffer = NULL;
|
for( i = 0; i < formatToStringTableSize; i++ ) {
|
||||||
dmapos = dmasize = 0;
|
if( spec->format == formatToStringTable[ i ].enumFormat ) {
|
||||||
snd_inited = 0;
|
fmt = formatToStringTable[ i ].stringFormat;
|
||||||
Com_Printf("SDL audio device shut down.\n");
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( fmt ) {
|
||||||
|
Com_Printf( " Format: %s\n", fmt );
|
||||||
|
} else {
|
||||||
|
Com_Printf( " Format: " S_COLOR_RED "UNKNOWN\n", fmt );
|
||||||
|
}
|
||||||
|
|
||||||
|
Com_Printf( " Freq: %d\n", (int) spec->freq );
|
||||||
|
Com_Printf( " Samples: %d\n", (int) spec->samples );
|
||||||
|
Com_Printf( " Channels: %d\n", (int) spec->channels );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==============
|
===============
|
||||||
|
SNDDMA_Init
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
qboolean SNDDMA_Init(void)
|
||||||
|
{
|
||||||
|
char drivername[128];
|
||||||
|
SDL_AudioSpec desired;
|
||||||
|
SDL_AudioSpec obtained;
|
||||||
|
int tmp;
|
||||||
|
|
||||||
|
if (snd_inited)
|
||||||
|
return qtrue;
|
||||||
|
|
||||||
|
Com_Printf("Initializing SDL audio driver...\n");
|
||||||
|
|
||||||
|
if (!s_sdlBits) {
|
||||||
|
s_sdlBits = Cvar_Get("s_sdlBits", "16", CVAR_ARCHIVE);
|
||||||
|
s_sdlSpeed = Cvar_Get("s_sdlSpeed", "0", CVAR_ARCHIVE);
|
||||||
|
s_sdlChannels = Cvar_Get("s_sdlChannels", "2", CVAR_ARCHIVE);
|
||||||
|
s_sdlDevSamps = Cvar_Get("s_sdlDevSamps", "0", CVAR_ARCHIVE);
|
||||||
|
s_sdlMixSamps = Cvar_Get("s_sdlMixSamps", "0", CVAR_ARCHIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SDL_WasInit(SDL_INIT_AUDIO))
|
||||||
|
{
|
||||||
|
if (SDL_Init(SDL_INIT_AUDIO) == -1)
|
||||||
|
{
|
||||||
|
Com_Printf("SDL_Init(SDL_INIT_AUDIO) failed: %s\n", SDL_GetError());
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_AudioDriverName(drivername, sizeof (drivername)) == NULL)
|
||||||
|
strcpy(drivername, "(UNKNOWN)");
|
||||||
|
Com_Printf("SDL audio driver is \"%s\".\n", drivername);
|
||||||
|
|
||||||
|
memset(&desired, '\0', sizeof (desired));
|
||||||
|
memset(&obtained, '\0', sizeof (obtained));
|
||||||
|
|
||||||
|
tmp = ((int) s_sdlBits->value);
|
||||||
|
if ((tmp != 16) && (tmp != 8))
|
||||||
|
tmp = 16;
|
||||||
|
|
||||||
|
desired.freq = (int) s_sdlSpeed->value;
|
||||||
|
if(!desired.freq) desired.freq = 22050;
|
||||||
|
desired.format = ((tmp == 16) ? AUDIO_S16SYS : AUDIO_U8);
|
||||||
|
|
||||||
|
// I dunno if this is the best idea, but I'll give it a try...
|
||||||
|
// should probably check a cvar for this...
|
||||||
|
if (s_sdlDevSamps->value)
|
||||||
|
desired.samples = s_sdlDevSamps->value;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// just pick a sane default.
|
||||||
|
if (desired.freq <= 11025)
|
||||||
|
desired.samples = 256;
|
||||||
|
else if (desired.freq <= 22050)
|
||||||
|
desired.samples = 512;
|
||||||
|
else if (desired.freq <= 44100)
|
||||||
|
desired.samples = 1024;
|
||||||
|
else
|
||||||
|
desired.samples = 2048; // (*shrug*)
|
||||||
|
}
|
||||||
|
|
||||||
|
desired.channels = (int) s_sdlChannels->value;
|
||||||
|
desired.callback = sdl_audio_callback;
|
||||||
|
|
||||||
|
if (SDL_OpenAudio(&desired, &obtained) == -1)
|
||||||
|
{
|
||||||
|
Com_Printf("SDL_OpenAudio() failed: %s\n", SDL_GetError());
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||||
|
return qfalse;
|
||||||
|
} // if
|
||||||
|
|
||||||
|
print_audiospec("SDL_AudioSpec", &obtained);
|
||||||
|
|
||||||
|
// dma.samples needs to be big, or id's mixer will just refuse to
|
||||||
|
// work at all; we need to keep it significantly bigger than the
|
||||||
|
// amount of SDL callback samples, and just copy a little each time
|
||||||
|
// the callback runs.
|
||||||
|
// 32768 is what the OSS driver filled in here on my system. I don't
|
||||||
|
// know if it's a good value overall, but at least we know it's
|
||||||
|
// reasonable...this is why I let the user override.
|
||||||
|
tmp = s_sdlMixSamps->value;
|
||||||
|
if (!tmp)
|
||||||
|
tmp = (obtained.samples * obtained.channels) * 10;
|
||||||
|
|
||||||
|
if (tmp & (tmp - 1)) // not a power of two? Seems to confuse something.
|
||||||
|
{
|
||||||
|
int val = 1;
|
||||||
|
while (val < tmp)
|
||||||
|
val <<= 1;
|
||||||
|
|
||||||
|
tmp = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
dmapos = 0;
|
||||||
|
dma.samplebits = obtained.format & 0xFF; // first byte of format is bits.
|
||||||
|
dma.channels = obtained.channels;
|
||||||
|
dma.samples = tmp;
|
||||||
|
dma.submission_chunk = 1;
|
||||||
|
dma.speed = obtained.freq;
|
||||||
|
dmasize = (dma.samples * (dma.samplebits/8));
|
||||||
|
dma.buffer = calloc(1, dmasize);
|
||||||
|
|
||||||
|
Com_Printf("Starting SDL audio callback...\n");
|
||||||
|
SDL_PauseAudio(0); // start callback.
|
||||||
|
|
||||||
|
Com_Printf("SDL audio initialized.\n");
|
||||||
|
snd_inited = qtrue;
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
SNDDMA_GetDMAPos
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
int SNDDMA_GetDMAPos(void)
|
||||||
|
{
|
||||||
|
return dmapos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
SNDDMA_Shutdown
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
void SNDDMA_Shutdown(void)
|
||||||
|
{
|
||||||
|
Com_Printf("Closing SDL audio device...\n");
|
||||||
|
SDL_PauseAudio(1);
|
||||||
|
SDL_CloseAudio();
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||||
|
free(dma.buffer);
|
||||||
|
dma.buffer = NULL;
|
||||||
|
dmapos = dmasize = 0;
|
||||||
|
snd_inited = qfalse;
|
||||||
|
Com_Printf("SDL audio device shut down.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
SNDDMA_Submit
|
SNDDMA_Submit
|
||||||
|
|
||||||
Send sound to device if buffer isn't really the dma buffer
|
Send sound to device if buffer isn't really the dma buffer
|
||||||
|
@ -290,15 +342,17 @@ Send sound to device if buffer isn't really the dma buffer
|
||||||
*/
|
*/
|
||||||
void SNDDMA_Submit(void)
|
void SNDDMA_Submit(void)
|
||||||
{
|
{
|
||||||
SDL_UnlockAudio();
|
SDL_UnlockAudio();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
SNDDMA_BeginPainting
|
||||||
|
===============
|
||||||
|
*/
|
||||||
void SNDDMA_BeginPainting (void)
|
void SNDDMA_BeginPainting (void)
|
||||||
{
|
{
|
||||||
SDL_LockAudio();
|
SDL_LockAudio();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_SDL_SOUND
|
#endif // USE_SDL_SOUND
|
||||||
|
|
||||||
// end of linux_snd_sdl.c ...
|
|
||||||
|
|
||||||
|
|
|
@ -109,13 +109,16 @@ follows:
|
||||||
|
|
||||||
...and comment out/remove the duplicated code marked by '>'.
|
...and comment out/remove the duplicated code marked by '>'.
|
||||||
|
|
||||||
4. If you didn't install the DirectX SDK in C:\DXSDK\, edit DXSDK_DIR in
|
4. If you didn't install the DirectX SDK in C:\DXSDK\, add DXSDK_DIR to
|
||||||
code/unix/Makefile to reflect the new location.
|
code/unix/Makefile.local to reflect the new location.
|
||||||
5. Perform the usual precompilation sacrificial ritual.
|
5. If you want OpenAL support, aquire some OpenAL headers and put them in
|
||||||
6. Open an MSys terminal, and follow the instructions for compiling on Linux.
|
/include/AL/ beneath your MinGW dir. If not, add "USE_OPENAL=0" to
|
||||||
7. Steal underpants
|
code/unix/Makefile.local.
|
||||||
8. ????
|
6. Perform the usual precompilation sacrificial ritual.
|
||||||
9. Profit!
|
7. Open an MSys terminal, and follow the instructions for compiling on Linux.
|
||||||
|
8. Steal underpants
|
||||||
|
9. ?????
|
||||||
|
10. Profit!
|
||||||
|
|
||||||
Creating mods compatible with Q3 1.32b
|
Creating mods compatible with Q3 1.32b
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
Loading…
Reference in a new issue