mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-10 07:12:07 +00:00
Merge OpenAL branch
This commit is contained in:
commit
53d54b1f23
13 changed files with 1566 additions and 134 deletions
11
Makefile
11
Makefile
|
@ -30,6 +30,10 @@ WITH_CDA=yes
|
|||
# dependencies to libogg, libvorbis and libvorbisfile.
|
||||
WITH_OGG=yes
|
||||
|
||||
# Enables the optional OpenAL sound systems. Adds
|
||||
# a dependencx to libopenal
|
||||
WITH_OPENAL=yes
|
||||
|
||||
# Enables retexturing support. Adds a dependency to
|
||||
# libjpeg
|
||||
WITH_RETEXTURING=yes
|
||||
|
@ -182,6 +186,11 @@ release/quake2 : CFLAGS += -DOGG
|
|||
release/quake2 : LDFLAGS += -lvorbis -lvorbisfile -logg
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_OPENAL),yes)
|
||||
release/quake2 : CFLAGS += -DUSE_OPENAL -DDEFAULT_OPENAL_DRIVER='"libopenal.so.1"'
|
||||
release/quake2 : LDFLAGS += -lopenal
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_ZIP),yes)
|
||||
release/quake2 : CFLAGS += -DZIP
|
||||
release/quake2 : LDFLAGS += -lz
|
||||
|
@ -325,6 +334,7 @@ CLIENT_OBJS_ := \
|
|||
src/client/menu/menu.o \
|
||||
src/client/menu/qmenu.o \
|
||||
src/client/menu/videomenu.o \
|
||||
src/client/sound/snd_al.o \
|
||||
src/client/sound/snd_dma.o \
|
||||
src/client/sound/snd_mem.o \
|
||||
src/client/sound/snd_mix.o \
|
||||
|
@ -371,6 +381,7 @@ CLIENT_OBJS_ := \
|
|||
src/unix/hunk.o \
|
||||
src/unix/main.o \
|
||||
src/unix/network.o \
|
||||
src/unix/qal.o \
|
||||
src/unix/signalhandler.o \
|
||||
src/unix/system.o \
|
||||
src/unix/vid.o
|
||||
|
|
56
README
56
README
|
@ -38,10 +38,11 @@ Content of this file:
|
|||
2.4 Console variables
|
||||
|
||||
3. Configuration
|
||||
3.1 Widescreen setup
|
||||
3.2 Video
|
||||
3.3 Input
|
||||
3.4 Sound
|
||||
3.1 Video
|
||||
3.2 Input
|
||||
3.3 Sound
|
||||
3.3.1 The classic sound system
|
||||
3.3.2 The OpenAL sound system
|
||||
|
||||
4. Bugreports
|
||||
|
||||
|
@ -338,14 +339,23 @@ There are some cvar to adjust:
|
|||
|
||||
3.3 Sound
|
||||
---------
|
||||
Quake II featured one of the best sound systems of it's time but sadly it was
|
||||
totaly broken. Therefore id Software rewrote it once, later it was rewritten
|
||||
again for the linux port. That fixed the most visible problems, but the code was
|
||||
just crap and broke again as time passed and sound on PCs evolved.
|
||||
For Yamagi Quake II 3.0 the sound system was overhauled, featuring a complete
|
||||
code audit of the upper layers with many bugfixes and memory leak plugs.
|
||||
The backend was rewritten from scratch. This should solve most if not all
|
||||
problems.
|
||||
Quake II featured one of the best sound systems of it's time (for example it had
|
||||
support for realtime calculated stereo effects) but sadly it was totaly broken.
|
||||
Therefore id Software rewrote it once, later it was rewritten again for the
|
||||
linux port. That fixed the most visible problems, but the code was just crap and
|
||||
broke again as time passed and sound on PCs evolved. For Yamagi Quake II 3.0 the
|
||||
sound system was overhauled, featuring a complete code audit of the upper layers
|
||||
with many bugfixes and memory leak plugs. The backend was rewritten from
|
||||
scratch. This should solve most if not all problems. Yamagi Quake II 4.20
|
||||
featured an optional OpenAL sound system, enabling better stereo calculations
|
||||
and even surround support.
|
||||
|
||||
3.3.1 The classic sound system
|
||||
------------------------------
|
||||
This is the original sound implementation, as used in the first release of Quake
|
||||
II in 1997. It featured stereo calculations for most samples. It's disabled by
|
||||
default and can be reenables by setting "s_openal" to "0", followed by
|
||||
"snd_restart. Common problems are:
|
||||
|
||||
- The earthquake sound sample is distorted
|
||||
This is not a fault of the sound code but of the sound sample itself.
|
||||
|
@ -370,6 +380,28 @@ problems.
|
|||
card 0
|
||||
}
|
||||
|
||||
3.3.2 The OpenAL sound system
|
||||
-----------------------------
|
||||
This is a sound system based upon the popular OpenAL audio library. It features
|
||||
surround playback which gives a huge improvement in sound quality and gameplay
|
||||
experience. It's enables by default, but can be disabled by setting "s_openal"
|
||||
to "0", followed by a "snd_restart". To work correctly it's in the need of a
|
||||
correctly configured OpenAL! OpenAL is configured in the file ~/.alsoftrc (for
|
||||
the openal-soft implementation, other implementations may vary). The most
|
||||
important options (tested with OpenAL Soft 1.14) are:
|
||||
|
||||
- channels = surround51 -> Enable 5.1 surround support. Other values are "mono",
|
||||
"stereo", "quad", "surround61" and "surround71".
|
||||
|
||||
- stereodup = true -> If set to "true" all raw stereo samples (in Quake II the
|
||||
background music and video sounds) are duplicated behind the listener.
|
||||
Otherwise they're played only through the front speakers.
|
||||
|
||||
- resampler = cubic -> Use cubic resampling. While this requires more cpu power
|
||||
than the default linear resamling it's highly recommended since Quake II has
|
||||
several hard to resamples sound effects. Especially the earthquake sound can
|
||||
distort if a low quality resampler is employed!
|
||||
|
||||
===============================================================================
|
||||
|
||||
4. Bugreports
|
||||
|
|
|
@ -37,6 +37,10 @@ typedef struct {
|
|||
int loopstart;
|
||||
int speed; /* not needed, because converted on load? */
|
||||
int width;
|
||||
#if USE_OPENAL
|
||||
int size;
|
||||
int bufnum;
|
||||
#endif
|
||||
int stereo;
|
||||
byte data[1]; /* variable sized */
|
||||
} sfxcache_t;
|
||||
|
@ -87,6 +91,10 @@ typedef struct {
|
|||
int master_vol; /* 0-255 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 {
|
||||
|
@ -98,6 +106,13 @@ typedef struct {
|
|||
int dataofs; /* chunk starts this many bytes from file start */
|
||||
} wavinfo_t;
|
||||
|
||||
typedef enum {
|
||||
SS_NOT = 0, // soundsystem not started
|
||||
SS_DMA, // soundsystem started, using DMA/SDL
|
||||
SS_OAL // soundsystem started, using OpenAL
|
||||
} sndstarted_t;
|
||||
|
||||
extern sndstarted_t sound_started;
|
||||
|
||||
/* initializes cycling through a DMA
|
||||
buffer and returns information on it */
|
||||
|
@ -113,6 +128,7 @@ void SNDDMA_Submit(void);
|
|||
|
||||
#define MAX_CHANNELS 32
|
||||
extern channel_t channels[MAX_CHANNELS];
|
||||
extern int s_numchannels;
|
||||
|
||||
extern int paintedtime;
|
||||
extern int s_rawend;
|
||||
|
@ -133,6 +149,7 @@ extern cvar_t *s_khz;
|
|||
extern cvar_t *s_show;
|
||||
extern cvar_t *s_mixahead;
|
||||
extern cvar_t *s_testsound;
|
||||
extern cvar_t *s_ambient;
|
||||
|
||||
wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength);
|
||||
void S_InitScaletable (void);
|
||||
|
@ -146,5 +163,29 @@ channel_t *S_PickChannel(int entnum, int entchannel);
|
|||
/* spatializes a channel */
|
||||
void S_Spatialize(channel_t *ch);
|
||||
|
||||
void S_BuildSoundList( int *sounds );
|
||||
|
||||
#if USE_OPENAL
|
||||
// this stuff was taken from Q2Pro
|
||||
// only begin attenuating sound volumes when outside the FULLVOLUME range
|
||||
#define SOUND_FULLVOLUME 80
|
||||
#define SOUND_LOOPATTENUATE 0.003
|
||||
|
||||
// number of buffers in flight (needed for ogg)
|
||||
extern int active_buffers;
|
||||
|
||||
// for snd_al.c - copied from Q2Pro and adapted
|
||||
void AL_SoundInfo( void );
|
||||
qboolean AL_Init( void );
|
||||
void AL_Shutdown( void );
|
||||
sfxcache_t *AL_UploadSfx( sfx_t *s, wavinfo_t *s_info, byte *data );
|
||||
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 );
|
||||
void AL_RawSamples( int samples, int rate, int width, int channels, byte *data, float volume );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
534
src/client/sound/snd_al.c
Normal file
534
src/client/sound/snd_al.c
Normal file
|
@ -0,0 +1,534 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2005 Id Software, Inc.
|
||||
* (C) 2010 skuller.net
|
||||
* (C) 2005 Stuart Dalton (badcdev@gmail.com)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* =======================================================================
|
||||
*
|
||||
* Most of these functions are from the Q2Pro project, and some are from
|
||||
* zeq2. We adapted them to work with Yamagi Quake II
|
||||
*
|
||||
* This is an OpenAL backend for the Quake II Soundsystem.
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#ifdef USE_OPENAL
|
||||
|
||||
#include "../header/client.h"
|
||||
#include "../../unix/header/qal.h"
|
||||
#include "header/local.h"
|
||||
#include "header/vorbis.h"
|
||||
|
||||
// translates from AL coordinate system to quake
|
||||
#define AL_UnpackVector(v) -v[1],v[2],-v[0]
|
||||
#define AL_CopyVector(a,b) ((b)[0]=-(a)[1],(b)[1]=(a)[2],(b)[2]=-(a)[0])
|
||||
|
||||
// OpenAL implementation should support at least this number of sources
|
||||
#define MIN_CHANNELS 16
|
||||
|
||||
qboolean streamPlaying;
|
||||
int active_buffers;
|
||||
|
||||
static ALuint streamSource;
|
||||
static ALuint underwaterFilter;
|
||||
|
||||
static ALuint s_srcnums[MAX_CHANNELS-1];
|
||||
static int s_framecount;
|
||||
|
||||
// Forward Declarations
|
||||
static void S_AL_StreamUpdate( void );
|
||||
static void S_AL_StreamDie( void );
|
||||
// /Forward Declarations
|
||||
|
||||
static void AL_InitStreamSource() {
|
||||
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 );
|
||||
}
|
||||
|
||||
static void AL_InitUnderwaterFilter()
|
||||
{
|
||||
// Generate a filter
|
||||
qalGenFilters(1, &underwaterFilter);
|
||||
|
||||
if (qalGetError() != AL_NO_ERROR)
|
||||
{
|
||||
Com_Printf("Couldn't generate an OpenAL filter!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Low pass filter for underwater effect
|
||||
qalFilteri(underwaterFilter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
|
||||
|
||||
if (qalGetError() != AL_NO_ERROR)
|
||||
{
|
||||
Com_Printf("Low pass filter is not supported!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// The effect
|
||||
qalFilterf(underwaterFilter, AL_LOWPASS_GAIN, 1.5);
|
||||
qalFilterf(underwaterFilter, AL_LOWPASS_GAINHF, 0.25);
|
||||
}
|
||||
|
||||
qboolean AL_Init( void ) {
|
||||
int i;
|
||||
|
||||
if( !QAL_Init() ) {
|
||||
Com_Printf( "ERROR: OpenAL failed to initialize.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for linear distance extension
|
||||
if( !qalIsExtensionPresent( "AL_EXT_LINEAR_DISTANCE" ) ) {
|
||||
Com_Printf( "ERROR: Required AL_EXT_LINEAR_DISTANCE extension is missing.\n" );
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// generate source names
|
||||
qalGetError();
|
||||
qalGenSources( 1, &streamSource );
|
||||
if( qalGetError() != AL_NO_ERROR )
|
||||
{
|
||||
Com_Printf( "ERROR: Couldn't get a single Source.\n" );
|
||||
goto fail;
|
||||
|
||||
} else {
|
||||
// -1 because we already got one channel for streaming
|
||||
for( i = 0; i < MAX_CHANNELS - 1; i++ ) {
|
||||
qalGenSources( 1, &s_srcnums[i] );
|
||||
if( qalGetError() != AL_NO_ERROR ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( i < MIN_CHANNELS - 1 ) {
|
||||
Com_Printf( "ERROR: Required at least %d sources, but got %d.\n", MIN_CHANNELS, i+1 );
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
s_numchannels = i;
|
||||
AL_InitStreamSource();
|
||||
AL_InitUnderwaterFilter();
|
||||
|
||||
Com_Printf("Number of OpenAL sources: %d\n\n", s_numchannels);
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
QAL_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
void AL_Shutdown( void ) {
|
||||
Com_Printf( "Shutting down OpenAL.\n" );
|
||||
|
||||
qalDeleteSources(1, &streamSource);
|
||||
qalDeleteFilters(1, &underwaterFilter);
|
||||
|
||||
if( s_numchannels ) {
|
||||
// delete source names
|
||||
qalDeleteSources( s_numchannels, s_srcnums );
|
||||
memset( s_srcnums, 0, sizeof( s_srcnums ) );
|
||||
s_numchannels = 0;
|
||||
}
|
||||
S_AL_StreamDie();
|
||||
QAL_Shutdown();
|
||||
}
|
||||
|
||||
sfxcache_t *AL_UploadSfx( sfx_t *s, wavinfo_t *s_info, byte *data ) {
|
||||
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;
|
||||
|
||||
if( !size ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qalGetError();
|
||||
qalGenBuffers( 1, &name );
|
||||
qalBufferData( name, format, data, size, s_info->rate );
|
||||
active_buffers++;
|
||||
if( qalGetError() != AL_NO_ERROR ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// allocate placeholder sfxcache
|
||||
sc = s->cache = Z_TagMalloc(sizeof(*sc), 0);
|
||||
sc->length = s_info->samples * 1000 / s_info->rate; // in msec
|
||||
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 );
|
||||
active_buffers--;
|
||||
}
|
||||
|
||||
void AL_StopChannel( channel_t *ch ) {
|
||||
|
||||
if (s_show->value > 1)
|
||||
Com_Printf("%s: %s\n", __func__, ch->sfx->name );
|
||||
|
||||
// stop it
|
||||
qalSourceStop( ch->srcnum );
|
||||
qalSourcei( ch->srcnum, AL_BUFFER, AL_NONE );
|
||||
memset (ch, 0, sizeof(*ch));
|
||||
}
|
||||
|
||||
static void AL_Spatialize( channel_t *ch ) {
|
||||
vec3_t origin;
|
||||
|
||||
// anything coming from the view entity will always be full volume
|
||||
// no attenuation = no spatialization
|
||||
if( ch->entnum == -1 || ch->entnum == cl.playernum + 1 || !ch->dist_mult ) {
|
||||
VectorCopy( listener_origin, origin );
|
||||
} else if( ch->fixed_origin ) {
|
||||
VectorCopy( ch->origin, origin );
|
||||
} else {
|
||||
CL_GetEntitySoundOrigin( ch->entnum, origin );
|
||||
}
|
||||
|
||||
qalSource3f( ch->srcnum, AL_POSITION, AL_UnpackVector( origin ) );
|
||||
}
|
||||
|
||||
void AL_PlayChannel( channel_t *ch ) {
|
||||
sfxcache_t *sc = ch->sfx->cache;
|
||||
|
||||
if (s_show->value > 1)
|
||||
Com_Printf("%s: %s\n", __func__, ch->sfx->name );
|
||||
|
||||
ch->srcnum = s_srcnums[ch - channels];
|
||||
qalGetError();
|
||||
qalSourcei( ch->srcnum, AL_BUFFER, sc->bufnum );
|
||||
qalSourcei( ch->srcnum, AL_LOOPING, ch->autosound ? AL_TRUE : AL_FALSE );
|
||||
qalSourcef( ch->srcnum, AL_GAIN, ch->master_vol );
|
||||
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 );
|
||||
if( qalGetError() != AL_NO_ERROR ) {
|
||||
AL_StopChannel( ch );
|
||||
}
|
||||
}
|
||||
|
||||
void AL_StopAllChannels( void ) {
|
||||
int i;
|
||||
channel_t *ch;
|
||||
|
||||
ch = channels;
|
||||
for( i = 0; i < s_numchannels; i++, ch++ ) {
|
||||
if (!ch->sfx)
|
||||
continue;
|
||||
AL_StopChannel( ch );
|
||||
}
|
||||
s_rawend = 0;
|
||||
S_AL_StreamDie();
|
||||
}
|
||||
|
||||
static channel_t *AL_FindLoopingSound( int entnum, sfx_t *sfx ) {
|
||||
int i;
|
||||
channel_t *ch;
|
||||
|
||||
ch = channels;
|
||||
for( i = 0; i < s_numchannels; 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[64]; // 64 is MAX_PACKET_ENTITIES in YQ2 (there's no define for it, though :/)
|
||||
channel_t *ch;
|
||||
sfx_t *sfx;
|
||||
sfxcache_t *sc;
|
||||
int num;
|
||||
entity_state_t *ent;
|
||||
|
||||
if( cls.state != ca_active || cl_paused->value || !s_ambient->value ) {
|
||||
return;
|
||||
}
|
||||
|
||||
S_BuildSoundList( sounds );
|
||||
|
||||
for( i = 0; i < cl.frame.num_entities; i++ ) {
|
||||
if (!sounds[i])
|
||||
continue;
|
||||
|
||||
sfx = cl.sound_precache[sounds[i]];
|
||||
if (!sfx)
|
||||
continue; // bad sound effect
|
||||
sc = sfx->cache;
|
||||
if (!sc)
|
||||
continue;
|
||||
|
||||
num = ( cl.frame.parse_entities + i ) & ( MAX_PARSE_ENTITIES - 1 );
|
||||
ent = &cl_parse_entities [ num ];
|
||||
|
||||
ch = AL_FindLoopingSound( ent->number, sfx );
|
||||
if( ch ) {
|
||||
ch->autoframe = s_framecount;
|
||||
ch->end = paintedtime + sc->length;
|
||||
continue;
|
||||
}
|
||||
|
||||
// allocate a channel
|
||||
ch = S_PickChannel(0, 0);
|
||||
if (!ch)
|
||||
continue;
|
||||
|
||||
ch->autosound = true; // 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 );
|
||||
}
|
||||
}
|
||||
|
||||
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_Update( void ) {
|
||||
int i;
|
||||
channel_t *ch;
|
||||
vec_t orientation[6];
|
||||
|
||||
paintedtime = cl.time;
|
||||
|
||||
// set listener parameters
|
||||
qalListener3f( AL_POSITION, AL_UnpackVector( listener_origin ) );
|
||||
AL_CopyVector( listener_forward, orientation );
|
||||
AL_CopyVector( listener_up, orientation + 3 );
|
||||
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 < s_numchannels; 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;
|
||||
|
||||
qalGetError();
|
||||
qalGetSourcei( ch->srcnum, AL_SOURCE_STATE, &state );
|
||||
if( qalGetError() != AL_NO_ERROR || state == AL_STOPPED ) {
|
||||
AL_StopChannel( ch );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_show->value) {
|
||||
Com_Printf ("%.1f %s\n", ch->master_vol, ch->sfx->name);
|
||||
}
|
||||
|
||||
AL_Spatialize(ch); // respatialize channel
|
||||
}
|
||||
|
||||
s_framecount++;
|
||||
|
||||
// add loopsounds
|
||||
AL_AddLoopSounds ();
|
||||
|
||||
// add music
|
||||
OGG_Stream();
|
||||
S_AL_StreamUpdate();
|
||||
|
||||
AL_IssuePlaysounds();
|
||||
}
|
||||
|
||||
void AL_Underwater()
|
||||
{
|
||||
int i;
|
||||
|
||||
// Apply to all sources
|
||||
for (i = 0; i < s_numchannels; i++)
|
||||
{
|
||||
qalSourcei(s_srcnums[i], AL_DIRECT_FILTER, underwaterFilter);
|
||||
}
|
||||
}
|
||||
|
||||
void AL_Overwater()
|
||||
{
|
||||
int i;
|
||||
|
||||
// Apply to all sources
|
||||
for (i = 0; i < s_numchannels; i++)
|
||||
{
|
||||
qalSourcei(s_srcnums[i], AL_DIRECT_FILTER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void S_AL_StreamDie( void )
|
||||
{
|
||||
int numBuffers;
|
||||
|
||||
streamPlaying = false;
|
||||
qalSourceStop(streamSource);
|
||||
|
||||
// Un-queue any buffers, and delete them
|
||||
qalGetSourcei( streamSource, AL_BUFFERS_PROCESSED, &numBuffers );
|
||||
while( numBuffers-- )
|
||||
{
|
||||
ALuint buffer;
|
||||
qalSourceUnqueueBuffers(streamSource, 1, &buffer);
|
||||
qalDeleteBuffers(1, &buffer);
|
||||
active_buffers--;
|
||||
}
|
||||
}
|
||||
|
||||
static void S_AL_StreamUpdate( void )
|
||||
{
|
||||
int numBuffers;
|
||||
ALint state;
|
||||
|
||||
// Un-queue any buffers, and delete them
|
||||
qalGetSourcei( streamSource, AL_BUFFERS_PROCESSED, &numBuffers );
|
||||
while( numBuffers-- )
|
||||
{
|
||||
ALuint buffer;
|
||||
qalSourceUnqueueBuffers(streamSource, 1, &buffer);
|
||||
qalDeleteBuffers(1, &buffer);
|
||||
active_buffers--;
|
||||
}
|
||||
|
||||
// Start the streamSource playing if necessary
|
||||
qalGetSourcei( streamSource, AL_BUFFERS_QUEUED, &numBuffers );
|
||||
|
||||
qalGetSourcei(streamSource, AL_SOURCE_STATE, &state);
|
||||
if(state == AL_STOPPED)
|
||||
{
|
||||
streamPlaying = false;
|
||||
}
|
||||
|
||||
if( !streamPlaying && numBuffers )
|
||||
{
|
||||
qalSourcePlay( streamSource );
|
||||
streamPlaying = true;
|
||||
}
|
||||
}
|
||||
|
||||
static ALuint S_AL_Format(int width, int channels)
|
||||
{
|
||||
ALuint format = AL_FORMAT_MONO16;
|
||||
|
||||
// Work out format
|
||||
if(width == 1)
|
||||
{
|
||||
if(channels == 1)
|
||||
format = AL_FORMAT_MONO8;
|
||||
else if(channels == 2)
|
||||
format = AL_FORMAT_STEREO8;
|
||||
}
|
||||
else if(width == 2)
|
||||
{
|
||||
if(channels == 1)
|
||||
format = AL_FORMAT_MONO16;
|
||||
else if(channels == 2)
|
||||
format = AL_FORMAT_STEREO16;
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
void AL_RawSamples( int samples, int rate, int width, int channels, byte *data, float volume )
|
||||
{
|
||||
ALuint buffer;
|
||||
ALuint format;
|
||||
|
||||
format = S_AL_Format( width, channels );
|
||||
|
||||
// Create a buffer, and stuff the data into it
|
||||
qalGenBuffers(1, &buffer);
|
||||
qalBufferData(buffer, format, (ALvoid *)data, (samples * width * channels), rate);
|
||||
active_buffers++;
|
||||
|
||||
// set volume
|
||||
qalSourcef( streamSource, AL_GAIN, volume );
|
||||
|
||||
// Shove the data onto the streamSource
|
||||
qalSourceQueueBuffers(streamSource, 1, &buffer);
|
||||
|
||||
// emulate behavior of S_RawSamples for s_rawend
|
||||
s_rawend += samples;
|
||||
}
|
||||
|
||||
void AL_UnqueueRawSamples()
|
||||
{
|
||||
S_AL_StreamDie();
|
||||
}
|
||||
|
||||
#endif // USE_OPENAL
|
|
@ -27,12 +27,12 @@
|
|||
*/
|
||||
|
||||
#include "../header/client.h"
|
||||
#include "../../unix/header/qal.h"
|
||||
#include "header/local.h"
|
||||
#include "header/vorbis.h"
|
||||
|
||||
void S_Play ( void );
|
||||
void S_SoundList ( void );
|
||||
void S_Update_ ();
|
||||
void S_StopAllSounds ( void );
|
||||
|
||||
/* only begin attenuating sound volumes when outside the FULLVOLUME range */
|
||||
|
@ -42,9 +42,10 @@ void S_StopAllSounds ( void );
|
|||
int s_registration_sequence;
|
||||
|
||||
channel_t channels [ MAX_CHANNELS ];
|
||||
int s_numchannels;
|
||||
|
||||
qboolean snd_initialized = false;
|
||||
int sound_started = 0;
|
||||
sndstarted_t sound_started = SS_NOT;
|
||||
|
||||
dma_t dma;
|
||||
|
||||
|
@ -79,6 +80,7 @@ cvar_t *s_loadas8bit;
|
|||
cvar_t *s_khz;
|
||||
cvar_t *s_mixahead;
|
||||
cvar_t *s_show;
|
||||
cvar_t *s_ambient;
|
||||
|
||||
int s_rawend;
|
||||
portable_samplepair_t s_rawsamples [ MAX_RAW_SAMPLES ];
|
||||
|
@ -86,15 +88,8 @@ portable_samplepair_t s_rawsamples [ MAX_RAW_SAMPLES ];
|
|||
/*
|
||||
* User-setable variables
|
||||
*/
|
||||
void
|
||||
S_SoundInfo_f ( void )
|
||||
{
|
||||
if ( !sound_started )
|
||||
{
|
||||
Com_Printf( "sound system not started\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
static void DMA_SoundInfo (void) {
|
||||
Com_Printf( "%5d stereo\n", dma.channels - 1 );
|
||||
Com_Printf( "%5d samples\n", dma.samples );
|
||||
Com_Printf( "%5d samplepos\n", dma.samplepos );
|
||||
|
@ -104,6 +99,26 @@ S_SoundInfo_f ( void )
|
|||
Com_Printf( "%p dma buffer\n", dma.buffer );
|
||||
}
|
||||
|
||||
void
|
||||
S_SoundInfo_f ( void )
|
||||
{
|
||||
if ( !sound_started )
|
||||
{
|
||||
Com_Printf( "sound system not started\n" );
|
||||
return;
|
||||
}
|
||||
#if USE_OPENAL
|
||||
if(sound_started == SS_OAL) {
|
||||
QAL_SoundInfo();
|
||||
Com_Printf("\nNumber of sources: %d\n", s_numchannels);
|
||||
} else
|
||||
#endif
|
||||
DMA_SoundInfo();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
S_Init ( void )
|
||||
{
|
||||
|
@ -116,16 +131,15 @@ S_Init ( void )
|
|||
if ( !cv->value )
|
||||
{
|
||||
Com_Printf( "not initializing.\n" );
|
||||
}
|
||||
} else {
|
||||
|
||||
else
|
||||
{
|
||||
s_volume = Cvar_Get( "s_volume", "0.7", CVAR_ARCHIVE );
|
||||
s_khz = Cvar_Get( "s_khz", "44", CVAR_ARCHIVE );
|
||||
s_loadas8bit = Cvar_Get( "s_loadas8bit", "0", CVAR_ARCHIVE );
|
||||
s_mixahead = Cvar_Get( "s_mixahead", "0.14", CVAR_ARCHIVE );
|
||||
s_show = Cvar_Get( "s_show", "0", 0 );
|
||||
s_testsound = Cvar_Get( "s_testsound", "0", 0 );
|
||||
s_ambient = Cvar_Get( "s_ambient", "1", 0);
|
||||
|
||||
Cmd_AddCommand( "play", S_Play );
|
||||
Cmd_AddCommand( "stopsound", S_StopAllSounds );
|
||||
|
@ -136,20 +150,37 @@ S_Init ( void )
|
|||
Cmd_AddCommand( "ogg_shutdown", OGG_Shutdown );
|
||||
#endif
|
||||
|
||||
if ( !SNDDMA_Init() )
|
||||
#if USE_OPENAL
|
||||
cv = Cvar_Get( "s_openal", "1", CVAR_ARCHIVE);
|
||||
if( cv->value && AL_Init() ) {
|
||||
sound_started = SS_OAL;
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
if ( SNDDMA_Init() )
|
||||
{
|
||||
sound_started = SS_DMA;
|
||||
} else {
|
||||
sound_started = SS_NOT;
|
||||
return;
|
||||
}
|
||||
#if USE_OPENAL
|
||||
} /* this is a bit ugly but prevents dangling else problems */
|
||||
#endif
|
||||
|
||||
S_InitScaletable();
|
||||
|
||||
sound_started = 1;
|
||||
num_sfx = 0;
|
||||
|
||||
soundtime = 0;
|
||||
paintedtime = 0;
|
||||
|
||||
Com_Printf( "sound sampling rate: %i\n", dma.speed );
|
||||
#if USE_OPENAL
|
||||
if(sound_started == SS_DMA)
|
||||
{
|
||||
Com_Printf( "Sound sampling rate: %i\n", dma.speed );
|
||||
}
|
||||
#else
|
||||
Com_Printf( "Sound sampling rate: %i\n", dma.speed );
|
||||
#endif
|
||||
|
||||
S_StopAllSounds();
|
||||
#ifdef OGG
|
||||
|
@ -174,6 +205,8 @@ S_Shutdown ( void )
|
|||
return;
|
||||
}
|
||||
|
||||
S_StopAllSounds();
|
||||
|
||||
/* free all sounds */
|
||||
for ( i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++ )
|
||||
{
|
||||
|
@ -181,23 +214,41 @@ S_Shutdown ( void )
|
|||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
#if USE_OPENAL
|
||||
if ( sound_started == SS_OAL )
|
||||
{
|
||||
AL_DeleteSfx( sfx );
|
||||
}
|
||||
#endif
|
||||
if ( sfx->cache )
|
||||
{
|
||||
Z_Free( sfx->cache );
|
||||
}
|
||||
if ( sfx->truename )
|
||||
{
|
||||
Z_Free( sfx-> truename );
|
||||
}
|
||||
}
|
||||
|
||||
memset( known_sfx, 0, sizeof ( known_sfx ) );
|
||||
|
||||
num_sfx = 0;
|
||||
sound_started = 0;
|
||||
|
||||
#ifdef OGG
|
||||
OGG_Shutdown();
|
||||
#endif
|
||||
|
||||
#if USE_OPENAL
|
||||
if( sound_started == SS_OAL )
|
||||
{
|
||||
AL_Shutdown();
|
||||
} else
|
||||
#endif
|
||||
SNDDMA_Shutdown();
|
||||
|
||||
sound_started = SS_NOT;
|
||||
s_numchannels = 0;
|
||||
|
||||
Cmd_RemoveCommand( "soundlist" );
|
||||
Cmd_RemoveCommand( "soundinfo" );
|
||||
Cmd_RemoveCommand( "play" );
|
||||
|
@ -407,7 +458,7 @@ S_PickChannel ( int entnum, int entchannel )
|
|||
first_to_die = -1;
|
||||
life_left = 0x7fffffff;
|
||||
|
||||
for ( ch_idx = 0; ch_idx < MAX_CHANNELS; ch_idx++ )
|
||||
for ( ch_idx = 0; ch_idx < s_numchannels; ch_idx++ )
|
||||
{
|
||||
/* channel 0 never overrides */
|
||||
if ( ( entchannel != 0 ) &&
|
||||
|
@ -438,6 +489,13 @@ S_PickChannel ( int entnum, int entchannel )
|
|||
}
|
||||
|
||||
ch = &channels [ first_to_die ];
|
||||
|
||||
#if USE_OPENAL
|
||||
if( sound_started == SS_OAL && ch->sfx )
|
||||
{
|
||||
AL_StopChannel( ch );
|
||||
}
|
||||
#endif
|
||||
memset( ch, 0, sizeof ( *ch ) );
|
||||
|
||||
return ( ch );
|
||||
|
@ -593,6 +651,13 @@ S_IssuePlaysound ( playsound_t *ps )
|
|||
return;
|
||||
}
|
||||
|
||||
sc = S_LoadSound( ps->sfx );
|
||||
if( !sc ) {
|
||||
Com_Printf( "S_IssuePlaysound: couldn't load %s\n", ps->sfx->name );
|
||||
S_FreePlaysound( ps );
|
||||
return;
|
||||
}
|
||||
|
||||
/* spatialize */
|
||||
if ( ps->attenuation == ATTN_STATIC )
|
||||
{
|
||||
|
@ -611,16 +676,15 @@ S_IssuePlaysound ( playsound_t *ps )
|
|||
VectorCopy( ps->origin, ch->origin );
|
||||
ch->fixed_origin = ps->fixed_origin;
|
||||
|
||||
#if USE_OPENAL
|
||||
if( sound_started == SS_OAL)
|
||||
{
|
||||
AL_PlayChannel( ch );
|
||||
} else
|
||||
#endif
|
||||
S_Spatialize( ch );
|
||||
|
||||
ch->pos = 0;
|
||||
sc = S_LoadSound( ch->sfx );
|
||||
|
||||
if (!sc)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ch->end = paintedtime + sc->length;
|
||||
|
||||
/* free the playsound */
|
||||
|
@ -690,6 +754,28 @@ S_RegisterSexedSound ( entity_state_t *ent, char *base )
|
|||
return ( sfx );
|
||||
}
|
||||
|
||||
static int DMA_DriftBeginofs( float timeofs ) {
|
||||
/* drift s_beginofs */
|
||||
int start = (int) ( cl.frame.servertime * 0.001f * dma.speed + s_beginofs );
|
||||
|
||||
if ( start < paintedtime )
|
||||
{
|
||||
start = paintedtime;
|
||||
s_beginofs = (int) ( start - ( cl.frame.servertime * 0.001f * dma.speed ) );
|
||||
}
|
||||
else if ( start > paintedtime + 0.3f * dma.speed )
|
||||
{
|
||||
start = (int) ( paintedtime + 0.1f * dma.speed );
|
||||
s_beginofs = (int) ( start - ( cl.frame.servertime * 0.001f * dma.speed ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
s_beginofs -= 10;
|
||||
}
|
||||
|
||||
return timeofs ? start + timeofs * dma.speed : paintedtime;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validates the parms and ques the sound up if pos is NULL, the sound
|
||||
* will be dynamically sourced from the entity Entchannel 0 will never
|
||||
|
@ -699,9 +785,7 @@ void
|
|||
S_StartSound ( vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs )
|
||||
{
|
||||
sfxcache_t *sc;
|
||||
int vol;
|
||||
playsound_t *ps, *sort;
|
||||
int start;
|
||||
|
||||
if ( !sound_started )
|
||||
{
|
||||
|
@ -716,6 +800,9 @@ S_StartSound ( vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol
|
|||
if ( sfx->name [ 0 ] == '*' )
|
||||
{
|
||||
sfx = S_RegisterSexedSound( &cl_entities [ entnum ].current, sfx->name );
|
||||
if( !sfx ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* make sure the sound is loaded */
|
||||
|
@ -726,8 +813,6 @@ S_StartSound ( vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol
|
|||
return; /* couldn't load the sound's data */
|
||||
}
|
||||
|
||||
vol = fvol * 255;
|
||||
|
||||
/* make the playsound_t */
|
||||
ps = S_AllocPlaysound();
|
||||
|
||||
|
@ -749,37 +834,20 @@ S_StartSound ( vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol
|
|||
ps->entnum = entnum;
|
||||
ps->entchannel = entchannel;
|
||||
ps->attenuation = attenuation;
|
||||
ps->volume = vol;
|
||||
ps->sfx = sfx;
|
||||
|
||||
/* drift s_beginofs */
|
||||
start = (int) ( cl.frame.servertime * 0.001f * dma.speed + s_beginofs );
|
||||
|
||||
if ( start < paintedtime )
|
||||
#if USE_OPENAL
|
||||
if( sound_started == SS_OAL )
|
||||
{
|
||||
start = paintedtime;
|
||||
s_beginofs = (int) ( start - ( cl.frame.servertime * 0.001f * dma.speed ) );
|
||||
}
|
||||
else if ( start > paintedtime + 0.3f * dma.speed )
|
||||
{
|
||||
start = (int) ( paintedtime + 0.1f * dma.speed );
|
||||
s_beginofs = (int) ( start - ( cl.frame.servertime * 0.001f * dma.speed ) );
|
||||
ps->begin = paintedtime + timeofs * 1000;
|
||||
ps->volume = fvol * 384;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
s_beginofs -= 10;
|
||||
}
|
||||
|
||||
if ( !timeofs )
|
||||
{
|
||||
ps->begin = paintedtime;
|
||||
}
|
||||
else
|
||||
{
|
||||
ps->begin = (int) ( start + timeofs * dma.speed );
|
||||
}
|
||||
|
||||
ps->begin = DMA_DriftBeginofs(timeofs);
|
||||
ps->volume = fvol * 255;
|
||||
}
|
||||
|
||||
/* sort into the pending sound list */
|
||||
for ( sort = s_pendingplays.next;
|
||||
|
@ -832,7 +900,6 @@ S_ClearBuffer ( void )
|
|||
{
|
||||
clear = 0x80;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
clear = 0;
|
||||
|
@ -880,10 +947,34 @@ S_StopAllSounds ( void )
|
|||
s_playsounds [ i ].next->prev = &s_playsounds [ i ];
|
||||
}
|
||||
|
||||
#if USE_OPENAL
|
||||
if( sound_started == SS_OAL ) {
|
||||
AL_StopAllChannels();
|
||||
} else
|
||||
#endif
|
||||
S_ClearBuffer();
|
||||
|
||||
/* 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.num_entities; i++ )
|
||||
{
|
||||
num = ( cl.frame.parse_entities + i ) & ( MAX_PARSE_ENTITIES - 1 );
|
||||
ent = &cl_parse_entities [ num ];
|
||||
if( s_ambient->value == 2 && !ent->modelindex ) {
|
||||
sounds[i] = 0;
|
||||
} else if( s_ambient->value == 3 && ent->number != cl.playernum + 1) {
|
||||
sounds[i] = 0;
|
||||
} else {
|
||||
sounds[i] = ent->sound;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -914,17 +1005,12 @@ S_AddLoopSounds ( void )
|
|||
return;
|
||||
}
|
||||
|
||||
if ( !cl.sound_prepped )
|
||||
if ( !cl.sound_prepped || !s_ambient->value )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for ( i = 0; i < cl.frame.num_entities; i++ )
|
||||
{
|
||||
num = ( cl.frame.parse_entities + i ) & ( MAX_PARSE_ENTITIES - 1 );
|
||||
ent = &cl_parse_entities [ num ];
|
||||
sounds [ i ] = ent->sound;
|
||||
}
|
||||
S_BuildSoundList( sounds );
|
||||
|
||||
for ( i = 0; i < cl.frame.num_entities; i++ )
|
||||
{
|
||||
|
@ -1042,6 +1128,14 @@ S_RawSamples ( int samples, int rate, int width, int channels, byte *data, float
|
|||
s_rawend = paintedtime;
|
||||
}
|
||||
|
||||
#if USE_OPENAL
|
||||
if( sound_started == SS_OAL )
|
||||
{
|
||||
AL_RawSamples(samples, rate, width, channels, data, volume);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
scale = (float) rate / dma.speed;
|
||||
intVolume = (int) (256 * volume);
|
||||
|
||||
|
@ -1094,9 +1188,6 @@ S_RawSamples ( int samples, int rate, int width, int channels, byte *data, float
|
|||
|
||||
dst = s_rawend & ( MAX_RAW_SAMPLES - 1 );
|
||||
s_rawend++;
|
||||
// s_rawsamples [dst].left = ((char *) data)[src * 2] * intVolume;
|
||||
// s_rawsamples [dst].right = ((char *) data)[src * 2 + 1] * intVolume;
|
||||
/* the above doesn't work for me with U8, only the unsigned ones below do */
|
||||
s_rawsamples [dst].left = (((byte *) data)[src * 2] - 128) * intVolume;
|
||||
s_rawsamples [dst].right = (((byte *) data)[src * 2 + 1] - 128) * intVolume;
|
||||
}
|
||||
|
@ -1175,14 +1266,10 @@ S_Update ( vec3_t origin, vec3_t forward, vec3_t right, vec3_t up )
|
|||
* dma buffer while loading */
|
||||
if ( cls.disable_screen )
|
||||
{
|
||||
if (sound_started == SS_DMA ) {
|
||||
S_ClearBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
/* rebuild scale tables if volume is modified */
|
||||
if ( s_volume->modified )
|
||||
{
|
||||
S_InitScaletable();
|
||||
return;
|
||||
}
|
||||
|
||||
VectorCopy( origin, listener_origin );
|
||||
|
@ -1190,10 +1277,24 @@ S_Update ( vec3_t origin, vec3_t forward, vec3_t right, vec3_t up )
|
|||
VectorCopy( right, listener_right );
|
||||
VectorCopy( up, listener_up );
|
||||
|
||||
|
||||
#if USE_OPENAL
|
||||
if( sound_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++ )
|
||||
for ( i = 0; i < s_numchannels; i++, ch++ )
|
||||
{
|
||||
if ( !ch->sfx )
|
||||
{
|
||||
|
@ -1225,7 +1326,7 @@ S_Update ( vec3_t origin, vec3_t forward, vec3_t right, vec3_t up )
|
|||
total = 0;
|
||||
ch = channels;
|
||||
|
||||
for ( i = 0; i < MAX_CHANNELS; i++, ch++ )
|
||||
for ( i = 0; i < s_numchannels; i++, ch++ )
|
||||
{
|
||||
if ( ch->sfx && ( ch->leftvol || ch->rightvol ) )
|
||||
{
|
||||
|
|
|
@ -149,10 +149,7 @@ S_LoadSound ( sfx_t *s )
|
|||
if ( name [ 0 ] == '#' )
|
||||
{
|
||||
strcpy( namebuffer, &name [ 1 ] );
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
} else {
|
||||
Com_sprintf( namebuffer, sizeof ( namebuffer ), "sound/%s", name );
|
||||
}
|
||||
|
||||
|
@ -173,7 +170,7 @@ S_LoadSound ( sfx_t *s )
|
|||
FS_FreeFile( data );
|
||||
return ( NULL );
|
||||
}
|
||||
|
||||
if (sound_started != SS_OAL) {
|
||||
stepscale = (float) info.rate / dma.speed;
|
||||
len = (int) ( info.samples / stepscale );
|
||||
|
||||
|
@ -198,7 +195,13 @@ S_LoadSound ( sfx_t *s )
|
|||
sc->speed = info.rate;
|
||||
sc->width = info.width;
|
||||
sc->stereo = info.channels;
|
||||
}
|
||||
|
||||
#if USE_OPENAL
|
||||
if (sound_started == SS_OAL)
|
||||
sc = AL_UploadSfx(s, &info, data + info.dataofs);
|
||||
else
|
||||
#endif
|
||||
ResampleSfx( s, sc->speed, sc->width, data + info.dataofs );
|
||||
|
||||
FS_FreeFile( data );
|
||||
|
|
|
@ -202,12 +202,6 @@ S_PaintChannels ( int endtime )
|
|||
end = paintedtime + PAINTBUFFER_SIZE;
|
||||
}
|
||||
|
||||
/* start any playsounds */
|
||||
if ( endtime - paintedtime > PAINTBUFFER_SIZE )
|
||||
{
|
||||
end = paintedtime + PAINTBUFFER_SIZE;
|
||||
}
|
||||
|
||||
/* start any playsounds */
|
||||
for ( ; ; )
|
||||
{
|
||||
|
@ -258,6 +252,7 @@ S_PaintChannels ( int endtime )
|
|||
|
||||
for ( ; i < end; i++ )
|
||||
{
|
||||
// TODO: this could be done with memset
|
||||
paintbuffer [ i - paintedtime ].left = paintbuffer [ i - paintedtime ].right = 0;
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +260,7 @@ S_PaintChannels ( int endtime )
|
|||
/* paint in the channels. */
|
||||
ch = channels;
|
||||
|
||||
for ( i = 0; i < MAX_CHANNELS; i++, ch++ )
|
||||
for ( i = 0; i < s_numchannels; i++, ch++ )
|
||||
{
|
||||
ltime = paintedtime;
|
||||
|
||||
|
|
|
@ -39,8 +39,9 @@
|
|||
#include "header/local.h"
|
||||
#include "header/vorbis.h"
|
||||
|
||||
extern int sound_started; /* Sound initialization flag. */
|
||||
extern cvar_t *fs_basedir; /* Path to "music". */
|
||||
#ifdef USE_OPENAL
|
||||
void AL_UnqueueRawSamples();
|
||||
#endif
|
||||
|
||||
qboolean ogg_first_init = true; /* First initialization flag. */
|
||||
qboolean ogg_started = false; /* Initialization flag. */
|
||||
|
@ -59,6 +60,7 @@ cvar_t *ogg_sequence; /* Sequence play indicator. */
|
|||
cvar_t *ogg_volume; /* Music volume. */
|
||||
OggVorbis_File ovFile; /* Ogg Vorbis file. */
|
||||
vorbis_info *ogg_info; /* Ogg Vorbis file information */
|
||||
int ogg_numbufs; /* Number of buffers for OpenAL */
|
||||
|
||||
/*
|
||||
* Initialize the Ogg Vorbis subsystem.
|
||||
|
@ -585,9 +587,14 @@ OGG_Stop ( void )
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_OPENAL
|
||||
AL_UnqueueRawSamples();
|
||||
#endif
|
||||
|
||||
ov_clear( &ovFile );
|
||||
ogg_status = STOP;
|
||||
ogg_info = NULL;
|
||||
ogg_numbufs = 0;
|
||||
|
||||
if ( ogg_buffer != NULL )
|
||||
{
|
||||
|
@ -607,10 +614,50 @@ OGG_Stream ( void )
|
|||
return;
|
||||
}
|
||||
|
||||
while ( ogg_status == PLAY && paintedtime + MAX_RAW_SAMPLES - 2048 > s_rawend )
|
||||
|
||||
if ( ogg_status == PLAY )
|
||||
{
|
||||
#ifdef USE_OPENAL
|
||||
if ( sound_started == SS_OAL )
|
||||
{
|
||||
/* Calculate the number of buffers used
|
||||
for storing decoded OGG/Vorbis data.
|
||||
We take the number of active buffers
|
||||
at startup (at this point most of the
|
||||
samples should be precached and loaded
|
||||
into buffers) and add 64. Empircal
|
||||
testing showed, that at most times
|
||||
at least 52 buffers remain available
|
||||
for OGG/Vorbis, enough for about 3
|
||||
seconds playback. The music won't
|
||||
stutter as long as the framerate
|
||||
stayes over 1 FPS. */
|
||||
if ( ogg_numbufs == 0 )
|
||||
{
|
||||
ogg_numbufs = active_buffers + 64;
|
||||
}
|
||||
|
||||
/* active_buffers are all active OpenAL buffers,
|
||||
buffering normal sfx _and_ ogg/vorbis samples. */
|
||||
while ( active_buffers <= ogg_numbufs )
|
||||
{
|
||||
OGG_Read();
|
||||
}
|
||||
} else { /* using DMA/SDL */
|
||||
#endif
|
||||
/* Read that number samples into the buffer, that
|
||||
were played since the last call to this function.
|
||||
This keeps the buffer at all times at an "optimal"
|
||||
fill level. */
|
||||
while ( paintedtime + MAX_RAW_SAMPLES - 2048 > s_rawend )
|
||||
{
|
||||
OGG_Read();
|
||||
}
|
||||
#ifdef USE_OPENAL
|
||||
} /* using DMA/SDL */
|
||||
#endif
|
||||
} /* ogg_status == PLAY */
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -695,6 +742,7 @@ OGG_PauseCmd ( void )
|
|||
if ( ogg_status == PLAY )
|
||||
{
|
||||
ogg_status = PAUSE;
|
||||
ogg_numbufs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include "../header/client.h"
|
||||
#include "header/local.h"
|
||||
|
||||
// FIXME: this code is really fucked up, those global variables make me sick.
|
||||
// someone should clean this up one day..
|
||||
|
||||
byte *data_p;
|
||||
byte *iff_end;
|
||||
byte *last_chunk;
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
|
||||
#include "header/common.h"
|
||||
|
||||
#if !defined(DEDICATED_ONLY) && defined(USE_OPENAL)
|
||||
void AL_Underwater();
|
||||
void AL_Overwater();
|
||||
#endif
|
||||
|
||||
#define STEPSIZE 18
|
||||
|
||||
/* all of the locals will be zeroed before each
|
||||
|
@ -1108,6 +1113,10 @@ void PM_ClampAngles (void)
|
|||
*/
|
||||
void Pmove (pmove_t *pmove)
|
||||
{
|
||||
#if !defined(DEDICATED_ONLY) && defined(USE_OPENAL)
|
||||
static int underwater;
|
||||
#endif
|
||||
|
||||
pm = pmove;
|
||||
|
||||
/* clear results */
|
||||
|
@ -1235,5 +1244,19 @@ void Pmove (pmove_t *pmove)
|
|||
/* set groundentity, watertype, and waterlevel for final spot */
|
||||
PM_CatagorizePosition ();
|
||||
|
||||
#if !defined(DEDICATED_ONLY) && defined(USE_OPENAL)
|
||||
if ((pm->waterlevel == 3) && !underwater)
|
||||
{
|
||||
underwater = 1;
|
||||
AL_Underwater();
|
||||
}
|
||||
|
||||
if ((pm->waterlevel < 3 && underwater))
|
||||
{
|
||||
underwater = 0;
|
||||
AL_Overwater();
|
||||
}
|
||||
#endif
|
||||
|
||||
PM_SnapPosition ();
|
||||
}
|
||||
|
|
|
@ -208,6 +208,9 @@ SNDDMA_Init(void)
|
|||
dmasize = (dmabackend->samples * (dmabackend->samplebits / 8));
|
||||
dmabackend->buffer = calloc(1, dmasize);
|
||||
|
||||
s_numchannels = MAX_CHANNELS;
|
||||
S_InitScaletable();
|
||||
|
||||
SDL_PauseAudio(0);
|
||||
|
||||
Com_Printf("SDL audio initialized.\n");
|
||||
|
|
137
src/unix/header/qal.h
Normal file
137
src/unix/header/qal.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Yamagi Burmeister
|
||||
* 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.
|
||||
*
|
||||
* =======================================================================
|
||||
*
|
||||
* Header file to the low level "qal" API implementation. This source file
|
||||
* was taken from Q2Pro and modified by the YQ2 authors.
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#ifdef USE_OPENAL
|
||||
|
||||
#ifndef _QAL_API_H_
|
||||
#define _QAL_API_H_
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <AL/efx.h>
|
||||
|
||||
/* Function pointers used to tie
|
||||
the qal API to the OpenAL API */
|
||||
extern LPALENABLE qalEnable;
|
||||
extern LPALDISABLE qalDisable;
|
||||
extern LPALISENABLED qalIsEnabled;
|
||||
extern LPALGETSTRING qalGetString;
|
||||
extern LPALGETBOOLEANV qalGetBooleanv;
|
||||
extern LPALGETINTEGERV qalGetIntegerv;
|
||||
extern LPALGETFLOATV qalGetFloatv;
|
||||
extern LPALGETDOUBLEV qalGetDoublev;
|
||||
extern LPALGETBOOLEAN qalGetBoolean;
|
||||
extern LPALGETINTEGER qalGetInteger;
|
||||
extern LPALGETFLOAT qalGetFloat;
|
||||
extern LPALGETDOUBLE qalGetDouble;
|
||||
extern LPALGETERROR qalGetError;
|
||||
extern LPALISEXTENSIONPRESENT qalIsExtensionPresent;
|
||||
extern LPALGETPROCADDRESS qalGetProcAddress;
|
||||
extern LPALGETENUMVALUE qalGetEnumValue;
|
||||
extern LPALLISTENERF qalListenerf;
|
||||
extern LPALLISTENER3F qalListener3f;
|
||||
extern LPALLISTENERFV qalListenerfv;
|
||||
extern LPALLISTENERI qalListeneri;
|
||||
extern LPALLISTENER3I qalListener3i;
|
||||
extern LPALLISTENERIV qalListeneriv;
|
||||
extern LPALGETLISTENERF qalGetListenerf;
|
||||
extern LPALGETLISTENER3F qalGetListener3f;
|
||||
extern LPALGETLISTENERFV qalGetListenerfv;
|
||||
extern LPALGETLISTENERI qalGetListeneri;
|
||||
extern LPALGETLISTENER3I qalGetListener3i;
|
||||
extern LPALGETLISTENERIV qalGetListeneriv;
|
||||
extern LPALGENSOURCES qalGenSources;
|
||||
extern LPALDELETESOURCES qalDeleteSources;
|
||||
extern LPALISSOURCE qalIsSource;
|
||||
extern LPALSOURCEF qalSourcef;
|
||||
extern LPALSOURCE3F qalSource3f;
|
||||
extern LPALSOURCEFV qalSourcefv;
|
||||
extern LPALSOURCEI qalSourcei;
|
||||
extern LPALSOURCE3I qalSource3i;
|
||||
extern LPALSOURCEIV qalSourceiv;
|
||||
extern LPALGETSOURCEF qalGetSourcef;
|
||||
extern LPALGETSOURCE3F qalGetSource3f;
|
||||
extern LPALGETSOURCEFV qalGetSourcefv;
|
||||
extern LPALGETSOURCEI qalGetSourcei;
|
||||
extern LPALGETSOURCE3I qalGetSource3i;
|
||||
extern LPALGETSOURCEIV qalGetSourceiv;
|
||||
extern LPALSOURCEPLAYV qalSourcePlayv;
|
||||
extern LPALSOURCESTOPV qalSourceStopv;
|
||||
extern LPALSOURCEREWINDV qalSourceRewindv;
|
||||
extern LPALSOURCEPAUSEV qalSourcePausev;
|
||||
extern LPALSOURCEPLAY qalSourcePlay;
|
||||
extern LPALSOURCESTOP qalSourceStop;
|
||||
extern LPALSOURCEREWIND qalSourceRewind;
|
||||
extern LPALSOURCEPAUSE qalSourcePause;
|
||||
extern LPALSOURCEQUEUEBUFFERS qalSourceQueueBuffers;
|
||||
extern LPALSOURCEUNQUEUEBUFFERS qalSourceUnqueueBuffers;
|
||||
extern LPALGENBUFFERS qalGenBuffers;
|
||||
extern LPALDELETEBUFFERS qalDeleteBuffers;
|
||||
extern LPALISBUFFER qalIsBuffer;
|
||||
extern LPALBUFFERDATA qalBufferData;
|
||||
extern LPALBUFFERF qalBufferf;
|
||||
extern LPALBUFFER3F qalBuffer3f;
|
||||
extern LPALBUFFERFV qalBufferfv;
|
||||
extern LPALBUFFERI qalBufferi;
|
||||
extern LPALBUFFER3I qalBuffer3i;
|
||||
extern LPALBUFFERIV qalBufferiv;
|
||||
extern LPALGETBUFFERF qalGetBufferf;
|
||||
extern LPALGETBUFFER3F qalGetBuffer3f;
|
||||
extern LPALGETBUFFERFV qalGetBufferfv;
|
||||
extern LPALGETBUFFERI qalGetBufferi;
|
||||
extern LPALGETBUFFER3I qalGetBuffer3i;
|
||||
extern LPALGETBUFFERIV qalGetBufferiv;
|
||||
extern LPALDOPPLERFACTOR qalDopplerFactor;
|
||||
extern LPALDOPPLERVELOCITY qalDopplerVelocity;
|
||||
extern LPALSPEEDOFSOUND qalSpeedOfSound;
|
||||
extern LPALDISTANCEMODEL qalDistanceModel;
|
||||
extern LPALGENFILTERS qalGenFilters;
|
||||
extern LPALFILTERI qalFilteri;
|
||||
extern LPALFILTERF qalFilterf;
|
||||
extern LPALDELETEFILTERS qalDeleteFilters;
|
||||
|
||||
/*
|
||||
* Gives information over the OpenAL
|
||||
* implementation and it's state
|
||||
*/
|
||||
void QAL_SoundInfo(void);
|
||||
|
||||
/*
|
||||
* Loads the OpenAL shared lib, creates
|
||||
* a context and device handle.
|
||||
*/
|
||||
qboolean QAL_Init(void);
|
||||
|
||||
/*
|
||||
* Shuts OpenAL down, frees all context and
|
||||
* device handles and unloads the shared lib.
|
||||
*/
|
||||
void QAL_Shutdown(void);
|
||||
|
||||
#endif /* _QAL_API_H_ */
|
||||
#endif /* USE_OPENAL */
|
||||
|
501
src/unix/qal.c
Normal file
501
src/unix/qal.c
Normal file
|
@ -0,0 +1,501 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Yamagi Burmeister
|
||||
* 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.
|
||||
*
|
||||
* =======================================================================
|
||||
*
|
||||
* Low level, platform depended "qal" API implementation. This files
|
||||
* provides functions to load, initialize, shutdown und unload the
|
||||
* OpenAL library and connects the "qal" funtion pointers to the
|
||||
* OpenAL functions. This source file was taken from Q2Pro and
|
||||
* modified by the YQ2 authors.
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#ifdef USE_OPENAL
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#include <AL/alext.h>
|
||||
|
||||
#include "../common/header/common.h"
|
||||
#include "header/qal.h"
|
||||
|
||||
static ALCcontext *context;
|
||||
static ALCdevice *device;
|
||||
static cvar_t *al_device;
|
||||
static cvar_t *al_driver;
|
||||
static void *handle;
|
||||
|
||||
/* Function pointers for OpenAL management */
|
||||
static LPALCCREATECONTEXT qalcCreateContext;
|
||||
static LPALCMAKECONTEXTCURRENT qalcMakeContextCurrent;
|
||||
static LPALCPROCESSCONTEXT qalcProcessContext;
|
||||
static LPALCSUSPENDCONTEXT qalcSuspendContext;
|
||||
static LPALCDESTROYCONTEXT qalcDestroyContext;
|
||||
static LPALCGETCURRENTCONTEXT qalcGetCurrentContext;
|
||||
static LPALCGETCONTEXTSDEVICE qalcGetContextsDevice;
|
||||
static LPALCOPENDEVICE qalcOpenDevice;
|
||||
static LPALCCLOSEDEVICE qalcCloseDevice;
|
||||
static LPALCGETERROR qalcGetError;
|
||||
static LPALCISEXTENSIONPRESENT qalcIsExtensionPresent;
|
||||
static LPALCGETPROCADDRESS qalcGetProcAddress;
|
||||
static LPALCGETENUMVALUE qalcGetEnumValue;
|
||||
static LPALCGETSTRING qalcGetString;
|
||||
static LPALCGETINTEGERV qalcGetIntegerv;
|
||||
static LPALCCAPTUREOPENDEVICE qalcCaptureOpenDevice;
|
||||
static LPALCCAPTURECLOSEDEVICE qalcCaptureCloseDevice;
|
||||
static LPALCCAPTURESTART qalcCaptureStart;
|
||||
static LPALCCAPTURESTOP qalcCaptureStop;
|
||||
static LPALCCAPTURESAMPLES qalcCaptureSamples ;
|
||||
|
||||
/* Declaration of function pointers used
|
||||
to connect OpenAL to our internal API */
|
||||
LPALENABLE qalEnable;
|
||||
LPALDISABLE qalDisable;
|
||||
LPALISENABLED qalIsEnabled;
|
||||
LPALGETSTRING qalGetString;
|
||||
LPALGETBOOLEANV qalGetBooleanv;
|
||||
LPALGETINTEGERV qalGetIntegerv;
|
||||
LPALGETFLOATV qalGetFloatv;
|
||||
LPALGETDOUBLEV qalGetDoublev;
|
||||
LPALGETBOOLEAN qalGetBoolean;
|
||||
LPALGETINTEGER qalGetInteger;
|
||||
LPALGETFLOAT qalGetFloat;
|
||||
LPALGETDOUBLE qalGetDouble;
|
||||
LPALGETERROR qalGetError;
|
||||
LPALISEXTENSIONPRESENT qalIsExtensionPresent;
|
||||
LPALGETPROCADDRESS qalGetProcAddress;
|
||||
LPALGETENUMVALUE qalGetEnumValue;
|
||||
LPALLISTENERF qalListenerf;
|
||||
LPALLISTENER3F qalListener3f;
|
||||
LPALLISTENERFV qalListenerfv;
|
||||
LPALLISTENERI qalListeneri;
|
||||
LPALLISTENER3I qalListener3i;
|
||||
LPALLISTENERIV qalListeneriv;
|
||||
LPALGETLISTENERF qalGetListenerf;
|
||||
LPALGETLISTENER3F qalGetListener3f;
|
||||
LPALGETLISTENERFV qalGetListenerfv;
|
||||
LPALGETLISTENERI qalGetListeneri;
|
||||
LPALGETLISTENER3I qalGetListener3i;
|
||||
LPALGETLISTENERIV qalGetListeneriv;
|
||||
LPALGENSOURCES qalGenSources;
|
||||
LPALDELETESOURCES qalDeleteSources;
|
||||
LPALISSOURCE qalIsSource;
|
||||
LPALSOURCEF qalSourcef;
|
||||
LPALSOURCE3F qalSource3f;
|
||||
LPALSOURCEFV qalSourcefv;
|
||||
LPALSOURCEI qalSourcei;
|
||||
LPALSOURCE3I qalSource3i;
|
||||
LPALSOURCEIV qalSourceiv;
|
||||
LPALGETSOURCEF qalGetSourcef;
|
||||
LPALGETSOURCE3F qalGetSource3f;
|
||||
LPALGETSOURCEFV qalGetSourcefv;
|
||||
LPALGETSOURCEI qalGetSourcei;
|
||||
LPALGETSOURCE3I qalGetSource3i;
|
||||
LPALGETSOURCEIV qalGetSourceiv;
|
||||
LPALSOURCEPLAYV qalSourcePlayv;
|
||||
LPALSOURCESTOPV qalSourceStopv;
|
||||
LPALSOURCEREWINDV qalSourceRewindv;
|
||||
LPALSOURCEPAUSEV qalSourcePausev;
|
||||
LPALSOURCEPLAY qalSourcePlay;
|
||||
LPALSOURCESTOP qalSourceStop;
|
||||
LPALSOURCEREWIND qalSourceRewind;
|
||||
LPALSOURCEPAUSE qalSourcePause;
|
||||
LPALSOURCEQUEUEBUFFERS qalSourceQueueBuffers;
|
||||
LPALSOURCEUNQUEUEBUFFERS qalSourceUnqueueBuffers;
|
||||
LPALGENBUFFERS qalGenBuffers;
|
||||
LPALDELETEBUFFERS qalDeleteBuffers;
|
||||
LPALISBUFFER qalIsBuffer;
|
||||
LPALBUFFERDATA qalBufferData;
|
||||
LPALBUFFERF qalBufferf;
|
||||
LPALBUFFER3F qalBuffer3f;
|
||||
LPALBUFFERFV qalBufferfv;
|
||||
LPALBUFFERI qalBufferi;
|
||||
LPALBUFFER3I qalBuffer3i;
|
||||
LPALBUFFERIV qalBufferiv;
|
||||
LPALGETBUFFERF qalGetBufferf;
|
||||
LPALGETBUFFER3F qalGetBuffer3f;
|
||||
LPALGETBUFFERFV qalGetBufferfv;
|
||||
LPALGETBUFFERI qalGetBufferi;
|
||||
LPALGETBUFFER3I qalGetBuffer3i;
|
||||
LPALGETBUFFERIV qalGetBufferiv;
|
||||
LPALDOPPLERFACTOR qalDopplerFactor;
|
||||
LPALDOPPLERVELOCITY qalDopplerVelocity;
|
||||
LPALSPEEDOFSOUND qalSpeedOfSound;
|
||||
LPALDISTANCEMODEL qalDistanceModel;
|
||||
LPALGENFILTERS qalGenFilters;
|
||||
LPALFILTERI qalFilteri;
|
||||
LPALFILTERF qalFilterf;
|
||||
LPALDELETEFILTERS qalDeleteFilters;
|
||||
|
||||
/*
|
||||
* Gives information over the OpenAL
|
||||
* implementation and it's state
|
||||
*/
|
||||
void QAL_SoundInfo()
|
||||
{
|
||||
Com_Printf("OpenAL settings:\n");
|
||||
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));
|
||||
|
||||
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT"))
|
||||
{
|
||||
const char *devs = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
|
||||
|
||||
Com_Printf("\nAvailable OpenAL devices:\n");
|
||||
|
||||
if (devs == NULL)
|
||||
{
|
||||
Com_Printf("- No devices found. Depending on your\n");
|
||||
Com_Printf(" platform this may be expected and\n");
|
||||
Com_Printf(" doesn't indicate a problem!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
while (devs && *devs)
|
||||
{
|
||||
Com_Printf("- %s\n", devs);
|
||||
devs += strlen(devs) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT"))
|
||||
{
|
||||
const char *devs = alcGetString(device, ALC_DEVICE_SPECIFIER);
|
||||
|
||||
Com_Printf("\nCurrent OpenAL device:\n");
|
||||
|
||||
if (devs == NULL)
|
||||
{
|
||||
Com_Printf("- No OpenAL device in use\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Printf("- %s\n", devs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Shuts OpenAL down, frees all context and
|
||||
* device handles and unloads the shared lib.
|
||||
*/
|
||||
void
|
||||
QAL_Shutdown()
|
||||
{
|
||||
if (context)
|
||||
{
|
||||
qalcMakeContextCurrent( NULL );
|
||||
qalcDestroyContext( context );
|
||||
context = NULL;
|
||||
}
|
||||
|
||||
if (device)
|
||||
{
|
||||
qalcCloseDevice( device );
|
||||
device = NULL;
|
||||
}
|
||||
|
||||
/* Disconnect function pointers used
|
||||
for OpenAL management calls */
|
||||
qalcCreateContext = NULL;
|
||||
qalcMakeContextCurrent = NULL;
|
||||
qalcProcessContext = NULL;
|
||||
qalcSuspendContext = NULL;
|
||||
qalcDestroyContext = NULL;
|
||||
qalcGetCurrentContext = NULL;
|
||||
qalcGetContextsDevice = NULL;
|
||||
qalcOpenDevice = NULL;
|
||||
qalcCloseDevice = NULL;
|
||||
qalcGetError = NULL;
|
||||
qalcIsExtensionPresent = NULL;
|
||||
qalcGetProcAddress = NULL;
|
||||
qalcGetEnumValue = NULL;
|
||||
qalcGetString = NULL;
|
||||
qalcGetIntegerv = NULL;
|
||||
qalcCaptureOpenDevice = NULL;
|
||||
qalcCaptureCloseDevice = NULL;
|
||||
qalcCaptureStart = NULL;
|
||||
qalcCaptureStop = NULL;
|
||||
qalcCaptureSamples = NULL;
|
||||
|
||||
/* Disconnect OpenAL
|
||||
* function pointers */
|
||||
qalEnable = NULL;
|
||||
qalDisable = NULL;
|
||||
qalIsEnabled = NULL;
|
||||
qalGetString = NULL;
|
||||
qalGetBooleanv = NULL;
|
||||
qalGetIntegerv = NULL;
|
||||
qalGetFloatv = NULL;
|
||||
qalGetDoublev = NULL;
|
||||
qalGetBoolean = NULL;
|
||||
qalGetInteger = NULL;
|
||||
qalGetFloat = NULL;
|
||||
qalGetDouble = NULL;
|
||||
qalGetError = NULL;
|
||||
qalIsExtensionPresent = NULL;
|
||||
qalGetProcAddress = NULL;
|
||||
qalGetEnumValue = NULL;
|
||||
qalListenerf = NULL;
|
||||
qalListener3f = NULL;
|
||||
qalListenerfv = NULL;
|
||||
qalListeneri = NULL;
|
||||
qalListener3i = NULL;
|
||||
qalListeneriv = NULL;
|
||||
qalGetListenerf = NULL;
|
||||
qalGetListener3f = NULL;
|
||||
qalGetListenerfv = NULL;
|
||||
qalGetListeneri = NULL;
|
||||
qalGetListener3i = NULL;
|
||||
qalGetListeneriv = NULL;
|
||||
qalGenSources = NULL;
|
||||
qalDeleteSources = NULL;
|
||||
qalIsSource = NULL;
|
||||
qalSourcef = NULL;
|
||||
qalSource3f = NULL;
|
||||
qalSourcefv = NULL;
|
||||
qalSourcei = NULL;
|
||||
qalSource3i = NULL;
|
||||
qalSourceiv = NULL;
|
||||
qalGetSourcef = NULL;
|
||||
qalGetSource3f = NULL;
|
||||
qalGetSourcefv = NULL;
|
||||
qalGetSourcei = NULL;
|
||||
qalGetSource3i = NULL;
|
||||
qalGetSourceiv = NULL;
|
||||
qalSourcePlayv = NULL;
|
||||
qalSourceStopv = NULL;
|
||||
qalSourceRewindv = NULL;
|
||||
qalSourcePausev = NULL;
|
||||
qalSourcePlay = NULL;
|
||||
qalSourceStop = NULL;
|
||||
qalSourceRewind = NULL;
|
||||
qalSourcePause = NULL;
|
||||
qalSourceQueueBuffers = NULL;
|
||||
qalSourceUnqueueBuffers = NULL;
|
||||
qalGenBuffers = NULL;
|
||||
qalDeleteBuffers = NULL;
|
||||
qalIsBuffer = NULL;
|
||||
qalBufferData = NULL;
|
||||
qalBufferf = NULL;
|
||||
qalBuffer3f = NULL;
|
||||
qalBufferfv = NULL;
|
||||
qalBufferi = NULL;
|
||||
qalBuffer3i = NULL;
|
||||
qalBufferiv = NULL;
|
||||
qalGetBufferf = NULL;
|
||||
qalGetBuffer3f = NULL;
|
||||
qalGetBufferfv = NULL;
|
||||
qalGetBufferi = NULL;
|
||||
qalGetBuffer3i = NULL;
|
||||
qalGetBufferiv = NULL;
|
||||
qalDopplerFactor = NULL;
|
||||
qalDopplerVelocity = NULL;
|
||||
qalSpeedOfSound = NULL;
|
||||
qalDistanceModel = NULL;
|
||||
qalGenFilters = NULL;
|
||||
qalFilteri = NULL;
|
||||
qalFilterf = NULL;
|
||||
qalDeleteFilters = NULL;
|
||||
|
||||
/* Unload the shared lib */
|
||||
dlclose(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads the OpenAL shared lib, creates
|
||||
* a context and device handle.
|
||||
*/
|
||||
qboolean
|
||||
QAL_Init()
|
||||
{
|
||||
/* DEFAULT_OPENAL_DRIVER is defined at compile time via the compiler */
|
||||
al_driver = Cvar_Get( "al_driver", DEFAULT_OPENAL_DRIVER, CVAR_ARCHIVE );
|
||||
al_device = Cvar_Get( "al_device", "", CVAR_ARCHIVE );
|
||||
|
||||
Com_Printf("LoadLibrary(%s)\n", al_driver->string);
|
||||
|
||||
/* Load the library */
|
||||
handle = dlopen( al_driver->string, RTLD_LAZY );
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Connect function pointers to management functions */
|
||||
qalcCreateContext = dlsym(handle, "alcCreateContext");
|
||||
qalcMakeContextCurrent = dlsym(handle, "alcMakeContextCurrent");
|
||||
qalcProcessContext = dlsym(handle, "alcProcessContext");
|
||||
qalcSuspendContext = dlsym(handle, "alcSuspendContext");
|
||||
qalcDestroyContext = dlsym(handle, "alcDestroyContext");
|
||||
qalcGetCurrentContext = dlsym(handle, "alcGetCurrentContext");
|
||||
qalcGetContextsDevice = dlsym(handle, "alcGetContextsDevice");
|
||||
qalcOpenDevice = dlsym(handle, "alcOpenDevice");
|
||||
qalcCloseDevice = dlsym(handle, "alcCloseDevice");
|
||||
qalcGetError = dlsym(handle, "alcGetError");
|
||||
qalcIsExtensionPresent = dlsym(handle, "alcIsExtensionPresent");
|
||||
qalcGetProcAddress = dlsym(handle, "alcGetProcAddress");
|
||||
qalcGetEnumValue = dlsym(handle, "alcGetEnumValue");
|
||||
qalcGetString = dlsym(handle, "alcGetString");
|
||||
qalcGetIntegerv = dlsym(handle, "alcGetIntegerv");
|
||||
qalcCaptureOpenDevice = dlsym(handle, "alcCaptureOpenDevice");
|
||||
qalcCaptureCloseDevice = dlsym(handle, "alcCaptureCloseDevice");
|
||||
qalcCaptureStart = dlsym(handle, "alcCaptureStart");
|
||||
qalcCaptureStop = dlsym(handle, "alcCaptureStop");
|
||||
qalcCaptureSamples = dlsym(handle, "alcCaptureSamples");
|
||||
|
||||
/* Connect function pointers to
|
||||
to OpenAL API functions */
|
||||
qalEnable = dlsym(handle, "alEnable");
|
||||
qalDisable = dlsym(handle, "alDisable");
|
||||
qalIsEnabled = dlsym(handle, "alIsEnabled");
|
||||
qalGetString = dlsym(handle, "alGetString");
|
||||
qalGetBooleanv = dlsym(handle, "alGetBooleanv");
|
||||
qalGetIntegerv = dlsym(handle, "alGetIntegerv");
|
||||
qalGetFloatv = dlsym(handle, "alGetFloatv");
|
||||
qalGetDoublev = dlsym(handle, "alGetDoublev");
|
||||
qalGetBoolean = dlsym(handle, "alGetBoolean");
|
||||
qalGetInteger = dlsym(handle, "alGetInteger");
|
||||
qalGetFloat = dlsym(handle, "alGetFloat");
|
||||
qalGetDouble = dlsym(handle, "alGetDouble");
|
||||
qalGetError = dlsym(handle, "alGetError");
|
||||
qalIsExtensionPresent = dlsym(handle, "alIsExtensionPresent");
|
||||
qalGetProcAddress = dlsym(handle, "alGetProcAddress");
|
||||
qalGetEnumValue = dlsym(handle, "alGetEnumValue");
|
||||
qalListenerf = dlsym(handle, "alListenerf");
|
||||
qalListener3f = dlsym(handle, "alListener3f");
|
||||
qalListenerfv = dlsym(handle, "alListenerfv");
|
||||
qalListeneri = dlsym(handle, "alListeneri");
|
||||
qalListener3i = dlsym(handle, "alListener3i");
|
||||
qalListeneriv = dlsym(handle, "alListeneriv");
|
||||
qalGetListenerf = dlsym(handle, "alGetListenerf");
|
||||
qalGetListener3f = dlsym(handle, "alGetListener3f");
|
||||
qalGetListenerfv = dlsym(handle, "alGetListenerfv");
|
||||
qalGetListeneri = dlsym(handle, "alGetListeneri");
|
||||
qalGetListener3i = dlsym(handle, "alGetListener3i");
|
||||
qalGetListeneriv = dlsym(handle, "alGetListeneriv");
|
||||
qalGenSources = dlsym(handle, "alGenSources");
|
||||
qalDeleteSources = dlsym(handle, "alDeleteSources");
|
||||
qalIsSource = dlsym(handle, "alIsSource");
|
||||
qalSourcef = dlsym(handle, "alSourcef");
|
||||
qalSource3f = dlsym(handle, "alSource3f");
|
||||
qalSourcefv = dlsym(handle, "alSourcefv");
|
||||
qalSourcei = dlsym(handle, "alSourcei");
|
||||
qalSource3i = dlsym(handle, "alSource3i");
|
||||
qalSourceiv = dlsym(handle, "alSourceiv");
|
||||
qalGetSourcef = dlsym(handle, "alGetSourcef");
|
||||
qalGetSource3f = dlsym(handle, "alGetSource3f");
|
||||
qalGetSourcefv = dlsym(handle, "alGetSourcefv");
|
||||
qalGetSourcei = dlsym(handle, "alGetSourcei");
|
||||
qalGetSource3i = dlsym(handle, "alGetSource3i");
|
||||
qalGetSourceiv = dlsym(handle, "alGetSourceiv");
|
||||
qalSourcePlayv = dlsym(handle, "alSourcePlayv");
|
||||
qalSourceStopv = dlsym(handle, "alSourceStopv");
|
||||
qalSourceRewindv = dlsym(handle, "alSourceRewindv");
|
||||
qalSourcePausev = dlsym(handle, "alSourcePausev");
|
||||
qalSourcePlay = dlsym(handle, "alSourcePlay");
|
||||
qalSourceStop = dlsym(handle, "alSourceStop");
|
||||
qalSourceRewind = dlsym(handle, "alSourceRewind");
|
||||
qalSourcePause = dlsym(handle, "alSourcePause");
|
||||
qalSourceQueueBuffers = dlsym(handle, "alSourceQueueBuffers");
|
||||
qalSourceUnqueueBuffers = dlsym(handle, "alSourceUnqueueBuffers");
|
||||
qalGenBuffers = dlsym(handle, "alGenBuffers");
|
||||
qalDeleteBuffers = dlsym(handle, "alDeleteBuffers");
|
||||
qalIsBuffer = dlsym(handle, "alIsBuffer");
|
||||
qalBufferData = dlsym(handle, "alBufferData");
|
||||
qalBufferf = dlsym(handle, "alBufferf");
|
||||
qalBuffer3f = dlsym(handle, "alBuffer3f");
|
||||
qalBufferfv = dlsym(handle, "alBufferfv");
|
||||
qalBufferi = dlsym(handle, "alBufferi");
|
||||
qalBuffer3i = dlsym(handle, "alBuffer3i");
|
||||
qalBufferiv = dlsym(handle, "alBufferiv");
|
||||
qalGetBufferf = dlsym(handle, "alGetBufferf");
|
||||
qalGetBuffer3f = dlsym(handle, "alGetBuffer3f");
|
||||
qalGetBufferfv = dlsym(handle, "alGetBufferfv");
|
||||
qalGetBufferi = dlsym(handle, "alGetBufferi");
|
||||
qalGetBuffer3i = dlsym(handle, "alGetBuffer3i");
|
||||
qalGetBufferiv = dlsym(handle, "alGetBufferiv");
|
||||
qalDopplerFactor = dlsym(handle, "alDopplerFactor");
|
||||
qalDopplerVelocity = dlsym(handle, "alDopplerVelocity");
|
||||
qalSpeedOfSound = dlsym(handle, "alSpeedOfSound");
|
||||
qalDistanceModel = dlsym(handle, "alDistanceModel");
|
||||
qalGenFilters = dlsym(handle, "alGenFilters");
|
||||
qalFilteri = dlsym(handle, "alFilteri");
|
||||
qalFilterf = dlsym(handle, "alFilterf");
|
||||
qalDeleteFilters = dlsym(handle, "alDeleteFilters");
|
||||
|
||||
/* Open the OpenAL device */
|
||||
Com_Printf("...opening OpenAL device:");
|
||||
|
||||
device = qalcOpenDevice(al_device->string[0] ? al_device->string : NULL);
|
||||
|
||||
if(!device)
|
||||
{
|
||||
Com_DPrintf("failed\n");
|
||||
QAL_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
Com_Printf("ok\n");
|
||||
|
||||
/* Create the OpenAL context */
|
||||
Com_Printf("...creating OpenAL context: ");
|
||||
|
||||
context = qalcCreateContext(device, NULL);
|
||||
|
||||
if(!context)
|
||||
{
|
||||
Com_DPrintf("failed\n");
|
||||
QAL_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
Com_Printf("ok\n");
|
||||
|
||||
/* Set the created context as current context */
|
||||
Com_Printf("...making context current: ");
|
||||
|
||||
if (!qalcMakeContextCurrent(context))
|
||||
{
|
||||
Com_DPrintf("failed\n");
|
||||
QAL_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
Com_Printf("ok\n");
|
||||
|
||||
/* Print OpenAL informations */
|
||||
Com_Printf("\n");
|
||||
QAL_SoundInfo();
|
||||
Com_Printf("\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* USE_OPENAL */
|
||||
|
Loading…
Reference in a new issue