diff options
author | Andrey Nazarov <skuller@skuller.net> | 2010-05-09 17:06:27 +0000 |
---|---|---|
committer | Andrey Nazarov <skuller@skuller.net> | 2010-05-09 17:06:27 +0000 |
commit | 633c832e43c42bce0a685a93acfc3937c84ed6bb (patch) | |
tree | 93f1da6ad3d2e66ec52a6b7548343dccb67facdf | |
parent | 1f3c71bf0acc8cf7d8893acfdc4ed0e24dde2e0e (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.mk | 4 | ||||
-rwxr-xr-x | configure | 15 | ||||
-rw-r--r-- | source/files.h | 2 | ||||
-rw-r--r-- | source/qal_api.c | 122 | ||||
-rw-r--r-- | source/qal_api.h | 104 | ||||
-rw-r--r-- | source/snd_al.c | 311 | ||||
-rw-r--r-- | source/snd_local.h | 58 | ||||
-rw-r--r-- | source/snd_main.c | 302 | ||||
-rw-r--r-- | source/snd_mem.c | 114 | ||||
-rw-r--r-- | source/sys_public.h | 5 | ||||
-rw-r--r-- | source/sys_unix.c | 14 | ||||
-rw-r--r-- | source/sys_win.c | 16 |
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 \ @@ -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; |