summaryrefslogtreecommitdiff
path: root/src/client/snd_openal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/snd_openal.c')
-rw-r--r--src/client/snd_openal.c262
1 files changed, 203 insertions, 59 deletions
diff --git a/src/client/snd_openal.c b/src/client/snd_openal.c
index fee1d22e..5fad0a45 100644
--- a/src/client/snd_openal.c
+++ b/src/client/snd_openal.c
@@ -499,9 +499,9 @@ typedef struct src_s
} src_t;
#ifdef MACOS_X
- #define MAX_SRC 64
+ #define MAX_SRC 64
#else
- #define MAX_SRC 128
+ #define MAX_SRC 128
#endif
static src_t srcList[MAX_SRC];
static int srcCount = 0;
@@ -896,10 +896,13 @@ S_AL_UpdateEntityPosition
static
void S_AL_UpdateEntityPosition( int entityNum, const vec3_t origin )
{
- S_AL_SanitiseVector( (vec_t *)origin );
+ vec3_t sanOrigin;
+
+ VectorCopy( origin, sanOrigin );
+ S_AL_SanitiseVector( sanOrigin );
if ( entityNum < 0 || entityNum > MAX_GENTITIES )
Com_Error( ERR_DROP, "S_UpdateEntityPosition: bad entitynum %i", entityNum );
- VectorCopy( origin, entityList[entityNum].origin );
+ VectorCopy( sanOrigin, entityList[entityNum].origin );
}
/*
@@ -917,8 +920,8 @@ static qboolean S_AL_CheckInput(int entityNum, sfxHandle_t sfx)
if (sfx < 0 || sfx >= numSfx)
{
Com_Printf(S_COLOR_RED "ERROR: S_AL_CheckInput: handle %i out of range\n", sfx);
- return qtrue;
- }
+ return qtrue;
+ }
return qfalse;
}
@@ -1093,12 +1096,17 @@ S_AL_AddLoopingSound
static
void S_AL_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx )
{
+ vec3_t sanOrigin, sanVelocity;
+
if(S_AL_CheckInput(entityNum, sfx))
return;
- S_AL_SanitiseVector( (vec_t *)origin );
- S_AL_SanitiseVector( (vec_t *)velocity );
- S_AL_SrcLoop(SRCPRI_ENTITY, sfx, origin, velocity, entityNum);
+ VectorCopy( origin, sanOrigin );
+ VectorCopy( velocity, sanVelocity );
+ S_AL_SanitiseVector( sanOrigin );
+ S_AL_SanitiseVector( sanVelocity );
+
+ S_AL_SrcLoop(SRCPRI_ENTITY, sfx, sanOrigin, sanVelocity, entityNum);
}
/*
@@ -1109,20 +1117,24 @@ S_AL_AddRealLoopingSound
static
void S_AL_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx )
{
+ vec3_t sanOrigin, sanVelocity;
+
if(S_AL_CheckInput(entityNum, sfx))
return;
- S_AL_SanitiseVector( (vec_t *)origin );
- S_AL_SanitiseVector( (vec_t *)velocity );
+ VectorCopy( origin, sanOrigin );
+ VectorCopy( velocity, sanVelocity );
+ S_AL_SanitiseVector( sanOrigin );
+ S_AL_SanitiseVector( sanVelocity );
// There are certain maps (*cough* Q3:TA mpterra*) that have large quantities
// of ET_SPEAKERS in the PVS at any given time. OpenAL can't cope with mixing
// large numbers of sounds, so this culls them by distance
- if( DistanceSquared( origin, lastListenerOrigin ) > (s_alMaxDistance->value + s_alGraceDistance->value) *
+ if( DistanceSquared( sanOrigin, lastListenerOrigin ) > (s_alMaxDistance->value + s_alGraceDistance->value) *
(s_alMaxDistance->value + s_alGraceDistance->value) )
return;
- S_AL_SrcLoop(SRCPRI_AMBIENT, sfx, origin, velocity, entityNum);
+ S_AL_SrcLoop(SRCPRI_AMBIENT, sfx, sanOrigin, sanVelocity, entityNum);
}
/*
@@ -1264,35 +1276,37 @@ ALuint S_AL_SrcGet(srcHandle_t src)
//===========================================================================
-
-static srcHandle_t streamSourceHandle = -1;
-static qboolean streamPlaying = qfalse;
-static ALuint streamSource;
+static srcHandle_t streamSourceHandles[MAX_RAW_STREAMS];
+static qboolean streamPlaying[MAX_RAW_STREAMS];
+static ALuint streamSources[MAX_RAW_STREAMS];
/*
=================
S_AL_AllocateStreamChannel
=================
*/
-static void S_AL_AllocateStreamChannel( void )
+static void S_AL_AllocateStreamChannel( int stream )
{
+ if ((stream < 0) || (stream >= MAX_RAW_STREAMS))
+ return;
+
// Allocate a streamSource at high priority
- streamSourceHandle = S_AL_SrcAlloc(SRCPRI_STREAM, -2, 0);
- if(streamSourceHandle == -1)
+ streamSourceHandles[stream] = S_AL_SrcAlloc(SRCPRI_STREAM, -2, 0);
+ if(streamSourceHandles[stream] == -1)
return;
// Lock the streamSource so nobody else can use it, and get the raw streamSource
- S_AL_SrcLock(streamSourceHandle);
- streamSource = S_AL_SrcGet(streamSourceHandle);
+ S_AL_SrcLock(streamSourceHandles[stream]);
+ streamSources[stream] = S_AL_SrcGet(streamSourceHandles[stream]);
// Set some streamSource parameters
- qalSourcei (streamSource, AL_BUFFER, 0 );
- qalSourcei (streamSource, AL_LOOPING, AL_FALSE );
- qalSource3f(streamSource, AL_POSITION, 0.0, 0.0, 0.0);
- qalSource3f(streamSource, AL_VELOCITY, 0.0, 0.0, 0.0);
- qalSource3f(streamSource, AL_DIRECTION, 0.0, 0.0, 0.0);
- qalSourcef (streamSource, AL_ROLLOFF_FACTOR, 0.0 );
- qalSourcei (streamSource, AL_SOURCE_RELATIVE, AL_TRUE );
+ qalSourcei (streamSources[stream], AL_BUFFER, 0 );
+ qalSourcei (streamSources[stream], AL_LOOPING, AL_FALSE );
+ qalSource3f(streamSources[stream], AL_POSITION, 0.0, 0.0, 0.0);
+ qalSource3f(streamSources[stream], AL_VELOCITY, 0.0, 0.0, 0.0);
+ qalSource3f(streamSources[stream], AL_DIRECTION, 0.0, 0.0, 0.0);
+ qalSourcef (streamSources[stream], AL_ROLLOFF_FACTOR, 0.0 );
+ qalSourcei (streamSources[stream], AL_SOURCE_RELATIVE, AL_TRUE );
}
/*
@@ -1300,12 +1314,15 @@ static void S_AL_AllocateStreamChannel( void )
S_AL_FreeStreamChannel
=================
*/
-static void S_AL_FreeStreamChannel( void )
+static void S_AL_FreeStreamChannel( int stream )
{
+ if ((stream < 0) || (stream >= MAX_RAW_STREAMS))
+ return;
+
// Release the output streamSource
- S_AL_SrcUnlock(streamSourceHandle);
- streamSource = 0;
- streamSourceHandle = -1;
+ S_AL_SrcUnlock(streamSourceHandles[stream]);
+ streamSources[stream] = 0;
+ streamSourceHandles[stream] = -1;
}
/*
@@ -1314,20 +1331,23 @@ S_AL_RawSamples
=================
*/
static
-void S_AL_RawSamples(int samples, int rate, int width, int channels, const byte *data, float volume)
+void S_AL_RawSamples(int stream, int samples, int rate, int width, int channels, const byte *data, float volume)
{
ALuint buffer;
ALuint format;
+ if ((stream < 0) || (stream >= MAX_RAW_STREAMS))
+ return;
+
format = S_AL_Format( width, channels );
// Create the streamSource if necessary
- if(streamSourceHandle == -1)
+ if(streamSourceHandles[stream] == -1)
{
- S_AL_AllocateStreamChannel();
+ S_AL_AllocateStreamChannel(stream);
// Failed?
- if(streamSourceHandle == -1)
+ if(streamSourceHandles[stream] == -1)
{
Com_Printf( S_COLOR_RED "ERROR: Can't allocate streaming streamSource\n");
return;
@@ -1339,10 +1359,10 @@ void S_AL_RawSamples(int samples, int rate, int width, int channels, const byte
qalBufferData(buffer, format, (ALvoid *)data, (samples * width * channels), rate);
// Shove the data onto the streamSource
- qalSourceQueueBuffers(streamSource, 1, &buffer);
+ qalSourceQueueBuffers(streamSources[stream], 1, &buffer);
// Volume
- qalSourcef (streamSource, AL_GAIN, volume * s_volume->value * s_alGain->value);
+ qalSourcef (streamSources[stream], AL_GAIN, volume * s_volume->value * s_alGain->value);
}
/*
@@ -1351,40 +1371,43 @@ S_AL_StreamUpdate
=================
*/
static
-void S_AL_StreamUpdate( void )
+void S_AL_StreamUpdate( int stream )
{
int numBuffers;
ALint state;
- if(streamSourceHandle == -1)
+ if ((stream < 0) || (stream >= MAX_RAW_STREAMS))
+ return;
+
+ if(streamSourceHandles[stream] == -1)
return;
// Un-queue any buffers, and delete them
- qalGetSourcei( streamSource, AL_BUFFERS_PROCESSED, &numBuffers );
+ qalGetSourcei( streamSources[stream], AL_BUFFERS_PROCESSED, &numBuffers );
while( numBuffers-- )
{
ALuint buffer;
- qalSourceUnqueueBuffers(streamSource, 1, &buffer);
+ qalSourceUnqueueBuffers(streamSources[stream], 1, &buffer);
qalDeleteBuffers(1, &buffer);
}
// Start the streamSource playing if necessary
- qalGetSourcei( streamSource, AL_BUFFERS_QUEUED, &numBuffers );
+ qalGetSourcei( streamSources[stream], AL_BUFFERS_QUEUED, &numBuffers );
- qalGetSourcei(streamSource, AL_SOURCE_STATE, &state);
+ qalGetSourcei(streamSources[stream], AL_SOURCE_STATE, &state);
if(state == AL_STOPPED)
{
- streamPlaying = qfalse;
+ streamPlaying[stream] = qfalse;
// If there are no buffers queued up, release the streamSource
if( !numBuffers )
- S_AL_FreeStreamChannel( );
+ S_AL_FreeStreamChannel( stream );
}
- if( !streamPlaying && numBuffers )
+ if( !streamPlaying[stream] && numBuffers )
{
- qalSourcePlay( streamSource );
- streamPlaying = qtrue;
+ qalSourcePlay( streamSources[stream] );
+ streamPlaying[stream] = qtrue;
}
}
@@ -1394,14 +1417,17 @@ S_AL_StreamDie
=================
*/
static
-void S_AL_StreamDie( void )
+void S_AL_StreamDie( int stream )
{
- if(streamSourceHandle == -1)
+ if ((stream < 0) || (stream >= MAX_RAW_STREAMS))
return;
- streamPlaying = qfalse;
- qalSourceStop(streamSource);
- S_AL_FreeStreamChannel();
+ if(streamSourceHandles[stream] == -1)
+ return;
+
+ streamPlaying[stream] = qfalse;
+ qalSourceStop(streamSources[stream]);
+ S_AL_FreeStreamChannel(stream);
}
@@ -1693,6 +1719,11 @@ void S_AL_MusicUpdate( void )
static ALCdevice *alDevice;
static ALCcontext *alContext;
+#ifdef USE_VOIP
+static ALCdevice *alCaptureDevice;
+static cvar_t *s_alCapture;
+#endif
+
#ifdef _WIN32
#define ALDRIVER_DEFAULT "OpenAL32.dll"
#define ALDEVICE_DEFAULT "Generic Software"
@@ -1710,9 +1741,11 @@ S_AL_StopAllSounds
static
void S_AL_StopAllSounds( void )
{
+ int i;
S_AL_SrcShutup();
S_AL_StopBackgroundTrack();
- S_AL_StreamDie();
+ for (i = 0; i < MAX_RAW_STREAMS; i++)
+ S_AL_StreamDie(i);
}
/*
@@ -1753,11 +1786,14 @@ S_AL_Update
static
void S_AL_Update( void )
{
+ int i;
+
// Update SFX channels
S_AL_SrcUpdate();
// Update streams
- S_AL_StreamUpdate();
+ for (i = 0; i < MAX_RAW_STREAMS; i++)
+ S_AL_StreamUpdate(i);
S_AL_MusicUpdate();
// Doppler
@@ -1831,6 +1867,47 @@ void S_AL_SoundList( void )
{
}
+#ifdef USE_VOIP
+static
+void S_AL_StartCapture( void )
+{
+ if (alCaptureDevice != NULL)
+ qalcCaptureStart(alCaptureDevice);
+}
+
+static
+int S_AL_AvailableCaptureSamples( void )
+{
+ int retval = 0;
+ if (alCaptureDevice != NULL)
+ {
+ ALint samples = 0;
+ qalcGetIntegerv(alCaptureDevice, ALC_CAPTURE_SAMPLES, sizeof (samples), &samples);
+ retval = (int) samples;
+ }
+ return retval;
+}
+
+static
+void S_AL_Capture( int samples, byte *data )
+{
+ if (alCaptureDevice != NULL)
+ qalcCaptureSamples(alCaptureDevice, data, samples);
+}
+
+void S_AL_StopCapture( void )
+{
+ if (alCaptureDevice != NULL)
+ qalcCaptureStop(alCaptureDevice);
+}
+
+void S_AL_MasterGain( float gain )
+{
+ qalListenerf(AL_GAIN, gain);
+}
+#endif
+
+
/*
=================
S_AL_SoundInfo
@@ -1843,7 +1920,8 @@ void S_AL_SoundInfo( void )
Com_Printf( " Vendor: %s\n", qalGetString( AL_VENDOR ) );
Com_Printf( " Version: %s\n", qalGetString( AL_VERSION ) );
Com_Printf( " Renderer: %s\n", qalGetString( AL_RENDERER ) );
- Com_Printf( " Extensions: %s\n", qalGetString( AL_EXTENSIONS ) );
+ Com_Printf( " AL Extensions: %s\n", qalGetString( AL_EXTENSIONS ) );
+ Com_Printf( " ALC Extensions: %s\n", qalcGetString( NULL, ALC_EXTENSIONS ) );
if(qalcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
{
Com_Printf(" Device: %s\n", qalcGetString(alDevice, ALC_DEVICE_SPECIFIER));
@@ -1860,7 +1938,9 @@ static
void S_AL_Shutdown( void )
{
// Shut down everything
- S_AL_StreamDie( );
+ int i;
+ for (i = 0; i < MAX_RAW_STREAMS; i++)
+ S_AL_StreamDie(i);
S_AL_StopBackgroundTrack( );
S_AL_SrcShutdown( );
S_AL_BufferShutdown( );
@@ -1868,6 +1948,21 @@ void S_AL_Shutdown( void )
qalcDestroyContext(alContext);
qalcCloseDevice(alDevice);
+#ifdef USE_VOIP
+ if (alCaptureDevice != NULL) {
+ qalcCaptureStop(alCaptureDevice);
+ qalcCaptureCloseDevice(alCaptureDevice);
+ alCaptureDevice = NULL;
+ Com_Printf( "OpenAL capture device closed.\n" );
+ }
+#endif
+
+ for (i = 0; i < MAX_RAW_STREAMS; i++) {
+ streamSourceHandles[i] = -1;
+ streamPlaying[i] = qfalse;
+ streamSources[i] = 0;
+ }
+
QAL_Shutdown();
}
@@ -1883,11 +1978,18 @@ qboolean S_AL_Init( soundInterface_t *si )
#ifdef USE_OPENAL
qboolean enumsupport, founddev = qfalse;
+ int i;
if( !si ) {
return qfalse;
}
+ for (i = 0; i < MAX_RAW_STREAMS; i++) {
+ streamSourceHandles[i] = -1;
+ streamPlaying[i] = qfalse;
+ streamSources[i] = 0;
+ }
+
// New console variables
s_alPrecache = Cvar_Get( "s_alPrecache", "1", CVAR_ARCHIVE );
s_alGain = Cvar_Get( "s_alGain", "0.4", CVAR_ARCHIVE );
@@ -1988,6 +2090,40 @@ qboolean S_AL_Init( soundInterface_t *si )
qalDopplerFactor( s_alDopplerFactor->value );
qalDopplerVelocity( s_alDopplerSpeed->value );
+#ifdef USE_VOIP
+ // !!! FIXME: some of these alcCaptureOpenDevice() values should be cvars.
+ // !!! FIXME: add support for capture device enumeration.
+ // !!! FIXME: add some better error reporting.
+ s_alCapture = Cvar_Get( "s_alCapture", "1", CVAR_ARCHIVE | CVAR_LATCH );
+ if (!s_alCapture->integer) {
+ Com_Printf("OpenAL capture support disabled by user ('+set s_alCapture 1' to enable)\n");
+#if USE_MUMBLE
+ } else if (cl_useMumble->integer) {
+ Com_Printf("OpenAL capture support disabled for Mumble support\n");
+#endif
+ } else {
+ // !!! FIXME: Apple has a 1.1-compliant OpenAL, which includes
+ // !!! FIXME: capture support, but they don't list it in the
+ // !!! FIXME: extension string. We need to check the version string,
+ // !!! FIXME: then the extension string, but that's too much trouble,
+ // !!! FIXME: so we'll just check the function pointer for now.
+ //if (qalcIsExtensionPresent(NULL, "ALC_EXT_capture")) {
+ if (qalcCaptureOpenDevice == NULL) {
+ Com_Printf("No ALC_EXT_capture support, can't record audio.\n");
+ } else {
+ // !!! FIXME: 8000Hz is what Speex narrowband mode needs, but we
+ // !!! FIXME: should probably open the capture device after
+ // !!! FIXME: initializing Speex so we can change to wideband
+ // !!! FIXME: if we like.
+ Com_Printf("OpenAL default capture device is '%s'\n",
+ qalcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
+ alCaptureDevice = qalcCaptureOpenDevice(NULL, 8000, AL_FORMAT_MONO16, 4096);
+ Com_Printf( "OpenAL capture device %s.\n",
+ (alCaptureDevice == NULL) ? "failed to open" : "opened");
+ }
+ }
+#endif
+
si->Shutdown = S_AL_Shutdown;
si->StartSound = S_AL_StartSound;
si->StartLocalSound = S_AL_StartLocalSound;
@@ -2010,6 +2146,14 @@ qboolean S_AL_Init( soundInterface_t *si )
si->SoundInfo = S_AL_SoundInfo;
si->SoundList = S_AL_SoundList;
+#ifdef USE_VOIP
+ si->StartCapture = S_AL_StartCapture;
+ si->AvailableCaptureSamples = S_AL_AvailableCaptureSamples;
+ si->Capture = S_AL_Capture;
+ si->StopCapture = S_AL_StopCapture;
+ si->MasterGain = S_AL_MasterGain;
+#endif
+
return qtrue;
#else
return qfalse;