summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Nazarov <skuller@skuller.net>2010-05-09 17:06:27 +0000
committerAndrey Nazarov <skuller@skuller.net>2010-05-09 17:06:27 +0000
commit633c832e43c42bce0a685a93acfc3937c84ed6bb (patch)
tree93f1da6ad3d2e66ec52a6b7548343dccb67facdf
parent1f3c71bf0acc8cf7d8893acfdc4ed0e24dde2e0e (diff)
Added support for OpenAL sound output, activated by setting ‘s_enable’ cvar to 2.
Added ‘al_driver’ cvar for choosing what OpenAL library to link dynamically with.
-rw-r--r--build/q2pro.mk4
-rwxr-xr-xconfigure15
-rw-r--r--source/files.h2
-rw-r--r--source/qal_api.c122
-rw-r--r--source/qal_api.h104
-rw-r--r--source/snd_al.c311
-rw-r--r--source/snd_local.h58
-rw-r--r--source/snd_main.c302
-rw-r--r--source/snd_mem.c114
-rw-r--r--source/sys_public.h5
-rw-r--r--source/sys_unix.c14
-rw-r--r--source/sys_win.c16
12 files changed, 866 insertions, 201 deletions
diff --git a/build/q2pro.mk b/build/q2pro.mk
index 8531380..19e24ac 100644
--- a/build/q2pro.mk
+++ b/build/q2pro.mk
@@ -45,6 +45,10 @@ SRCFILES+=m_flash.c \
snd_mem.c \
snd_mix.c
+ifdef USE_OPENAL
+SRCFILES+=snd_al.c qal_api.c
+endif
+
ifdef USE_UI
SRCFILES+=ui_atoms.c \
ui_confirm.c \
diff --git a/configure b/configure
index 44d89cb..efa5758 100755
--- a/configure
+++ b/configure
@@ -81,6 +81,7 @@ homedir="~/.q2pro"
sitecfg="/etc/default/q2pro"
# use flags
+use_openal="no"
use_dsound="no"
use_dinput="no"
use_lirc="no"
@@ -114,6 +115,7 @@ democache=".democache"
screenshots="screenshots"
scoreshots="scoreshots"
gldriver="libGL.so.1"
+aldriver="libopenal.so.1"
indriver=""
vid_modelist="640x480 800x600 1024x768"
vid_geometry="640x480"
@@ -149,6 +151,8 @@ for opt do
;;
--enable-baseq2) use_baseq2="yes"
;;
+ --enable-openal) use_openal="yes"
+ ;;
--enable-dsound) use_dsound="yes"
;;
--enable-dinput) use_dinput="yes"
@@ -213,8 +217,10 @@ echo " --disable-client do not build graphical client"
echo " --enable-server build dedicated server"
echo " --enable-baseq2 build baseq2 game module"
echo " --enable-mingw enable Windows build"
+echo " --enable-openal enable OpenAL sound interface"
echo " --enable-dsound enable direct sound driver"
echo " --enable-dinput enable direct input driver"
+echo " --enable-lirc enable LIRC input interface"
echo " --disable-zlib disable linking with zlib"
echo " --disable-tga disable TGA images support"
echo " --enable-png enable PNG images support"
@@ -300,6 +306,7 @@ if [ "$mingw" = "yes" ]; then
libsuffix=".dll"
use_sdl="no"
gldriver="opengl32"
+ aldriver="soft_oal"
exported="__attribute__((dllexport))"
homedir=""
asmflags="-DUNDERSCORES"
@@ -398,6 +405,7 @@ if [ "$use_client" = "yes" ]; then
echo "Refresh type $use_ref"
echo "Direct input $use_dinput"
echo "Direct sound $use_dsound"
+ echo "OpenAL support $use_openal"
if [ "$mingw" = "no" ]; then
echo "LIRC support $use_lirc"
fi
@@ -420,6 +428,7 @@ if [ "$use_client" = "yes" ]; then
targets="$targets q2pro"
executables="$executables q2pro$exesuffix"
else
+ use_openal="no"
use_dsound="no"
use_dinput="no"
use_lirc="no"
@@ -592,6 +601,12 @@ if [ "$use_sdl" = "yes" ]; then
fi
fi
+if [ "$use_openal" = "yes" ]; then
+ echo "USE_OPENAL=yes" >> $config_mk
+ echo "#define DEFAULT_OPENAL_DRIVER \"$aldriver\"" >> $config_h
+ echo "#define USE_OPENAL 1" >> $config_h
+fi
+
if [ "$use_dsound" = "yes" ]; then
echo "USE_DSOUND=yes" >> $config_mk
echo "#define USE_DSOUND 1" >> $config_h
diff --git a/source/files.h b/source/files.h
index 03acfb6..b0a9d29 100644
--- a/source/files.h
+++ b/source/files.h
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAX_LISTED_FILES 4096
-typedef struct {
+typedef struct file_info_s {
size_t size;
time_t ctime;
time_t mtime;
diff --git a/source/qal_api.c b/source/qal_api.c
new file mode 100644
index 0000000..c2f53e7
--- /dev/null
+++ b/source/qal_api.c
@@ -0,0 +1,122 @@
+/*
+Copyright (C) 2010 skuller.net
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "com_local.h"
+#include "sys_public.h"
+#include "qal_api.h"
+#include <AL/alc.h>
+
+#define QALC_IMP \
+ QAL( LPALCCREATECONTEXT, alcCreateContext ); \
+ QAL( LPALCMAKECONTEXTCURRENT, alcMakeContextCurrent ); \
+ QAL( LPALCPROCESSCONTEXT, alcProcessContext ); \
+ QAL( LPALCSUSPENDCONTEXT, alcSuspendContext ); \
+ QAL( LPALCDESTROYCONTEXT, alcDestroyContext ); \
+ QAL( LPALCGETCURRENTCONTEXT, alcGetCurrentContext ); \
+ QAL( LPALCGETCONTEXTSDEVICE, alcGetContextsDevice ); \
+ QAL( LPALCOPENDEVICE, alcOpenDevice ); \
+ QAL( LPALCCLOSEDEVICE, alcCloseDevice ); \
+ QAL( LPALCGETERROR, alcGetError ); \
+ QAL( LPALCISEXTENSIONPRESENT, alcIsExtensionPresent ); \
+ QAL( LPALCGETPROCADDRESS, alcGetProcAddress ); \
+ QAL( LPALCGETENUMVALUE, alcGetEnumValue ); \
+ QAL( LPALCGETSTRING, alcGetString ); \
+ QAL( LPALCGETINTEGERV, alcGetIntegerv ); \
+ QAL( LPALCCAPTUREOPENDEVICE, alcCaptureOpenDevice ); \
+ QAL( LPALCCAPTURECLOSEDEVICE, alcCaptureCloseDevice ); \
+ QAL( LPALCCAPTURESTART, alcCaptureStart ); \
+ QAL( LPALCCAPTURESTOP, alcCaptureStop ); \
+ QAL( LPALCCAPTURESAMPLES, alcCaptureSamples );
+
+static cvar_t *al_driver;
+
+static void *handle;
+static ALCdevice *device;
+static ALCcontext *context;
+
+#define QAL(type,func) static type q##func;
+QALC_IMP
+#undef QAL
+
+#define QAL(type,func) type q##func;
+QAL_IMP
+#undef QAL
+
+void QAL_Shutdown( void ) {
+ if( context ) {
+ qalcMakeContextCurrent( NULL );
+ qalcDestroyContext( context );
+ context = NULL;
+ }
+ if( device ) {
+ qalcCloseDevice( device );
+ device = NULL;
+ }
+
+#define QAL(type,func) q##func = NULL;
+QALC_IMP
+QAL_IMP
+#undef QAL
+
+ Sys_FreeLibrary( handle );
+ handle = NULL;
+}
+
+qboolean QAL_Init( void ) {
+ al_driver = Cvar_Get( "al_driver", DEFAULT_OPENAL_DRIVER, 0 );
+
+ Sys_LoadLibrary( al_driver->string, NULL, &handle );
+ if( !handle ) {
+ return qfalse;
+ }
+
+#define QAL(type,func) q##func = Sys_GetProcAddress( handle, #func );
+QALC_IMP
+QAL_IMP
+#undef QAL
+
+ Com_DPrintf( "...opening OpenAL device: " );
+ device = qalcOpenDevice( NULL );
+ if( !device ) {
+ goto fail;
+ }
+ Com_DPrintf( "ok\n" );
+
+ Com_DPrintf( "...creating OpenAL context: " );
+ context = qalcCreateContext( device, NULL );
+ if( !context ) {
+ goto fail;
+ }
+ Com_DPrintf( "ok\n" );
+
+ Com_DPrintf( "...making context current: " );
+ if( !qalcMakeContextCurrent( context ) ) {
+ goto fail;
+ }
+ Com_DPrintf( "ok\n" );
+
+ return qtrue;
+
+fail:
+ Com_DPrintf( "failed\n" );
+ QAL_Shutdown();
+ return qfalse;
+}
+
diff --git a/source/qal_api.h b/source/qal_api.h
new file mode 100644
index 0000000..74c8c51
--- /dev/null
+++ b/source/qal_api.h
@@ -0,0 +1,104 @@
+/*
+Copyright (C) 2010 skuller.net
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <AL/al.h>
+
+#define QAL_IMP \
+ QAL( LPALENABLE, alEnable ); \
+ QAL( LPALDISABLE, alDisable ); \
+ QAL( LPALISENABLED, alIsEnabled ); \
+ QAL( LPALGETSTRING, alGetString ); \
+ QAL( LPALGETBOOLEANV, alGetBooleanv ); \
+ QAL( LPALGETINTEGERV, alGetIntegerv ); \
+ QAL( LPALGETFLOATV, alGetFloatv ); \
+ QAL( LPALGETDOUBLEV, alGetDoublev ); \
+ QAL( LPALGETBOOLEAN, alGetBoolean ); \
+ QAL( LPALGETINTEGER, alGetInteger ); \
+ QAL( LPALGETFLOAT, alGetFloat ); \
+ QAL( LPALGETDOUBLE, alGetDouble ); \
+ QAL( LPALGETERROR, alGetError ); \
+ QAL( LPALISEXTENSIONPRESENT, alIsExtensionPresent ); \
+ QAL( LPALGETPROCADDRESS, alGetProcAddress ); \
+ QAL( LPALGETENUMVALUE, alGetEnumValue ); \
+ QAL( LPALLISTENERF, alListenerf ); \
+ QAL( LPALLISTENER3F, alListener3f ); \
+ QAL( LPALLISTENERFV, alListenerfv ); \
+ QAL( LPALLISTENERI, alListeneri ); \
+ QAL( LPALLISTENER3I, alListener3i ); \
+ QAL( LPALLISTENERIV, alListeneriv ); \
+ QAL( LPALGETLISTENERF, alGetListenerf ); \
+ QAL( LPALGETLISTENER3F, alGetListener3f ); \
+ QAL( LPALGETLISTENERFV, alGetListenerfv ); \
+ QAL( LPALGETLISTENERI, alGetListeneri ); \
+ QAL( LPALGETLISTENER3I, alGetListener3i ); \
+ QAL( LPALGETLISTENERIV, alGetListeneriv ); \
+ QAL( LPALGENSOURCES, alGenSources ); \
+ QAL( LPALDELETESOURCES, alDeleteSources ); \
+ QAL( LPALISSOURCE, alIsSource ); \
+ QAL( LPALSOURCEF, alSourcef ); \
+ QAL( LPALSOURCE3F, alSource3f ); \
+ QAL( LPALSOURCEFV, alSourcefv ); \
+ QAL( LPALSOURCEI, alSourcei ); \
+ QAL( LPALSOURCE3I, alSource3i ); \
+ QAL( LPALSOURCEIV, alSourceiv ); \
+ QAL( LPALGETSOURCEF, alGetSourcef ); \
+ QAL( LPALGETSOURCE3F, alGetSource3f ); \
+ QAL( LPALGETSOURCEFV, alGetSourcefv ); \
+ QAL( LPALGETSOURCEI, alGetSourcei ); \
+ QAL( LPALGETSOURCE3I, alGetSource3i ); \
+ QAL( LPALGETSOURCEIV, alGetSourceiv ); \
+ QAL( LPALSOURCEPLAYV, alSourcePlayv ); \
+ QAL( LPALSOURCESTOPV, alSourceStopv ); \
+ QAL( LPALSOURCEREWINDV, alSourceRewindv ); \
+ QAL( LPALSOURCEPAUSEV, alSourcePausev ); \
+ QAL( LPALSOURCEPLAY, alSourcePlay ); \
+ QAL( LPALSOURCESTOP, alSourceStop ); \
+ QAL( LPALSOURCEREWIND, alSourceRewind ); \
+ QAL( LPALSOURCEPAUSE, alSourcePause ); \
+ QAL( LPALSOURCEQUEUEBUFFERS, alSourceQueueBuffers ); \
+ QAL( LPALSOURCEUNQUEUEBUFFERS, alSourceUnqueueBuffers ); \
+ QAL( LPALGENBUFFERS, alGenBuffers ); \
+ QAL( LPALDELETEBUFFERS, alDeleteBuffers ); \
+ QAL( LPALISBUFFER, alIsBuffer ); \
+ QAL( LPALBUFFERDATA, alBufferData ); \
+ QAL( LPALBUFFERF, alBufferf ); \
+ QAL( LPALBUFFER3F, alBuffer3f ); \
+ QAL( LPALBUFFERFV, alBufferfv ); \
+ QAL( LPALBUFFERI, alBufferi ); \
+ QAL( LPALBUFFER3I, alBuffer3i ); \
+ QAL( LPALBUFFERIV, alBufferiv ); \
+ QAL( LPALGETBUFFERF, alGetBufferf ); \
+ QAL( LPALGETBUFFER3F, alGetBuffer3f ); \
+ QAL( LPALGETBUFFERFV, alGetBufferfv ); \
+ QAL( LPALGETBUFFERI, alGetBufferi ); \
+ QAL( LPALGETBUFFER3I, alGetBuffer3i ); \
+ QAL( LPALGETBUFFERIV, alGetBufferiv ); \
+ QAL( LPALDOPPLERFACTOR, alDopplerFactor ); \
+ QAL( LPALDOPPLERVELOCITY, alDopplerVelocity ); \
+ QAL( LPALSPEEDOFSOUND, alSpeedOfSound ); \
+ QAL( LPALDISTANCEMODEL, alDistanceModel );
+
+#define QAL(type,func) extern type q##func;
+QAL_IMP
+#undef QAL
+
+qboolean QAL_Init( void );
+void QAL_Shutdown( void );
+
diff --git a/source/snd_al.c b/source/snd_al.c
new file mode 100644
index 0000000..30b5143
--- /dev/null
+++ b/source/snd_al.c
@@ -0,0 +1,311 @@
+/*
+Copyright (C) 2010 skuller.net
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "cl_local.h"
+#include "snd_local.h"
+#include "qal_api.h"
+
+// translates from AL coordinate system to quake
+#define OAL_POS3f(v) -v[1], v[2], -v[0]
+
+static ALuint s_srcnums[MAX_CHANNELS];
+static int s_framecount;
+
+void AL_SoundInfo( void ) {
+ Com_Printf( "AL_VENDOR: %s\n", qalGetString( AL_VENDOR ) );
+ Com_Printf( "AL_RENDERER: %s\n", qalGetString( AL_RENDERER ) );
+ Com_Printf( "AL_VERSION: %s\n", qalGetString( AL_VERSION ) );
+ Com_Printf( "AL_EXTENSIONS: %s\n", qalGetString( AL_EXTENSIONS ) );
+}
+
+static void AL_ShowError( const char *func ) {
+ ALenum err;
+
+ if( ( err = qalGetError() ) != AL_NO_ERROR ) {
+ Com_EPrintf( "%s: %s\n", func, qalGetString( err ) );
+ }
+}
+
+qboolean AL_Init( void ) {
+ if( !QAL_Init() ) {
+ Com_EPrintf( "OpenAL failed to initialize.\n" );
+ return qfalse;
+ }
+
+ // generate source names
+ qalGenSources( MAX_CHANNELS, s_srcnums );
+ AL_ShowError( __func__ );
+
+ Com_Printf( "OpenAL initialized.\n" );
+ return qtrue;
+}
+
+void AL_Shutdown( void ) {
+ Com_Printf( "Shutting down OpenAL.\n" );
+
+ if( s_srcnums[0] ) {
+ // delete source names
+ qalDeleteSources( MAX_CHANNELS, s_srcnums );
+ memset( s_srcnums, 0, sizeof( s_srcnums ) );
+ }
+
+ QAL_Shutdown();
+}
+
+sfxcache_t *AL_UploadSfx( sfx_t *s ) {
+ sfxcache_t *sc;
+ ALsizei size = s_info.samples * s_info.width;
+ ALenum format = s_info.width == 2 ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8;
+ ALuint name;
+
+ qalGenBuffers( 1, &name );
+ qalBufferData( name, format, s_info.data, size, s_info.rate );
+ AL_ShowError( __func__ );
+
+ // allocate placeholder sfxcache
+ sc = s->cache = S_Malloc( sizeof( *sc ) );
+ sc->length = s_info.samples / s_info.rate; // in seconds
+ sc->loopstart = s_info.loopstart;
+ sc->width = s_info.width;
+ sc->size = size;
+ sc->bufnum = name;
+
+ return sc;
+}
+
+void AL_DeleteSfx( sfx_t *s ) {
+ sfxcache_t *sc;
+ ALuint name;
+
+ sc = s->cache;
+ if( !sc ) {
+ return;
+ }
+
+ name = sc->bufnum;
+ qalDeleteBuffers( 1, &name );
+}
+
+static void AL_Spatialize( channel_t *ch ) {
+ vec3_t origin;
+
+ // anything coming from the view entity will always be full volume
+ if( ch->entnum == -1 || ch->entnum == listener_entnum ) {
+ VectorCopy( listener_origin, origin );
+ } else if( ch->fixed_origin ) {
+ VectorCopy( ch->origin, origin );
+ } else {
+ CL_GetEntitySoundOrigin( ch->entnum, origin );
+ }
+
+ qalSource3f( ch->srcnum, AL_POSITION, OAL_POS3f( origin ) );
+}
+
+void AL_StopChannel( channel_t *ch ) {
+ // stop it
+ qalSourceStop( ch->srcnum );
+ qalSourcei( ch->srcnum, AL_BUFFER, AL_NONE );
+ AL_ShowError( __func__ );
+ memset (ch, 0, sizeof(*ch));
+}
+
+void AL_PlayChannel( channel_t *ch ) {
+ sfxcache_t *sc = ch->sfx->cache;
+
+ ch->srcnum = s_srcnums[ch - channels];
+ qalSourcei( ch->srcnum, AL_BUFFER, sc->bufnum );
+ //qalSourcei( ch->srcnum, AL_LOOPING, sc->loopstart == -1 ? AL_FALSE : AL_TRUE );
+ qalSourcei( ch->srcnum, AL_LOOPING, ch->autosound ? AL_TRUE : AL_FALSE );
+ qalSourcef( ch->srcnum, AL_GAIN, ch->master_vol );
+#if 0
+ // anything coming from the view entity will always be full volume
+ if( ch->entnum == -1 || ch->entnum == listener_entnum ) {
+ qalSourcef( ch->srcnum, AL_MIN_GAIN, 1 );
+ } else {
+ qalSourcef( ch->srcnum, AL_MIN_GAIN, 0 );
+ }
+#endif
+ qalSourcef( ch->srcnum, AL_REFERENCE_DISTANCE, SOUND_FULLVOLUME );
+ qalSourcef( ch->srcnum, AL_MAX_DISTANCE, 8192 );
+ qalSourcef( ch->srcnum, AL_ROLLOFF_FACTOR, ch->dist_mult * ( 8192 - SOUND_FULLVOLUME ) );
+
+ AL_Spatialize( ch );
+
+ // play it
+ qalSourcePlay( ch->srcnum );
+ AL_ShowError( __func__ );
+}
+
+static void AL_IssuePlaysounds( void ) {
+ playsound_t *ps;
+
+ // start any playsounds
+ while (1) {
+ ps = s_pendingplays.next;
+ if (ps == &s_pendingplays)
+ break; // no more pending sounds
+ if (ps->begin > paintedtime)
+ break;
+ S_IssuePlaysound (ps);
+ }
+}
+
+void AL_StopAllChannels( void ) {
+ int i;
+ channel_t *ch;
+
+ ch = channels;
+ for( i = 0; i < MAX_CHANNELS; i++, ch++ ) {
+ if (!ch->sfx)
+ continue;
+ AL_StopChannel( ch );
+ }
+}
+
+static channel_t *AL_FindLoopingSound( int entnum, sfx_t *sfx ) {
+ int i;
+ channel_t *ch;
+
+ ch = channels;
+ for( i = 0; i < MAX_CHANNELS; i++, ch++ ) {
+ if( !ch->sfx )
+ continue;
+ if( !ch->autosound )
+ continue;
+ if( ch->entnum != entnum )
+ continue;
+ if( ch->sfx != sfx )
+ continue;
+ return ch;
+ }
+ return NULL;
+}
+
+static void AL_AddLoopSounds( void ) {
+ int i;
+ int sounds[MAX_PACKET_ENTITIES];
+ channel_t *ch;
+ sfx_t *sfx;
+ sfxcache_t *sc;
+ int num;
+ entity_state_t *ent;
+
+ if( cls.state != ca_active || sv_paused->integer || !s_ambient->integer ) {
+ return;
+ }
+
+ S_BuildSoundList( sounds );
+
+ for( i = 0; i < cl.frame.numEntities; i++ ) {
+ if (!sounds[i])
+ continue;
+
+ sfx = S_SfxForHandle( cl.sound_precache[sounds[i]] );
+ if (!sfx)
+ continue; // bad sound effect
+ sc = sfx->cache;
+ if (!sc)
+ continue;
+
+ num = ( cl.frame.firstEntity + i ) & PARSE_ENTITIES_MASK;
+ ent = &cl.entityStates[num];
+
+ ch = AL_FindLoopingSound( ent->number, sfx );
+ if( ch ) {
+ ch->autoframe = s_framecount;
+ continue;
+ }
+
+ // allocate a channel
+ ch = S_PickChannel(0, 0);
+ if (!ch)
+ continue;
+
+ ch->autosound = qtrue; // remove next frame
+ ch->autoframe = s_framecount;
+ ch->sfx = sfx;
+ ch->entnum = ent->number;
+ ch->master_vol = 1;
+ ch->dist_mult = SOUND_LOOPATTENUATE;
+ ch->end = paintedtime + sc->length;
+
+ AL_PlayChannel( ch );
+ }
+}
+
+void AL_Update( void ) {
+ int i;
+ channel_t *ch;
+ vec_t orientation[6];
+
+ paintedtime = cl.time;
+
+ qalListener3f( AL_POSITION, OAL_POS3f( listener_origin ) );
+ orientation[0] = -listener_forward[1];
+ orientation[1] = listener_forward[2];
+ orientation[2] = -listener_forward[0];
+ orientation[3] = -listener_up[1];
+ orientation[4] = listener_up[2];
+ orientation[5] = -listener_up[0];
+ qalListenerfv( AL_ORIENTATION, orientation );
+ qalListenerf( AL_GAIN, s_volume->value );
+ qalDistanceModel( AL_LINEAR_DISTANCE_CLAMPED );
+
+ // update spatialization for dynamic sounds
+ ch = channels;
+ for( i = 0; i < MAX_CHANNELS; i++, ch++ ) {
+ if( !ch->sfx )
+ continue;
+
+ if( ch->autosound ) {
+ // autosounds are regenerated fresh each frame
+ if( ch->autoframe != s_framecount ) {
+ AL_StopChannel( ch );
+ continue;
+ }
+ } else {
+ ALenum state;
+
+ qalGetSourcei( ch->srcnum, AL_SOURCE_STATE, &state );
+ AL_ShowError( __func__ );
+ if( state == AL_STOPPED ) {
+ AL_StopChannel( ch );
+ continue;
+ }
+ }
+
+#ifdef _DEBUG
+ if (s_show->integer) {
+ Com_Printf ("%.1f %s\n", ch->master_vol, ch->sfx->name);
+ // total++;
+ }
+#endif
+
+ AL_Spatialize(ch); // respatialize channel
+ }
+
+ s_framecount++;
+
+ // add loopsounds
+ AL_AddLoopSounds ();
+
+ AL_IssuePlaysounds();
+}
+
diff --git a/source/snd_local.h b/source/snd_local.h
index c7c4a9a..bc9e842 100644
--- a/source/snd_local.h
+++ b/source/snd_local.h
@@ -31,6 +31,10 @@ typedef struct sfxcache_s
int length;
int loopstart;
int width;
+#if USE_OPENAL
+ int size;
+ int bufnum;
+#endif
byte data[1]; // variable sized
} sfxcache_t;
@@ -82,11 +86,23 @@ typedef struct channel_s
int entchannel; //
vec3_t origin; // only use if fixed_origin is set
vec_t dist_mult; // distance multiplier (attenuation/clipK)
- int master_vol; // 0-255 master volume
+ float master_vol; // 0.0-1.0 master volume
qboolean fixed_origin; // use origin instead of fetching entnum's origin
qboolean autosound; // from an entity->sound, cleared each frame
+#if USE_OPENAL
+ int autoframe;
+ int srcnum;
+#endif
} channel_t;
+typedef struct {
+ char *name;
+ int rate;
+ int width;
+ int loopstart;
+ int samples;
+ byte *data;
+} wavinfo_t;
/*
====================================================================
@@ -112,8 +128,29 @@ typedef struct snddmaAPI_s {
extern snddmaAPI_t snddma;
+#if USE_OPENAL
+void AL_SoundInfo( void );
+qboolean AL_Init( void );
+void AL_Shutdown( void );
+sfxcache_t *AL_UploadSfx( sfx_t *s );
+void AL_DeleteSfx( sfx_t *s );
+void AL_StopChannel( channel_t *ch );
+void AL_PlayChannel( channel_t *ch );
+void AL_StopAllChannels( void );
+void AL_Update( void );
+#endif
+
//====================================================================
+// only begin attenuating sound volumes when outside the FULLVOLUME range
+#define SOUND_FULLVOLUME 80
+
+#define SOUND_LOOPATTENUATE 0.003
+
+typedef enum { SS_NOT, SS_DMA, SS_OAL } sndstarted_t;
+
+extern sndstarted_t s_started;
+
#define MAX_CHANNELS 32
extern channel_t channels[MAX_CHANNELS];
@@ -121,21 +158,28 @@ extern int paintedtime;
extern dma_t dma;
extern playsound_t s_pendingplays;
+extern vec3_t listener_origin;
+extern vec3_t listener_forward;
+extern vec3_t listener_right;
+extern vec3_t listener_up;
+extern int listener_entnum;
+
+extern wavinfo_t s_info;
+
extern cvar_t *s_volume;
extern cvar_t *s_khz;
extern cvar_t *s_testsound;
+extern cvar_t *s_ambient;
+extern cvar_t *s_show;
#define S_Malloc( x ) Z_TagMalloc( x, TAG_SOUND )
#define S_CopyString( x ) Z_TagCopyString( x, TAG_SOUND )
+sfx_t *S_SfxForHandle( qhandle_t hSfx );
void S_InitScaletable (void);
-
sfxcache_t *S_LoadSound (sfx_t *s);
-
+channel_t *S_PickChannel( int entnum, int entchannel );
void S_IssuePlaysound (playsound_t *ps);
-
void S_PaintChannels(int endtime);
-
-// spatializes a channel
-void S_Spatialize(channel_t *ch);
+void S_BuildSoundList( int *sounds );
diff --git a/source/snd_main.c b/source/snd_main.c
index 9930967..1c60fc4 100644
--- a/source/snd_main.c
+++ b/source/snd_main.c
@@ -26,16 +26,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// Internal sound data & structures
// =======================================================================
-// only begin attenuating sound volumes when outside the FULLVOLUME range
-#define SOUND_FULLVOLUME 80
-
-#define SOUND_LOOPATTENUATE 0.003
-
int s_registration_sequence;
channel_t channels[MAX_CHANNELS];
-qboolean sound_started;
+sndstarted_t s_started;
dma_t dma;
@@ -67,16 +62,16 @@ static int s_beginofs;
cvar_t *s_khz;
cvar_t *s_volume;
cvar_t *s_testsound;
+cvar_t *s_ambient;
+cvar_t *s_show;
static cvar_t *s_enable;
#if USE_DSOUND
static cvar_t *s_direct;
#endif
#ifdef _DEBUG
-static cvar_t *s_show;
#endif
static cvar_t *s_mixahead;
-static cvar_t *s_ambient;
void WAVE_FillAPI( snddmaAPI_t *api );
@@ -84,6 +79,8 @@ void WAVE_FillAPI( snddmaAPI_t *api );
void DS_FillAPI( snddmaAPI_t *api );
#endif
+static void S_ClearBuffer (void);
+
snddmaAPI_t snddma;
/*
@@ -93,18 +90,25 @@ console functions
*/
static void S_SoundInfo_f( void ) {
- if( !sound_started ) {
+ if( !s_started ) {
Com_Printf( "Sound system not started.\n" );
return;
}
+
+#if USE_OPENAL
+ if( s_started == SS_OAL ) {
+ AL_SoundInfo();
+ return;
+ }
+#endif
- Com_Printf( "%5d stereo\n", dma.channels - 1 );
+ Com_Printf( "%5d channels\n", dma.channels );
Com_Printf( "%5d samples\n", dma.samples );
Com_Printf( "%5d samplepos\n", dma.samplepos );
Com_Printf( "%5d samplebits\n", dma.samplebits );
Com_Printf( "%5d submission_chunk\n", dma.submission_chunk );
Com_Printf( "%5d speed\n", dma.speed );
- Com_Printf( "0x%p dma buffer\n", dma.buffer );
+ Com_Printf( "%p dma buffer\n", dma.buffer );
}
@@ -120,7 +124,12 @@ static void S_SoundList_f( void ) {
continue;
sc = sfx->cache;
if( sc ) {
- size = sc->length * sc->width;
+#if USE_OPENAL
+ if( s_started == SS_OAL )
+ size = sc->size;
+ else
+#endif
+ size = sc->length * sc->width;
total += size;
if( sc->loopstart >= 0 )
Com_Printf( "L" );
@@ -161,50 +170,62 @@ void S_Init( void ) {
Com_Printf( "------- S_Init -------\n" );
- s_khz = Cvar_Get( "s_khz", "22", CVAR_ARCHIVE|CVAR_SOUND );
+#if USE_OPENAL
+ if( s_enable->integer > 1 ) {
+ if( !AL_Init() ) {
+ Cvar_Set( "s_enable", "1" );
+ } else
+ s_started = SS_OAL;
+
+ }
+ if( !s_started )
+#endif
+ {
+ s_khz = Cvar_Get( "s_khz", "22", CVAR_ARCHIVE|CVAR_SOUND );
+ s_mixahead = Cvar_Get( "s_mixahead", "0.2", CVAR_ARCHIVE );
+ s_testsound = Cvar_Get( "s_testsound", "0", 0 );
#if USE_DSOUND
- s_direct = Cvar_Get( "s_direct", "1", CVAR_ARCHIVE|CVAR_SOUND );
- if( s_direct->integer ) {
- DS_FillAPI( &snddma );
- ret = snddma.Init();
- if( ret != SIS_SUCCESS ) {
- Cvar_Set( "s_direct", "0" );
+ s_direct = Cvar_Get( "s_direct", "1", CVAR_ARCHIVE|CVAR_SOUND );
+ if( s_direct->integer ) {
+ DS_FillAPI( &snddma );
+ ret = snddma.Init();
+ if( ret != SIS_SUCCESS ) {
+ Cvar_Set( "s_direct", "0" );
+ }
}
- }
#endif
- if( ret != SIS_SUCCESS ) {
- WAVE_FillAPI( &snddma );
- ret = snddma.Init();
if( ret != SIS_SUCCESS ) {
- Cvar_Set( "s_enable", "0" );
- return;
+ WAVE_FillAPI( &snddma );
+ ret = snddma.Init();
+ if( ret != SIS_SUCCESS ) {
+ Cvar_Set( "s_enable", "0" );
+ return;
+ }
}
+
+ S_ClearBuffer();
+
+ Com_Printf( "sound sampling rate: %i\n", dma.speed );
+ s_started = SS_DMA;
}
s_volume = Cvar_Get( "s_volume", "0.7", CVAR_ARCHIVE );
- s_mixahead = Cvar_Get( "s_mixahead", "0.2", CVAR_ARCHIVE );
#ifdef _DEBUG
s_show = Cvar_Get( "s_show", "0", 0 );
#endif
- s_testsound = Cvar_Get( "s_testsound", "0", 0 );
s_ambient = Cvar_Get( "s_ambient", "1", 0 );
Cmd_Register( c_sound );
S_InitScaletable();
- sound_started = qtrue;
num_sfx = 0;
paintedtime = 0;
s_registration_sequence = 1;
- Com_Printf( "sound sampling rate: %i\n", dma.speed );
-
- S_StopAllSounds();
-
Com_Printf( "----------------------\n" );
}
@@ -213,6 +234,18 @@ void S_Init( void ) {
// Shutdown sound engine
// =======================================================================
+static void S_FreeSound( sfx_t *sfx ) {
+#if USE_OPENAL
+ if( s_started == SS_OAL )
+ AL_DeleteSfx( sfx );
+#endif
+ if( sfx->cache )
+ Z_Free( sfx->cache );
+ if( sfx->truename )
+ Z_Free( sfx->truename );
+ memset( sfx, 0, sizeof( *sfx ) );
+}
+
void S_FreeAllSounds( void ) {
int i;
sfx_t *sfx;
@@ -221,38 +254,35 @@ void S_FreeAllSounds( void ) {
for( i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++ ) {
if( !sfx->name[0] )
continue;
- if( sfx->cache )
- Z_Free( sfx->cache );
- if( sfx->truename )
- Z_Free( sfx->truename );
- memset( sfx, 0, sizeof( *sfx ) );
+ S_FreeSound( sfx );
}
num_sfx = 0;
}
void S_Shutdown( void ) {
- if( !sound_started )
+ if( !s_started )
return;
- snddma.Shutdown();
-
- sound_started = qfalse;
+ S_StopAllSounds();
+ S_FreeAllSounds();
-#if USE_DSOUND
- s_direct->changed = NULL;
+#if USE_OPENAL
+ if( s_started == SS_OAL )
+ AL_Shutdown();
+ else
#endif
- s_khz->changed = NULL;
+ snddma.Shutdown();
- Cmd_Deregister( c_sound );
+ s_started = SS_NOT;
- S_FreeAllSounds();
+ Cmd_Deregister( c_sound );
Z_LeakTest( TAG_SOUND );
}
void S_Activate( void ) {
- if( sound_started && snddma.Activate ) {
+ if( s_started == SS_DMA && snddma.Activate ) {
S_StopAllSounds();
snddma.Activate( cls.active == ACT_ACTIVATED ? qtrue : qfalse );
}
@@ -268,7 +298,7 @@ void S_Activate( void ) {
S_SfxForHandle
==================
*/
-static sfx_t *S_SfxForHandle( qhandle_t hSfx ) {
+sfx_t *S_SfxForHandle( qhandle_t hSfx ) {
if( !hSfx ) {
return NULL;
}
@@ -353,7 +383,7 @@ S_RegisterSound
qhandle_t S_RegisterSound( const char *name ) {
sfx_t *sfx;
- if( !sound_started )
+ if( !s_started )
return 0;
sfx = S_FindName( name );
@@ -389,18 +419,18 @@ void S_EndRegistration( void ) {
continue;
if( sfx->registration_sequence != s_registration_sequence ) {
// don't need this sound
- if( sfx->cache ) // it is possible to have a leftover
- Z_Free( sfx->cache ); // from a server that didn't finish loading
- if( sfx->truename )
- Z_Free( sfx->truename );
- memset( sfx, 0, sizeof( *sfx ) );
- } else {
- // make sure it is paged in
- sc = sfx->cache;
- if( sc ) {
- size = sc->length * sc->width;
- Com_PageInMemory( sc, size );
- }
+ S_FreeSound( sfx );
+ continue;
+ }
+#if USE_OPENAL
+ if( s_started == SS_OAL )
+ continue;
+#endif
+ // make sure it is paged in
+ sc = sfx->cache;
+ if( sc ) {
+ size = sc->length * sc->width;
+ Com_PageInMemory( sc, size );
}
}
@@ -424,7 +454,7 @@ S_PickChannel
picks a channel based on priorities, empty slots, number of channels
=================
*/
-static channel_t *S_PickChannel( int entnum, int entchannel ) {
+channel_t *S_PickChannel( int entnum, int entchannel ) {
int ch_idx;
int first_to_die;
int life_left;
@@ -462,6 +492,10 @@ static channel_t *S_PickChannel( int entnum, int entchannel ) {
return NULL;
ch = &channels[first_to_die];
+#if USE_OPENAL
+ if( s_started == SS_OAL && ch->sfx )
+ AL_StopChannel( ch );
+#endif
memset( ch, 0, sizeof( *ch ) );
return ch;
@@ -474,7 +508,7 @@ S_SpatializeOrigin
Used for spatializing channels and autosounds
=================
*/
-void S_SpatializeOrigin( const vec3_t origin, float master_vol, float dist_mult, int *left_vol, int *right_vol ) {
+static void S_SpatializeOrigin( const vec3_t origin, float master_vol, float dist_mult, int *left_vol, int *right_vol ) {
vec_t dot;
vec_t dist;
vec_t lscale, rscale, scale;
@@ -505,6 +539,8 @@ void S_SpatializeOrigin( const vec3_t origin, float master_vol, float dist_mult,
lscale = 0.5 * ( 1.0 - dot );
}
+ master_vol *= 255.0;
+
// add in distance effect
scale = ( 1.0 - dist ) * rscale;
*right_vol = (int)( master_vol * scale );
@@ -522,13 +558,13 @@ void S_SpatializeOrigin( const vec3_t origin, float master_vol, float dist_mult,
S_Spatialize
=================
*/
-void S_Spatialize( channel_t *ch ) {
+static void S_Spatialize( channel_t *ch ) {
vec3_t origin;
// anything coming from the view entity will always be full volume
if( ch->entnum == -1 || ch->entnum == listener_entnum ) {
- ch->leftvol = ch->master_vol;
- ch->rightvol = ch->master_vol;
+ ch->leftvol = ch->master_vol * 255;
+ ch->rightvol = ch->master_vol * 255;
return;
}
@@ -624,7 +660,12 @@ void S_IssuePlaysound( playsound_t *ps ) {
VectorCopy( ps->origin, ch->origin );
ch->fixed_origin = ps->fixed_origin;
- S_Spatialize( ch );
+#if USE_OPENAL
+ if( s_started == SS_OAL )
+ AL_PlayChannel( ch );
+ else
+#endif
+ S_Spatialize( ch );
ch->pos = 0;
ch->end = paintedtime + sc->length;
@@ -678,6 +719,24 @@ static sfx_t *S_RegisterSexedSound( int entnum, const char *base ) {
// Start a sound effect
// =======================================================================
+static int S_DriftBeginofs( float timeofs ) {
+ int start;
+
+ // drift s_beginofs
+ start = cl.servertime * 0.001 * dma.speed + s_beginofs;
+ if( start < paintedtime ) {
+ start = paintedtime;
+ s_beginofs = start - ( cl.servertime * 0.001 * dma.speed );
+ } else if ( start > paintedtime + 0.3 * dma.speed ) {
+ start = paintedtime + 0.1 * dma.speed;
+ s_beginofs = start - ( cl.servertime * 0.001 * dma.speed );
+ } else {
+ s_beginofs -= 10;
+ }
+
+ return timeofs ? start + timeofs * dma.speed : paintedtime;
+}
+
/*
====================
S_StartSound
@@ -687,14 +746,12 @@ if pos is NULL, the sound will be dynamically sourced from the entity
Entchannel 0 will never override a playing sound
====================
*/
-void S_StartSound( const vec3_t origin, int entnum, int entchannel, qhandle_t hSfx, float fvol, float attenuation, float timeofs ) {
+void S_StartSound( const vec3_t origin, int entnum, int entchannel, qhandle_t hSfx, float vol, float attenuation, float timeofs ) {
sfxcache_t *sc;
- int vol;
playsound_t *ps, *sort;
- int start;
sfx_t *sfx;
- if( !sound_started )
+ if( !s_started )
return;
if( !( sfx = S_SfxForHandle( hSfx ) ) ) {
@@ -710,8 +767,6 @@ void S_StartSound( const vec3_t origin, int entnum, int entchannel, qhandle_t hS
if( !sc )
return; // couldn't load the sound's data
- vol = fvol*255;
-
// make the playsound_t
ps = S_AllocPlaysound();
if( !ps )
@@ -730,22 +785,12 @@ void S_StartSound( const vec3_t origin, int entnum, int entchannel, qhandle_t hS
ps->volume = vol;
ps->sfx = sfx;
- // drift s_beginofs
- start = cl.servertime * 0.001 * dma.speed + s_beginofs;
- if( start < paintedtime ) {
- start = paintedtime;
- s_beginofs = start - ( cl.servertime * 0.001 * dma.speed );
- } else if ( start > paintedtime + 0.3 * dma.speed ) {
- start = paintedtime + 0.1 * dma.speed;
- s_beginofs = start - ( cl.servertime * 0.001 * dma.speed );
- } else {
- s_beginofs -= 10;
- }
-
- if( !timeofs )
- ps->begin = paintedtime;
+#if USE_OPENAL
+ if( s_started == SS_OAL )
+ ps->begin = paintedtime + timeofs * 1000;
else
- ps->begin = start + timeofs * dma.speed;
+#endif
+ ps->begin = S_DriftBeginofs( timeofs );
// sort into the pending sound list
for( sort = s_pendingplays.next ; sort != &s_pendingplays && sort->begin < ps->begin ; sort = sort->next )
@@ -765,14 +810,14 @@ S_StartLocalSound
==================
*/
void S_StartLocalSound( const char *sound ) {
- if( sound_started ) {
+ if( s_started ) {
qhandle_t sfx = S_RegisterSound( sound );
S_StartSound( NULL, listener_entnum, 0, sfx, 1, 1, 0 );
}
}
void S_StartLocalSound_( const char *sound ) {
- if( sound_started ) {
+ if( s_started ) {
qhandle_t sfx = S_RegisterSound( sound );
S_StartSound( NULL, listener_entnum, 256, sfx, 1, 1, 0 );
}
@@ -784,11 +829,11 @@ void S_StartLocalSound_( const char *sound ) {
S_ClearBuffer
==================
*/
-void S_ClearBuffer (void)
+static void S_ClearBuffer (void)
{
int clear;
-
- if (!sound_started)
+
+ if (s_started != SS_DMA)
return;
if (dma.samplebits == 8)
@@ -811,7 +856,7 @@ void S_StopAllSounds(void)
{
int i;
- if (!sound_started)
+ if (!s_started)
return;
// clear all the playsounds
@@ -827,12 +872,35 @@ void S_StopAllSounds(void)
s_playsounds[i].next->prev = &s_playsounds[i];
}
+#if USE_OPENAL
+ if( s_started == SS_OAL )
+ AL_StopAllChannels();
+#endif
+
// clear all the channels
memset(channels, 0, sizeof(channels));
S_ClearBuffer ();
}
+void S_BuildSoundList( int *sounds ) {
+ int i;
+ int num;
+ entity_state_t *ent;
+
+ for( i = 0; i < cl.frame.numEntities; i++ ) {
+ num = ( cl.frame.firstEntity + i ) & PARSE_ENTITIES_MASK;
+ ent = &cl.entityStates[num];
+ if( s_ambient->integer == 2 && !ent->modelindex ) {
+ sounds[i] = 0;
+ } else if( s_ambient->integer == 3 && ent->number != listener_entnum ) {
+ sounds[i] = 0;
+ } else {
+ sounds[i] = ent->sound;
+ }
+ }
+}
+
/*
==================
S_AddLoopSounds
@@ -854,27 +922,11 @@ static void S_AddLoopSounds (void)
entity_state_t *ent;
centity_t *cent;
- if( sv_paused->integer ) {
- return;
- }
- if( cls.state != ca_active ) {
- return;
- }
- if( !s_ambient->integer ) {
+ if( cls.state != ca_active || sv_paused->integer || !s_ambient->integer ) {
return;
}
- for( i = 0; i < cl.frame.numEntities; i++ ) {
- num = ( cl.frame.firstEntity + i ) & PARSE_ENTITIES_MASK;
- ent = &cl.entityStates[num];
- if( s_ambient->integer == 2 && !ent->modelindex ) {
- sounds[i] = 0;
- } else if( s_ambient->integer == 3 && ent->number != listener_entnum ) {
- sounds[i] = 0;
- } else {
- sounds[i] = ent->sound;
- }
- }
+ S_BuildSoundList( sounds );
for( i = 0; i < cl.frame.numEntities; i++ ) {
if (!sounds[i])
@@ -892,7 +944,7 @@ static void S_AddLoopSounds (void)
cent = &cl_entities[ent->number];
// find the total contribution of all sounds of this type
- S_SpatializeOrigin (cent->lerp_origin, 255.0, SOUND_LOOPATTENUATE,
+ S_SpatializeOrigin (cent->lerp_origin, 1.0, SOUND_LOOPATTENUATE,
&left_total, &right_total);
for (j=i+1 ; j<cl.frame.numEntities ; j++)
{
@@ -904,7 +956,7 @@ static void S_AddLoopSounds (void)
ent = &cl.entityStates[num];
cent = &cl_entities[ent->number];
- S_SpatializeOrigin (cent->lerp_origin, 255.0, SOUND_LOOPATTENUATE,
+ S_SpatializeOrigin (cent->lerp_origin, 1.0, SOUND_LOOPATTENUATE,
&left, &right);
left_total += left;
right_total += right;
@@ -1008,22 +1060,17 @@ void S_Update( void ) {
return;
}
- if (!sound_started)
+ if (!s_started)
return;
// if the laoding plaque is up, clear everything
// out to make sure we aren't looping a dirty
// dma buffer while loading
- if (cls.state == ca_loading )
- {
- /* S_ClearBuffer should be already done in S_StopAllSounds */
+ if (cls.state == ca_loading) {
+ // S_ClearBuffer should be already done in S_StopAllSounds
return;
}
- // rebuild scale tables if volume is modified
- if (s_volume->modified)
- S_InitScaletable ();
-
// set listener entity number
// other parameters should be already set up by CL_CalcViewValues
if( cl.clientNum == -1 || cl.frame.clientNum == CLIENTNUM_NONE ) {
@@ -1032,6 +1079,17 @@ void S_Update( void ) {
listener_entnum = cl.frame.clientNum + 1;
}
+#if USE_OPENAL
+ if( s_started == SS_OAL ) {
+ AL_Update();
+ return;
+ }
+#endif
+
+ // rebuild scale tables if volume is modified
+ if (s_volume->modified)
+ S_InitScaletable ();
+
// update spatialization for dynamic sounds
ch = channels;
for (i=0 ; i<MAX_CHANNELS; i++, ch++)
diff --git a/source/snd_mem.c b/source/snd_mem.c
index 096bc91..883a017 100644
--- a/source/snd_mem.c
+++ b/source/snd_mem.c
@@ -22,13 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "cl_local.h"
#include "snd_local.h"
-typedef struct {
- int rate;
- int width;
- int loopstart;
- int samples;
- byte *data;
-} wavinfo_t;
+wavinfo_t s_info;
/*
@@ -36,7 +30,7 @@ typedef struct {
ResampleSfx
================
*/
-static sfxcache_t *ResampleSfx( sfx_t *sfx, wavinfo_t *info ) {
+static sfxcache_t *ResampleSfx( sfx_t *sfx ) {
int outcount;
int srcsample;
float stepscale;
@@ -44,31 +38,32 @@ static sfxcache_t *ResampleSfx( sfx_t *sfx, wavinfo_t *info ) {
int samplefrac, fracstep;
sfxcache_t *sc;
- stepscale = ( float )info->rate / dma.speed; // this is usually 0.5, 1, or 2
+ stepscale = ( float )s_info.rate / dma.speed; // this is usually 0.5, 1, or 2
- outcount = info->samples / stepscale;
+ outcount = s_info.samples / stepscale;
if( !outcount ) {
+ Com_DPrintf( "%s resampled to zero length\n", s_info.name );
return NULL;
}
- sc = sfx->cache = S_Malloc( outcount * info->width + sizeof( sfxcache_t ) - 1 );
+ sc = sfx->cache = S_Malloc( outcount * s_info.width + sizeof( sfxcache_t ) - 1 );
sc->length = outcount;
- sc->loopstart = info->loopstart == -1 ? -1 : info->loopstart / stepscale;
- sc->width = info->width;
+ sc->loopstart = s_info.loopstart == -1 ? -1 : s_info.loopstart / stepscale;
+ sc->width = s_info.width;
// resample / decimate to the current source rate
//Com_Printf("%s: %f, %d\n",sfx->name,stepscale,sc->width);
if (stepscale == 1) {
// fast special case
if( sc->width == 1 ) {
- memcpy( sc->data, info->data, outcount );
+ memcpy( sc->data, s_info.data, outcount );
} else {
#if __BYTE_ORDER == __LITTLE_ENDIAN
- memcpy( sc->data, info->data, outcount << 1 );
+ memcpy( sc->data, s_info.data, outcount << 1 );
#else
for(i = 0; i < outcount; i++) {
- ((uint16_t *)sc->data)[i] = LittleShort( (( uint16_t * )info->data)[i] );
+ ((uint16_t *)sc->data)[i] = LittleShort( (( uint16_t * )s_info.data)[i] );
}
#endif
}
@@ -80,13 +75,13 @@ static sfxcache_t *ResampleSfx( sfx_t *sfx, wavinfo_t *info ) {
for (i = 0; i < outcount; i++) {
srcsample = samplefrac >> 8;
samplefrac += fracstep;
- sc->data[i] = info->data[srcsample];
+ sc->data[i] = s_info.data[srcsample];
}
} else {
for (i = 0; i < outcount; i++) {
srcsample = samplefrac >> 8;
samplefrac += fracstep;
- ((uint16_t *)sc->data)[i] = LittleShort( (( uint16_t * )info->data)[srcsample] );
+ ((uint16_t *)sc->data)[i] = LittleShort( (( uint16_t * )s_info.data)[srcsample] );
}
}
}
@@ -135,7 +130,7 @@ static int GetLittleLong( void ) {
return val;
}
-static void FindNextChunk( const char *name, uint32_t search ) {
+static void FindNextChunk( uint32_t search ) {
uint32_t chunk, length;
int i;
@@ -149,7 +144,7 @@ static void FindNextChunk( const char *name, uint32_t search ) {
iff_chunk_len = GetLittleLong();
if( iff_chunk_len > iff_end - data_p ) {
Com_DPrintf( "%s: oversize chunk %#x in %s\n",
- __func__, chunk, name );
+ __func__, chunk, s_info.name );
data_p = NULL;
return;
}
@@ -161,12 +156,12 @@ static void FindNextChunk( const char *name, uint32_t search ) {
}
Com_WPrintf( "%s: too many iterations for chunk %#x in %s\n",
- __func__, search, name );
+ __func__, search, s_info.name );
}
-static void FindChunk( const char *name, uint32_t search ) {
+static void FindChunk( uint32_t search ) {
data_p = iff_data;
- FindNextChunk( name, search );
+ FindNextChunk( search );
}
#define TAG_RIFF MakeLong( 'R', 'I', 'F', 'F' )
@@ -182,48 +177,46 @@ static void FindChunk( const char *name, uint32_t search ) {
GetWavinfo
============
*/
-static qboolean GetWavinfo( const char *name, wavinfo_t *info ) {
+static qboolean GetWavinfo( void ) {
int format;
int samples, width;
uint32_t chunk;
- memset( info, 0, sizeof( *info ) );
-
// find "RIFF" chunk
- FindChunk( name, TAG_RIFF );
+ FindChunk( TAG_RIFF );
if( !data_p ) {
- Com_DPrintf( "%s has missing/invalid RIFF chunk\n", name );
+ Com_DPrintf( "%s has missing/invalid RIFF chunk\n", s_info.name );
return qfalse;
}
chunk = GetLittleLong();
if( chunk != TAG_WAVE ) {
- Com_DPrintf( "%s has missing/invalid WAVE chunk\n", name );
+ Com_DPrintf( "%s has missing/invalid WAVE chunk\n", s_info.name );
return qfalse;
}
iff_data = data_p;
// get "fmt " chunk
- FindChunk( name, TAG_fmt );
+ FindChunk( TAG_fmt );
if( !data_p ) {
- Com_DPrintf("%s has missing/invalid fmt chunk\n", name );
+ Com_DPrintf("%s has missing/invalid fmt chunk\n", s_info.name );
return qfalse;
}
format = GetLittleShort();
if( format != 1 ) {
- Com_DPrintf( "%s has non-Microsoft PCM format\n", name );
+ Com_DPrintf( "%s has non-Microsoft PCM format\n", s_info.name );
return qfalse;
}
format = GetLittleShort();
if( format != 1 ) {
- Com_DPrintf( "%s has bad number of channels\n", name );
+ Com_DPrintf( "%s has bad number of channels\n", s_info.name );
return qfalse;
}
- info->rate = GetLittleLong();
- if( info->rate <= 0 ) {
- Com_DPrintf( "%s has bad rate\n", name );
+ s_info.rate = GetLittleLong();
+ if( s_info.rate <= 0 ) {
+ Com_DPrintf( "%s has bad rate\n", s_info.name );
return qfalse;
}
@@ -232,23 +225,23 @@ static qboolean GetWavinfo( const char *name, wavinfo_t *info ) {
width = GetLittleShort();
switch( width ) {
case 8:
- info->width = 1;
+ s_info.width = 1;
break;
case 16:
- info->width = 2;
+ s_info.width = 2;
break;
default:
- Com_DPrintf( "%s has bad width\n", name );
+ Com_DPrintf( "%s has bad width\n", s_info.name );
return qfalse;
}
// get cue chunk
- FindChunk( name, TAG_cue );
+ FindChunk( TAG_cue );
if( data_p ) {
data_p += 24;
- info->loopstart = GetLittleLong();
+ s_info.loopstart = GetLittleLong();
- FindNextChunk( name, TAG_LIST );
+ FindNextChunk( TAG_LIST );
if( data_p ) {
data_p += 20;
chunk = GetLittleLong();
@@ -256,36 +249,36 @@ static qboolean GetWavinfo( const char *name, wavinfo_t *info ) {
// this is not a proper parse, but it works with cooledit...
data_p += 16;
samples = GetLittleLong(); // samples in loop
- info->samples = info->loopstart + samples;
+ s_info.samples = s_info.loopstart + samples;
}
}
} else {
- info->loopstart = -1;
+ s_info.loopstart = -1;
}
// find data chunk
- FindChunk( name, TAG_data );
+ FindChunk( TAG_data );
if( !data_p ) {
- Com_DPrintf( "%s has missing/invalid data chunk\n", name );
+ Com_DPrintf( "%s has missing/invalid data chunk\n", s_info.name );
return qfalse;
}
- samples = iff_chunk_len / info->width;
+ samples = iff_chunk_len / s_info.width;
if( !samples ) {
- Com_DPrintf( "%s has zero length\n", name );
+ Com_DPrintf( "%s has zero length\n", s_info.name );
return qfalse;
}
- if( info->samples ) {
- if( samples < info->samples ) {
- Com_DPrintf( "%s has bad loop length\n", name );
+ if( s_info.samples ) {
+ if( samples < s_info.samples ) {
+ Com_DPrintf( "%s has bad loop length\n", s_info.name );
return qfalse;
}
} else {
- info->samples = samples;
+ s_info.samples = samples;
}
- info->data = data_p;
+ s_info.data = data_p;
return qtrue;
}
@@ -298,7 +291,6 @@ S_LoadSound
sfxcache_t *S_LoadSound (sfx_t *s) {
char namebuffer[MAX_QPATH];
byte *data;
- wavinfo_t info;
sfxcache_t *sc;
size_t size;
char *name;
@@ -328,12 +320,18 @@ sfxcache_t *S_LoadSound (sfx_t *s) {
return NULL;
}
+ memset( &s_info, 0, sizeof( s_info ) );
+ s_info.name = namebuffer;
+
iff_data = data;
iff_end = data + size;
- if( GetWavinfo( name, &info ) ) {
- if( !( sc = ResampleSfx( s, &info ) ) ) {
- Com_DPrintf( "%s resampled to zero length\n", name );
- }
+ if( GetWavinfo() ) {
+#if USE_OPENAL
+ if( s_started == SS_OAL )
+ sc = AL_UploadSfx( s );
+ else
+#endif
+ sc = ResampleSfx( s );
}
FS_FreeFile( data );
diff --git a/source/sys_public.h b/source/sys_public.h
index c4d6a60..976dbc4 100644
--- a/source/sys_public.h
+++ b/source/sys_public.h
@@ -55,8 +55,9 @@ void Sys_Quit( void ) q_noreturn;
void **Sys_ListFiles( const char *path, const char *extension,
int flags, size_t length, int *numFiles );
-qboolean Sys_GetPathInfo( const char *path, file_info_t *info );
-qboolean Sys_GetFileInfo( FILE *fp, file_info_t *info );
+struct file_info_s;
+qboolean Sys_GetPathInfo( const char *path, struct file_info_s *info );
+qboolean Sys_GetFileInfo( FILE *fp, struct file_info_s *info );
char *Sys_GetCurrentDirectory( void );
diff --git a/source/sys_unix.c b/source/sys_unix.c
index 96de99e..0368a77 100644
--- a/source/sys_unix.c
+++ b/source/sys_unix.c
@@ -800,11 +800,15 @@ void *Sys_LoadLibrary( const char *path, const char *sym, void **handle ) {
return NULL;
}
- entry = dlsym( module, sym );
- if( !entry ) {
- Com_DPrintf( "%s failed: %s\n", __func__, dlerror() );
- dlclose( module );
- return NULL;
+ if( sym ) {
+ entry = dlsym( module, sym );
+ if( !entry ) {
+ Com_DPrintf( "%s failed: %s\n", __func__, dlerror() );
+ dlclose( module );
+ return NULL;
+ }
+ } else {
+ entry = NULL;
}
Com_DPrintf( "%s succeeded: %s\n", __func__, path );
diff --git a/source/sys_win.c b/source/sys_win.c
index da53c03..8a36bb5 100644
--- a/source/sys_win.c
+++ b/source/sys_win.c
@@ -767,12 +767,16 @@ void *Sys_LoadLibrary( const char *path, const char *sym, void **handle ) {
return NULL;
}
- entry = GetProcAddress( module, sym );
- if( !entry ) {
- Com_DPrintf( "%s failed: GetProcAddress returned %lu on %s\n",
- __func__, GetLastError(), path );
- FreeLibrary( module );
- return NULL;
+ if( sym ) {
+ entry = GetProcAddress( module, sym );
+ if( !entry ) {
+ Com_DPrintf( "%s failed: GetProcAddress returned %lu on %s\n",
+ __func__, GetLastError(), path );
+ FreeLibrary( module );
+ return NULL;
+ }
+ } else {
+ entry = NULL;
}
*handle = module;