aboutsummaryrefslogtreecommitdiffstats
path: root/code/client/snd_openal.c
diff options
context:
space:
mode:
Diffstat (limited to 'code/client/snd_openal.c')
-rw-r--r--code/client/snd_openal.c220
1 files changed, 174 insertions, 46 deletions
diff --git a/code/client/snd_openal.c b/code/client/snd_openal.c
index 74be8f2..3295e3e 100644
--- a/code/client/snd_openal.c
+++ b/code/client/snd_openal.c
@@ -1253,35 +1253,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 );
}
/*
@@ -1289,12 +1291,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;
}
/*
@@ -1303,20 +1308,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;
@@ -1328,10 +1336,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);
}
/*
@@ -1340,40 +1348,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;
}
}
@@ -1383,14 +1394,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;
+
+ if(streamSourceHandles[stream] == -1)
return;
- streamPlaying = qfalse;
- qalSourceStop(streamSource);
- S_AL_FreeStreamChannel();
+ streamPlaying[stream] = qfalse;
+ qalSourceStop(streamSources[stream]);
+ S_AL_FreeStreamChannel(stream);
}
@@ -1682,6 +1696,11 @@ void S_AL_MusicUpdate( void )
static ALCdevice *alDevice;
static ALCcontext *alContext;
+#if USE_VOIP
+static ALCdevice *alCaptureDevice;
+static cvar_t *s_alCapture;
+#endif
+
#ifdef _WIN32
#define ALDRIVER_DEFAULT "OpenAL32.dll"
#define ALDEVICE_DEFAULT "Generic Software"
@@ -1699,9 +1718,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);
}
/*
@@ -1742,11 +1763,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
@@ -1820,6 +1844,47 @@ void S_AL_SoundList( void )
{
}
+#if 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
@@ -1832,7 +1897,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));
@@ -1849,7 +1915,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( );
@@ -1857,6 +1925,21 @@ void S_AL_Shutdown( void )
qalcDestroyContext(alContext);
qalcCloseDevice(alDevice);
+#if 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();
}
@@ -1872,11 +1955,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 );
@@ -1977,6 +2067,36 @@ qboolean S_AL_Init( soundInterface_t *si )
qalDopplerFactor( s_alDopplerFactor->value );
qalDopplerVelocity( s_alDopplerSpeed->value );
+#if 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 );
+ 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 {
+ 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;
@@ -1998,6 +2118,14 @@ qboolean S_AL_Init( soundInterface_t *si )
si->SoundInfo = S_AL_SoundInfo;
si->SoundList = S_AL_SoundList;
+#if 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;