2011-02-18 14:31:32 +00:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
Copyright (C) 1999-2005 Id Software, Inc.
|
|
|
|
|
|
|
|
This file is part of Quake III Arena source code.
|
|
|
|
|
|
|
|
Quake III Arena source code 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.
|
|
|
|
|
|
|
|
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* name: snd_dma.c
|
|
|
|
*
|
|
|
|
* desc: main control for any streaming sound output device
|
|
|
|
*
|
|
|
|
* $Archive: /MissionPack/code/client/snd_dma.c $
|
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "snd_local.h"
|
|
|
|
#include "snd_codec.h"
|
|
|
|
#include "client.h"
|
|
|
|
|
|
|
|
void S_Update_( void );
|
|
|
|
void S_Base_StopAllSounds(void);
|
|
|
|
void S_Base_StopBackgroundTrack( void );
|
|
|
|
|
|
|
|
snd_stream_t *s_backgroundStream = NULL;
|
|
|
|
static char s_backgroundLoop[MAX_QPATH];
|
|
|
|
//static char s_backgroundMusic[MAX_QPATH]; //TTimo: unused
|
|
|
|
|
|
|
|
|
|
|
|
// =======================================================================
|
|
|
|
// Internal sound data & structures
|
|
|
|
// =======================================================================
|
|
|
|
|
|
|
|
// only begin attenuating sound volumes when outside the FULLVOLUME range
|
|
|
|
#define SOUND_FULLVOLUME 80
|
|
|
|
|
|
|
|
#define SOUND_ATTENUATE 0.0008f
|
|
|
|
|
|
|
|
channel_t s_channels[MAX_CHANNELS];
|
|
|
|
channel_t loop_channels[MAX_CHANNELS];
|
|
|
|
int numLoopChannels;
|
|
|
|
|
|
|
|
static int s_soundStarted;
|
|
|
|
static qboolean s_soundMuted;
|
|
|
|
|
|
|
|
dma_t dma;
|
|
|
|
|
|
|
|
static int listener_number;
|
|
|
|
static vec3_t listener_origin;
|
|
|
|
static vec3_t listener_axis[3];
|
|
|
|
|
|
|
|
int s_soundtime; // sample PAIRS
|
|
|
|
int s_paintedtime; // sample PAIRS
|
|
|
|
|
|
|
|
// MAX_SFX may be larger than MAX_SOUNDS because
|
|
|
|
// of custom player sounds
|
|
|
|
#define MAX_SFX 4096
|
|
|
|
sfx_t s_knownSfx[MAX_SFX];
|
|
|
|
int s_numSfx = 0;
|
|
|
|
|
|
|
|
#define LOOP_HASH 128
|
|
|
|
static sfx_t *sfxHash[LOOP_HASH];
|
|
|
|
|
|
|
|
cvar_t *s_testsound;
|
|
|
|
cvar_t *s_show;
|
|
|
|
cvar_t *s_mixahead;
|
|
|
|
cvar_t *s_mixPreStep;
|
|
|
|
|
|
|
|
static loopSound_t loopSounds[MAX_GENTITIES];
|
|
|
|
static channel_t *freelist = NULL;
|
|
|
|
|
|
|
|
int s_rawend[MAX_RAW_STREAMS];
|
|
|
|
portable_samplepair_t s_rawsamples[MAX_RAW_STREAMS][MAX_RAW_SAMPLES];
|
|
|
|
|
|
|
|
|
|
|
|
// ====================================================================
|
|
|
|
// User-setable variables
|
|
|
|
// ====================================================================
|
|
|
|
|
|
|
|
|
|
|
|
void S_Base_SoundInfo(void) {
|
|
|
|
Com_Printf("----- Sound Info -----\n" );
|
|
|
|
if (!s_soundStarted) {
|
|
|
|
Com_Printf ("sound system not started\n");
|
|
|
|
} else {
|
|
|
|
Com_Printf("%5d stereo\n", dma.channels - 1);
|
|
|
|
Com_Printf("%5d samples\n", dma.samples);
|
2018-07-30 11:35:12 +00:00
|
|
|
Com_Printf("%5d samplebits (%s)\n", dma.samplebits, dma.isfloat ? "float" : "int");
|
2011-02-18 14:31:32 +00:00
|
|
|
Com_Printf("%5d submission_chunk\n", dma.submission_chunk);
|
|
|
|
Com_Printf("%5d speed\n", dma.speed);
|
|
|
|
Com_Printf("%p dma buffer\n", dma.buffer);
|
|
|
|
if ( s_backgroundStream ) {
|
|
|
|
Com_Printf("Background file: %s\n", s_backgroundLoop );
|
|
|
|
} else {
|
|
|
|
Com_Printf("No background file.\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
Com_Printf("----------------------\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_VOIP
|
|
|
|
static
|
|
|
|
void S_Base_StartCapture( void )
|
|
|
|
{
|
2018-07-30 11:35:12 +00:00
|
|
|
SNDDMA_StartCapture();
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
int S_Base_AvailableCaptureSamples( void )
|
|
|
|
{
|
2018-07-30 11:35:12 +00:00
|
|
|
return SNDDMA_AvailableCaptureSamples();
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
void S_Base_Capture( int samples, byte *data )
|
|
|
|
{
|
2018-07-30 11:35:12 +00:00
|
|
|
SNDDMA_Capture(samples, data);
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
void S_Base_StopCapture( void )
|
|
|
|
{
|
2018-07-30 11:35:12 +00:00
|
|
|
SNDDMA_StopCapture();
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
void S_Base_MasterGain( float val )
|
|
|
|
{
|
2018-07-30 11:35:12 +00:00
|
|
|
SNDDMA_MasterGain(val);
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
S_Base_SoundList
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
void S_Base_SoundList( void ) {
|
|
|
|
int i;
|
|
|
|
sfx_t *sfx;
|
|
|
|
int size, total;
|
|
|
|
char type[4][16];
|
|
|
|
char mem[2][16];
|
|
|
|
|
|
|
|
strcpy(type[0], "16bit");
|
|
|
|
strcpy(type[1], "adpcm");
|
|
|
|
strcpy(type[2], "daub4");
|
|
|
|
strcpy(type[3], "mulaw");
|
|
|
|
strcpy(mem[0], "paged out");
|
|
|
|
strcpy(mem[1], "resident ");
|
|
|
|
total = 0;
|
|
|
|
for (sfx=s_knownSfx, i=0 ; i<s_numSfx ; i++, sfx++) {
|
|
|
|
size = sfx->soundLength;
|
|
|
|
total += size;
|
|
|
|
Com_Printf("%6i[%s] : %s[%s]\n", size, type[sfx->soundCompressionMethod],
|
|
|
|
sfx->soundName, mem[sfx->inMemory] );
|
|
|
|
}
|
|
|
|
Com_Printf ("Total resident: %i\n", total);
|
|
|
|
S_DisplayFreeMemory();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void S_ChannelFree(channel_t *v) {
|
|
|
|
v->thesfx = NULL;
|
|
|
|
*(channel_t **)v = freelist;
|
|
|
|
freelist = (channel_t*)v;
|
|
|
|
}
|
|
|
|
|
|
|
|
channel_t* S_ChannelMalloc( void ) {
|
|
|
|
channel_t *v;
|
|
|
|
if (freelist == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
v = freelist;
|
|
|
|
freelist = *(channel_t **)freelist;
|
|
|
|
v->allocTime = Com_Milliseconds();
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
void S_ChannelSetup( void ) {
|
|
|
|
channel_t *p, *q;
|
|
|
|
|
|
|
|
// clear all the sounds so they don't
|
|
|
|
Com_Memset( s_channels, 0, sizeof( s_channels ) );
|
|
|
|
|
|
|
|
p = s_channels;;
|
|
|
|
q = p + MAX_CHANNELS;
|
|
|
|
while (--q > p) {
|
|
|
|
*(channel_t **)q = q-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*(channel_t **)q = NULL;
|
|
|
|
freelist = p + MAX_CHANNELS - 1;
|
|
|
|
Com_DPrintf("Channel memory manager started\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// =======================================================================
|
|
|
|
// Load a sound
|
|
|
|
// =======================================================================
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
return a hash value for the sfx name
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
static long S_HashSFXName(const char *name) {
|
|
|
|
int i;
|
|
|
|
long hash;
|
|
|
|
char letter;
|
|
|
|
|
|
|
|
hash = 0;
|
|
|
|
i = 0;
|
|
|
|
while (name[i] != '\0') {
|
|
|
|
letter = tolower(name[i]);
|
|
|
|
if (letter =='.') break; // don't include extension
|
|
|
|
if (letter =='\\') letter = '/'; // damn path names
|
|
|
|
hash+=(long)(letter)*(i+119);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
hash &= (LOOP_HASH-1);
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
S_FindName
|
|
|
|
|
|
|
|
Will allocate a new sfx if it isn't found
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
static sfx_t *S_FindName( const char *name ) {
|
|
|
|
int i;
|
|
|
|
int hash;
|
|
|
|
|
|
|
|
sfx_t *sfx;
|
|
|
|
|
|
|
|
if (!name) {
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
Com_Error(ERR_FATAL, "Sound name is NULL");
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
|
2011-02-18 14:31:32 +00:00
|
|
|
if (!name[0]) {
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
Com_Printf( S_COLOR_YELLOW "WARNING: Sound name is empty\n" );
|
|
|
|
return NULL;
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (strlen(name) >= MAX_QPATH) {
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
Com_Printf( S_COLOR_YELLOW "WARNING: Sound name is too long: %s\n", name );
|
|
|
|
return NULL;
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
|
2017-07-10 01:33:41 +00:00
|
|
|
if (name[0] == '*') {
|
|
|
|
Com_Printf( S_COLOR_YELLOW "WARNING: Tried to load player sound directly: %s\n", name );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-02-18 14:31:32 +00:00
|
|
|
hash = S_HashSFXName(name);
|
|
|
|
|
|
|
|
sfx = sfxHash[hash];
|
|
|
|
// see if already loaded
|
|
|
|
while (sfx) {
|
|
|
|
if (!Q_stricmp(sfx->soundName, name) ) {
|
|
|
|
return sfx;
|
|
|
|
}
|
|
|
|
sfx = sfx->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
// find a free sfx
|
|
|
|
for (i=0 ; i < s_numSfx ; i++) {
|
|
|
|
if (!s_knownSfx[i].soundName[0]) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == s_numSfx) {
|
|
|
|
if (s_numSfx == MAX_SFX) {
|
|
|
|
Com_Error (ERR_FATAL, "S_FindName: out of sfx_t");
|
|
|
|
}
|
|
|
|
s_numSfx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
sfx = &s_knownSfx[i];
|
|
|
|
Com_Memset (sfx, 0, sizeof(*sfx));
|
|
|
|
strcpy (sfx->soundName, name);
|
|
|
|
|
|
|
|
sfx->next = sfxHash[hash];
|
|
|
|
sfxHash[hash] = sfx;
|
|
|
|
|
|
|
|
return sfx;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
S_DefaultSound
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
void S_DefaultSound( sfx_t *sfx ) {
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
sfx->soundLength = 512;
|
|
|
|
sfx->soundData = SND_malloc();
|
|
|
|
sfx->soundData->next = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
for ( i = 0 ; i < sfx->soundLength ; i++ ) {
|
|
|
|
sfx->soundData->sndChunk[i] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===================
|
|
|
|
S_DisableSounds
|
|
|
|
|
|
|
|
Disables sounds until the next S_BeginRegistration.
|
|
|
|
This is called when the hunk is cleared and the sounds
|
|
|
|
are no longer valid.
|
|
|
|
===================
|
|
|
|
*/
|
|
|
|
void S_Base_DisableSounds( void ) {
|
|
|
|
S_Base_StopAllSounds();
|
|
|
|
s_soundMuted = qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
S_RegisterSound
|
|
|
|
|
|
|
|
Creates a default buzz sound if the file can't be loaded
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
sfxHandle_t S_Base_RegisterSound( const char *name, qboolean compressed ) {
|
|
|
|
sfx_t *sfx;
|
|
|
|
|
|
|
|
compressed = qfalse;
|
|
|
|
if (!s_soundStarted) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
sfx = S_FindName( name );
|
|
|
|
if ( !sfx ) {
|
2011-02-18 14:31:32 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( sfx->soundData ) {
|
|
|
|
if ( sfx->defaultSound ) {
|
|
|
|
Com_Printf( S_COLOR_YELLOW "WARNING: could not find %s - using default\n", sfx->soundName );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return sfx - s_knownSfx;
|
|
|
|
}
|
|
|
|
|
|
|
|
sfx->inMemory = qfalse;
|
|
|
|
sfx->soundCompressed = compressed;
|
|
|
|
|
|
|
|
S_memoryLoad(sfx);
|
|
|
|
|
|
|
|
if ( sfx->defaultSound ) {
|
|
|
|
Com_Printf( S_COLOR_YELLOW "WARNING: could not find %s - using default\n", sfx->soundName );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sfx - s_knownSfx;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=====================
|
|
|
|
S_BeginRegistration
|
|
|
|
|
|
|
|
=====================
|
|
|
|
*/
|
|
|
|
void S_Base_BeginRegistration( void ) {
|
|
|
|
s_soundMuted = qfalse; // we can play again
|
|
|
|
|
|
|
|
if (s_numSfx == 0) {
|
|
|
|
SND_setup();
|
|
|
|
|
2011-07-26 08:52:24 +00:00
|
|
|
Com_Memset(s_knownSfx, '\0', sizeof(s_knownSfx));
|
|
|
|
Com_Memset(sfxHash, '\0', sizeof(sfx_t *) * LOOP_HASH);
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
S_Base_RegisterSound("sound/misc/silence.wav", qfalse);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void S_memoryLoad(sfx_t *sfx) {
|
|
|
|
// load the sound file
|
|
|
|
if ( !S_LoadSound ( sfx ) ) {
|
|
|
|
// Com_Printf( S_COLOR_YELLOW "WARNING: couldn't load sound: %s\n", sfx->soundName );
|
|
|
|
sfx->defaultSound = qtrue;
|
|
|
|
}
|
|
|
|
sfx->inMemory = qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
S_SpatializeOrigin
|
|
|
|
|
|
|
|
Used for spatializing s_channels
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
void S_SpatializeOrigin (vec3_t origin, int master_vol, int *left_vol, int *right_vol)
|
|
|
|
{
|
|
|
|
vec_t dot;
|
|
|
|
vec_t dist;
|
|
|
|
vec_t lscale, rscale, scale;
|
|
|
|
vec3_t source_vec;
|
|
|
|
vec3_t vec;
|
|
|
|
|
|
|
|
const float dist_mult = SOUND_ATTENUATE;
|
|
|
|
|
2017-12-03 10:09:52 +00:00
|
|
|
// calculate stereo separation and distance attenuation
|
2011-02-18 14:31:32 +00:00
|
|
|
VectorSubtract(origin, listener_origin, source_vec);
|
|
|
|
|
|
|
|
dist = VectorNormalize(source_vec);
|
|
|
|
dist -= SOUND_FULLVOLUME;
|
|
|
|
if (dist < 0)
|
|
|
|
dist = 0; // close enough to be at full volume
|
|
|
|
dist *= dist_mult; // different attenuation levels
|
|
|
|
|
|
|
|
VectorRotate( source_vec, listener_axis, vec );
|
|
|
|
|
|
|
|
dot = -vec[1];
|
|
|
|
|
|
|
|
if (dma.channels == 1)
|
|
|
|
{ // no attenuation = no spatialization
|
|
|
|
rscale = 1.0;
|
|
|
|
lscale = 1.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rscale = 0.5 * (1.0 + dot);
|
|
|
|
lscale = 0.5 * (1.0 - dot);
|
|
|
|
if ( rscale < 0 ) {
|
|
|
|
rscale = 0;
|
|
|
|
}
|
|
|
|
if ( lscale < 0 ) {
|
|
|
|
lscale = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add in distance effect
|
|
|
|
scale = (1.0 - dist) * rscale;
|
|
|
|
*right_vol = (master_vol * scale);
|
|
|
|
if (*right_vol < 0)
|
|
|
|
*right_vol = 0;
|
|
|
|
|
|
|
|
scale = (1.0 - dist) * lscale;
|
|
|
|
*left_vol = (master_vol * scale);
|
|
|
|
if (*left_vol < 0)
|
|
|
|
*left_vol = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// =======================================================================
|
|
|
|
// Start a sound effect
|
|
|
|
// =======================================================================
|
|
|
|
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
/*
|
|
|
|
=================
|
|
|
|
S_Base_HearingThroughEntity
|
|
|
|
|
|
|
|
Also see S_AL_HearingThroughEntity
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
static qboolean S_Base_HearingThroughEntity( int entityNum, vec3_t origin )
|
|
|
|
{
|
|
|
|
float distanceSq;
|
|
|
|
vec3_t sorigin;
|
|
|
|
|
|
|
|
if (origin)
|
|
|
|
VectorCopy(origin, sorigin);
|
|
|
|
else
|
|
|
|
VectorCopy(loopSounds[entityNum].origin, sorigin);
|
|
|
|
|
|
|
|
if( listener_number == entityNum )
|
|
|
|
{
|
2017-07-10 01:33:41 +00:00
|
|
|
// This is an outrageous hack to detect
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
// whether or not the player is rendering in third person or not. We can't
|
|
|
|
// ask the renderer because the renderer has no notion of entities and we
|
|
|
|
// can't ask cgame since that would involve changing the API and hence mod
|
|
|
|
// compatibility. I don't think there is any way around this, but I'll leave
|
|
|
|
// the FIXME just in case anyone has a bright idea.
|
|
|
|
distanceSq = DistanceSquared(
|
|
|
|
sorigin,
|
|
|
|
listener_origin );
|
|
|
|
|
|
|
|
if( distanceSq > THIRD_PERSON_THRESHOLD_SQ )
|
|
|
|
return qfalse; //we're the player, but third person
|
|
|
|
else
|
|
|
|
return qtrue; //we're the player
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return qfalse; //not the player
|
|
|
|
}
|
|
|
|
|
2011-02-18 14:31:32 +00:00
|
|
|
/*
|
|
|
|
====================
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
S_Base_StartSoundEx
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
Validates the parms and ques the sound up
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
if origin is NULL, the sound will be dynamically sourced from the entity
|
2011-02-18 14:31:32 +00:00
|
|
|
Entchannel 0 will never override a playing sound
|
|
|
|
====================
|
|
|
|
*/
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
static void S_Base_StartSoundEx( vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfxHandle, qboolean localSound ) {
|
2011-02-18 14:31:32 +00:00
|
|
|
channel_t *ch;
|
|
|
|
sfx_t *sfx;
|
|
|
|
int i, oldest, chosen, time;
|
|
|
|
int inplay, allowed;
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
qboolean fullVolume;
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
if ( !s_soundStarted || s_soundMuted ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
if ( !origin && ( entityNum < 0 || entityNum >= MAX_GENTITIES ) ) {
|
2011-02-18 14:31:32 +00:00
|
|
|
Com_Error( ERR_DROP, "S_StartSound: bad entitynum %i", entityNum );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( sfxHandle < 0 || sfxHandle >= s_numSfx ) {
|
|
|
|
Com_Printf( S_COLOR_YELLOW "S_StartSound: handle %i out of range\n", sfxHandle );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sfx = &s_knownSfx[ sfxHandle ];
|
|
|
|
|
|
|
|
if (sfx->inMemory == qfalse) {
|
|
|
|
S_memoryLoad(sfx);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( s_show->integer == 1 ) {
|
|
|
|
Com_Printf( "%i : %s\n", s_paintedtime, sfx->soundName );
|
|
|
|
}
|
|
|
|
|
|
|
|
time = Com_Milliseconds();
|
|
|
|
|
|
|
|
// Com_Printf("playing %s\n", sfx->soundName);
|
|
|
|
// pick a channel to play on
|
|
|
|
|
|
|
|
allowed = 4;
|
|
|
|
if (entityNum == listener_number) {
|
|
|
|
allowed = 8;
|
|
|
|
}
|
|
|
|
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
fullVolume = qfalse;
|
|
|
|
if (localSound || S_Base_HearingThroughEntity(entityNum, origin)) {
|
|
|
|
fullVolume = qtrue;
|
|
|
|
}
|
|
|
|
|
2011-02-18 14:31:32 +00:00
|
|
|
ch = s_channels;
|
|
|
|
inplay = 0;
|
|
|
|
for ( i = 0; i < MAX_CHANNELS ; i++, ch++ ) {
|
|
|
|
if (ch->entnum == entityNum && ch->thesfx == sfx) {
|
|
|
|
if (time - ch->allocTime < 50) {
|
|
|
|
// if (Cvar_VariableValue( "cg_showmiss" )) {
|
|
|
|
// Com_Printf("double sound start\n");
|
|
|
|
// }
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
inplay++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inplay>allowed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sfx->lastTimeUsed = time;
|
|
|
|
|
|
|
|
ch = S_ChannelMalloc(); // entityNum, entchannel);
|
|
|
|
if (!ch) {
|
|
|
|
ch = s_channels;
|
|
|
|
|
|
|
|
oldest = sfx->lastTimeUsed;
|
|
|
|
chosen = -1;
|
|
|
|
for ( i = 0 ; i < MAX_CHANNELS ; i++, ch++ ) {
|
|
|
|
if (ch->entnum != listener_number && ch->entnum == entityNum && ch->allocTime<oldest && ch->entchannel != CHAN_ANNOUNCER) {
|
|
|
|
oldest = ch->allocTime;
|
|
|
|
chosen = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (chosen == -1) {
|
|
|
|
ch = s_channels;
|
|
|
|
for ( i = 0 ; i < MAX_CHANNELS ; i++, ch++ ) {
|
|
|
|
if (ch->entnum != listener_number && ch->allocTime<oldest && ch->entchannel != CHAN_ANNOUNCER) {
|
|
|
|
oldest = ch->allocTime;
|
|
|
|
chosen = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (chosen == -1) {
|
|
|
|
ch = s_channels;
|
|
|
|
if (ch->entnum == listener_number) {
|
|
|
|
for ( i = 0 ; i < MAX_CHANNELS ; i++, ch++ ) {
|
|
|
|
if (ch->allocTime<oldest) {
|
|
|
|
oldest = ch->allocTime;
|
|
|
|
chosen = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (chosen == -1) {
|
|
|
|
Com_Printf("dropping sound\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ch = &s_channels[chosen];
|
|
|
|
ch->allocTime = sfx->lastTimeUsed;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (origin) {
|
|
|
|
VectorCopy (origin, ch->origin);
|
|
|
|
ch->fixed_origin = qtrue;
|
|
|
|
} else {
|
|
|
|
ch->fixed_origin = qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
ch->master_vol = 127;
|
|
|
|
ch->entnum = entityNum;
|
|
|
|
ch->thesfx = sfx;
|
|
|
|
ch->startSample = START_SAMPLE_IMMEDIATE;
|
|
|
|
ch->entchannel = entchannel;
|
|
|
|
ch->leftvol = ch->master_vol; // these will get calced at next spatialize
|
|
|
|
ch->rightvol = ch->master_vol; // unless the game isn't running
|
|
|
|
ch->doppler = qfalse;
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
ch->fullVolume = fullVolume;
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
/*
|
|
|
|
====================
|
|
|
|
S_StartSound
|
|
|
|
|
|
|
|
if origin is NULL, the sound will be dynamically sourced from the entity
|
|
|
|
====================
|
|
|
|
*/
|
|
|
|
void S_Base_StartSound( vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfxHandle ) {
|
|
|
|
S_Base_StartSoundEx( origin, entityNum, entchannel, sfxHandle, qfalse );
|
|
|
|
}
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
S_StartLocalSound
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
void S_Base_StartLocalSound( sfxHandle_t sfxHandle, int channelNum ) {
|
|
|
|
if ( !s_soundStarted || s_soundMuted ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( sfxHandle < 0 || sfxHandle >= s_numSfx ) {
|
|
|
|
Com_Printf( S_COLOR_YELLOW "S_StartLocalSound: handle %i out of range\n", sfxHandle );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
S_Base_StartSoundEx( NULL, listener_number, channelNum, sfxHandle, qtrue );
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
S_ClearSoundBuffer
|
|
|
|
|
|
|
|
If we are about to perform file access, clear the buffer
|
|
|
|
so sound doesn't stutter.
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
void S_Base_ClearSoundBuffer( void ) {
|
|
|
|
int clear;
|
|
|
|
|
|
|
|
if (!s_soundStarted)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// stop looping sounds
|
|
|
|
Com_Memset(loopSounds, 0, MAX_GENTITIES*sizeof(loopSound_t));
|
|
|
|
Com_Memset(loop_channels, 0, MAX_CHANNELS*sizeof(channel_t));
|
|
|
|
numLoopChannels = 0;
|
|
|
|
|
|
|
|
S_ChannelSetup();
|
|
|
|
|
|
|
|
Com_Memset(s_rawend, '\0', sizeof (s_rawend));
|
|
|
|
|
|
|
|
if (dma.samplebits == 8)
|
|
|
|
clear = 0x80;
|
|
|
|
else
|
|
|
|
clear = 0;
|
|
|
|
|
|
|
|
SNDDMA_BeginPainting ();
|
|
|
|
if (dma.buffer)
|
|
|
|
Com_Memset(dma.buffer, clear, dma.samples * dma.samplebits/8);
|
|
|
|
SNDDMA_Submit ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
S_StopAllSounds
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
void S_Base_StopAllSounds(void) {
|
|
|
|
if ( !s_soundStarted ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// stop the background music
|
|
|
|
S_Base_StopBackgroundTrack();
|
|
|
|
|
|
|
|
S_Base_ClearSoundBuffer ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============================================================
|
|
|
|
|
|
|
|
continuous looping sounds are added each frame
|
|
|
|
|
|
|
|
==============================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
void S_Base_StopLoopingSound(int entityNum) {
|
|
|
|
loopSounds[entityNum].active = qfalse;
|
|
|
|
// loopSounds[entityNum].sfx = 0;
|
|
|
|
loopSounds[entityNum].kill = qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
S_ClearLoopingSounds
|
|
|
|
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
void S_Base_ClearLoopingSounds( qboolean killall ) {
|
|
|
|
int i;
|
|
|
|
for ( i = 0 ; i < MAX_GENTITIES ; i++) {
|
|
|
|
if (killall || loopSounds[i].kill == qtrue || (loopSounds[i].sfx && loopSounds[i].sfx->soundLength == 0)) {
|
|
|
|
S_Base_StopLoopingSound(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
numLoopChannels = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
S_AddLoopingSound
|
|
|
|
|
|
|
|
Called during entity generation for a frame
|
|
|
|
Include velocity in case I get around to doing doppler...
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
void S_Base_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfxHandle ) {
|
|
|
|
sfx_t *sfx;
|
|
|
|
|
|
|
|
if ( !s_soundStarted || s_soundMuted ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( sfxHandle < 0 || sfxHandle >= s_numSfx ) {
|
|
|
|
Com_Printf( S_COLOR_YELLOW "S_AddLoopingSound: handle %i out of range\n", sfxHandle );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sfx = &s_knownSfx[ sfxHandle ];
|
|
|
|
|
|
|
|
if (sfx->inMemory == qfalse) {
|
|
|
|
S_memoryLoad(sfx);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !sfx->soundLength ) {
|
|
|
|
Com_Error( ERR_DROP, "%s has length 0", sfx->soundName );
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorCopy( origin, loopSounds[entityNum].origin );
|
|
|
|
VectorCopy( velocity, loopSounds[entityNum].velocity );
|
|
|
|
loopSounds[entityNum].active = qtrue;
|
|
|
|
loopSounds[entityNum].kill = qtrue;
|
|
|
|
loopSounds[entityNum].doppler = qfalse;
|
|
|
|
loopSounds[entityNum].oldDopplerScale = 1.0;
|
|
|
|
loopSounds[entityNum].dopplerScale = 1.0;
|
|
|
|
loopSounds[entityNum].sfx = sfx;
|
|
|
|
|
|
|
|
if (s_doppler->integer && VectorLengthSquared(velocity)>0.0) {
|
|
|
|
vec3_t out;
|
|
|
|
float lena, lenb;
|
|
|
|
|
|
|
|
loopSounds[entityNum].doppler = qtrue;
|
|
|
|
lena = DistanceSquared(loopSounds[listener_number].origin, loopSounds[entityNum].origin);
|
|
|
|
VectorAdd(loopSounds[entityNum].origin, loopSounds[entityNum].velocity, out);
|
|
|
|
lenb = DistanceSquared(loopSounds[listener_number].origin, out);
|
|
|
|
if ((loopSounds[entityNum].framenum+1) != cls.framecount) {
|
|
|
|
loopSounds[entityNum].oldDopplerScale = 1.0;
|
|
|
|
} else {
|
|
|
|
loopSounds[entityNum].oldDopplerScale = loopSounds[entityNum].dopplerScale;
|
|
|
|
}
|
|
|
|
loopSounds[entityNum].dopplerScale = lenb/(lena*100);
|
|
|
|
if (loopSounds[entityNum].dopplerScale<=1.0) {
|
|
|
|
loopSounds[entityNum].doppler = qfalse; // don't bother doing the math
|
|
|
|
} else if (loopSounds[entityNum].dopplerScale>MAX_DOPPLER_SCALE) {
|
|
|
|
loopSounds[entityNum].dopplerScale = MAX_DOPPLER_SCALE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
loopSounds[entityNum].framenum = cls.framecount;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
S_AddLoopingSound
|
|
|
|
|
|
|
|
Called during entity generation for a frame
|
|
|
|
Include velocity in case I get around to doing doppler...
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
void S_Base_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfxHandle ) {
|
|
|
|
sfx_t *sfx;
|
|
|
|
|
|
|
|
if ( !s_soundStarted || s_soundMuted ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( sfxHandle < 0 || sfxHandle >= s_numSfx ) {
|
|
|
|
Com_Printf( S_COLOR_YELLOW "S_AddRealLoopingSound: handle %i out of range\n", sfxHandle );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sfx = &s_knownSfx[ sfxHandle ];
|
|
|
|
|
|
|
|
if (sfx->inMemory == qfalse) {
|
|
|
|
S_memoryLoad(sfx);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !sfx->soundLength ) {
|
|
|
|
Com_Error( ERR_DROP, "%s has length 0", sfx->soundName );
|
|
|
|
}
|
|
|
|
VectorCopy( origin, loopSounds[entityNum].origin );
|
|
|
|
VectorCopy( velocity, loopSounds[entityNum].velocity );
|
|
|
|
loopSounds[entityNum].sfx = sfx;
|
|
|
|
loopSounds[entityNum].active = qtrue;
|
|
|
|
loopSounds[entityNum].kill = qfalse;
|
|
|
|
loopSounds[entityNum].doppler = qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
S_AddLoopSounds
|
|
|
|
|
|
|
|
Spatialize all of the looping sounds.
|
|
|
|
All sounds are on the same cycle, so any duplicates can just
|
|
|
|
sum up the channel multipliers.
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
void S_AddLoopSounds (void) {
|
|
|
|
int i, j, time;
|
|
|
|
int left_total, right_total, left, right;
|
|
|
|
channel_t *ch;
|
|
|
|
loopSound_t *loop, *loop2;
|
|
|
|
static int loopFrame;
|
|
|
|
|
|
|
|
|
|
|
|
numLoopChannels = 0;
|
|
|
|
|
|
|
|
time = Com_Milliseconds();
|
|
|
|
|
|
|
|
loopFrame++;
|
|
|
|
for ( i = 0 ; i < MAX_GENTITIES ; i++) {
|
|
|
|
loop = &loopSounds[i];
|
|
|
|
if ( !loop->active || loop->mergeFrame == loopFrame ) {
|
|
|
|
continue; // already merged into an earlier sound
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop->kill) {
|
|
|
|
S_SpatializeOrigin( loop->origin, 127, &left_total, &right_total); // 3d
|
|
|
|
} else {
|
|
|
|
S_SpatializeOrigin( loop->origin, 90, &left_total, &right_total); // sphere
|
|
|
|
}
|
|
|
|
|
|
|
|
loop->sfx->lastTimeUsed = time;
|
|
|
|
|
|
|
|
for (j=(i+1); j< MAX_GENTITIES ; j++) {
|
|
|
|
loop2 = &loopSounds[j];
|
|
|
|
if ( !loop2->active || loop2->doppler || loop2->sfx != loop->sfx) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
loop2->mergeFrame = loopFrame;
|
|
|
|
|
|
|
|
if (loop2->kill) {
|
|
|
|
S_SpatializeOrigin( loop2->origin, 127, &left, &right); // 3d
|
|
|
|
} else {
|
|
|
|
S_SpatializeOrigin( loop2->origin, 90, &left, &right); // sphere
|
|
|
|
}
|
|
|
|
|
|
|
|
loop2->sfx->lastTimeUsed = time;
|
|
|
|
left_total += left;
|
|
|
|
right_total += right;
|
|
|
|
}
|
|
|
|
if (left_total == 0 && right_total == 0) {
|
|
|
|
continue; // not audible
|
|
|
|
}
|
|
|
|
|
|
|
|
// allocate a channel
|
|
|
|
ch = &loop_channels[numLoopChannels];
|
|
|
|
|
|
|
|
if (left_total > 255) {
|
|
|
|
left_total = 255;
|
|
|
|
}
|
|
|
|
if (right_total > 255) {
|
|
|
|
right_total = 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
ch->master_vol = 127;
|
|
|
|
ch->leftvol = left_total;
|
|
|
|
ch->rightvol = right_total;
|
|
|
|
ch->thesfx = loop->sfx;
|
|
|
|
ch->doppler = loop->doppler;
|
|
|
|
ch->dopplerScale = loop->dopplerScale;
|
|
|
|
ch->oldDopplerScale = loop->oldDopplerScale;
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
ch->fullVolume = qfalse;
|
2011-02-18 14:31:32 +00:00
|
|
|
numLoopChannels++;
|
|
|
|
if (numLoopChannels == MAX_CHANNELS) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
S_ByteSwapRawSamples
|
|
|
|
|
|
|
|
If raw data has been loaded in little endien binary form, this must be done.
|
|
|
|
If raw data was calculated, as with ADPCM, this should not be called.
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
void S_ByteSwapRawSamples( int samples, int width, int s_channels, const byte *data ) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if ( width != 2 ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ( LittleShort( 256 ) == 256 ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( s_channels == 2 ) {
|
|
|
|
samples <<= 1;
|
|
|
|
}
|
|
|
|
for ( i = 0 ; i < samples ; i++ ) {
|
|
|
|
((short *)data)[i] = LittleShort( ((short *)data)[i] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
============
|
|
|
|
S_Base_RawSamples
|
|
|
|
|
|
|
|
Music streaming
|
|
|
|
============
|
|
|
|
*/
|
2011-07-29 17:52:36 +00:00
|
|
|
void S_Base_RawSamples( int stream, int samples, int rate, int width, int s_channels, const byte *data, float volume, int entityNum)
|
|
|
|
{
|
2011-02-18 14:31:32 +00:00
|
|
|
int i;
|
|
|
|
int src, dst;
|
|
|
|
float scale;
|
2017-07-10 01:33:41 +00:00
|
|
|
int intVolumeLeft, intVolumeRight;
|
2011-02-18 14:31:32 +00:00
|
|
|
portable_samplepair_t *rawsamples;
|
|
|
|
|
|
|
|
if ( !s_soundStarted || s_soundMuted ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( (stream < 0) || (stream >= MAX_RAW_STREAMS) ) {
|
|
|
|
return;
|
|
|
|
}
|
2017-07-10 01:33:41 +00:00
|
|
|
|
2011-02-18 14:31:32 +00:00
|
|
|
rawsamples = s_rawsamples[stream];
|
|
|
|
|
2017-07-10 01:33:41 +00:00
|
|
|
if ( s_muted->integer ) {
|
|
|
|
intVolumeLeft = intVolumeRight = 0;
|
|
|
|
} else {
|
|
|
|
int leftvol, rightvol;
|
|
|
|
|
|
|
|
if ( entityNum >= 0 && entityNum < MAX_GENTITIES ) {
|
|
|
|
// support spatialized raw streams, e.g. for VoIP
|
|
|
|
S_SpatializeOrigin( loopSounds[ entityNum ].origin, 256, &leftvol, &rightvol );
|
|
|
|
} else {
|
|
|
|
leftvol = rightvol = 256;
|
|
|
|
}
|
|
|
|
|
|
|
|
intVolumeLeft = leftvol * volume * s_volume->value;
|
|
|
|
intVolumeRight = rightvol * volume * s_volume->value;
|
|
|
|
}
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
if ( s_rawend[stream] < s_soundtime ) {
|
|
|
|
Com_DPrintf( "S_Base_RawSamples: resetting minimum: %i < %i\n", s_rawend[stream], s_soundtime );
|
|
|
|
s_rawend[stream] = s_soundtime;
|
|
|
|
}
|
|
|
|
|
|
|
|
scale = (float)rate / dma.speed;
|
|
|
|
|
|
|
|
//Com_Printf ("%i < %i < %i\n", s_soundtime, s_paintedtime, s_rawend[stream]);
|
|
|
|
if (s_channels == 2 && width == 2)
|
|
|
|
{
|
|
|
|
if (scale == 1.0)
|
|
|
|
{ // optimized case
|
|
|
|
for (i=0 ; i<samples ; i++)
|
|
|
|
{
|
|
|
|
dst = s_rawend[stream]&(MAX_RAW_SAMPLES-1);
|
|
|
|
s_rawend[stream]++;
|
2017-07-10 01:33:41 +00:00
|
|
|
rawsamples[dst].left = ((short *)data)[i*2] * intVolumeLeft;
|
|
|
|
rawsamples[dst].right = ((short *)data)[i*2+1] * intVolumeRight;
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i=0 ; ; i++)
|
|
|
|
{
|
|
|
|
src = i*scale;
|
|
|
|
if (src >= samples)
|
|
|
|
break;
|
|
|
|
dst = s_rawend[stream]&(MAX_RAW_SAMPLES-1);
|
|
|
|
s_rawend[stream]++;
|
2017-07-10 01:33:41 +00:00
|
|
|
rawsamples[dst].left = ((short *)data)[src*2] * intVolumeLeft;
|
|
|
|
rawsamples[dst].right = ((short *)data)[src*2+1] * intVolumeRight;
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (s_channels == 1 && width == 2)
|
|
|
|
{
|
|
|
|
for (i=0 ; ; i++)
|
|
|
|
{
|
|
|
|
src = i*scale;
|
|
|
|
if (src >= samples)
|
|
|
|
break;
|
|
|
|
dst = s_rawend[stream]&(MAX_RAW_SAMPLES-1);
|
|
|
|
s_rawend[stream]++;
|
2017-07-10 01:33:41 +00:00
|
|
|
rawsamples[dst].left = ((short *)data)[src] * intVolumeLeft;
|
|
|
|
rawsamples[dst].right = ((short *)data)[src] * intVolumeRight;
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (s_channels == 2 && width == 1)
|
|
|
|
{
|
2017-07-10 01:33:41 +00:00
|
|
|
intVolumeLeft *= 256;
|
|
|
|
intVolumeRight *= 256;
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
for (i=0 ; ; i++)
|
|
|
|
{
|
|
|
|
src = i*scale;
|
|
|
|
if (src >= samples)
|
|
|
|
break;
|
|
|
|
dst = s_rawend[stream]&(MAX_RAW_SAMPLES-1);
|
|
|
|
s_rawend[stream]++;
|
2017-07-10 01:33:41 +00:00
|
|
|
rawsamples[dst].left = ((char *)data)[src*2] * intVolumeLeft;
|
|
|
|
rawsamples[dst].right = ((char *)data)[src*2+1] * intVolumeRight;
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (s_channels == 1 && width == 1)
|
|
|
|
{
|
2017-07-10 01:33:41 +00:00
|
|
|
intVolumeLeft *= 256;
|
|
|
|
intVolumeRight *= 256;
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
for (i=0 ; ; i++)
|
|
|
|
{
|
|
|
|
src = i*scale;
|
|
|
|
if (src >= samples)
|
|
|
|
break;
|
|
|
|
dst = s_rawend[stream]&(MAX_RAW_SAMPLES-1);
|
|
|
|
s_rawend[stream]++;
|
2017-07-10 01:33:41 +00:00
|
|
|
rawsamples[dst].left = (((byte *)data)[src]-128) * intVolumeLeft;
|
|
|
|
rawsamples[dst].right = (((byte *)data)[src]-128) * intVolumeRight;
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( s_rawend[stream] > s_soundtime + MAX_RAW_SAMPLES ) {
|
|
|
|
Com_DPrintf( "S_Base_RawSamples: overflowed %i > %i\n", s_rawend[stream], s_soundtime );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
/*
|
|
|
|
=====================
|
|
|
|
S_UpdateEntityPosition
|
|
|
|
|
|
|
|
let the sound system know where an entity currently is
|
|
|
|
======================
|
|
|
|
*/
|
|
|
|
void S_Base_UpdateEntityPosition( int entityNum, const vec3_t origin ) {
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
if ( entityNum < 0 || entityNum >= MAX_GENTITIES ) {
|
2011-02-18 14:31:32 +00:00
|
|
|
Com_Error( ERR_DROP, "S_UpdateEntityPosition: bad entitynum %i", entityNum );
|
|
|
|
}
|
|
|
|
VectorCopy( origin, loopSounds[entityNum].origin );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
============
|
|
|
|
S_Respatialize
|
|
|
|
|
|
|
|
Change the volumes of all the playing sounds for changes in their positions
|
|
|
|
============
|
|
|
|
*/
|
|
|
|
void S_Base_Respatialize( int entityNum, const vec3_t head, vec3_t axis[3], int inwater ) {
|
|
|
|
int i;
|
|
|
|
channel_t *ch;
|
|
|
|
vec3_t origin;
|
|
|
|
|
|
|
|
if ( !s_soundStarted || s_soundMuted ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
listener_number = entityNum;
|
|
|
|
VectorCopy(head, listener_origin);
|
|
|
|
VectorCopy(axis[0], listener_axis[0]);
|
|
|
|
VectorCopy(axis[1], listener_axis[1]);
|
|
|
|
VectorCopy(axis[2], listener_axis[2]);
|
|
|
|
|
|
|
|
// update spatialization for dynamic sounds
|
|
|
|
ch = s_channels;
|
|
|
|
for ( i = 0 ; i < MAX_CHANNELS ; i++, ch++ ) {
|
|
|
|
if ( !ch->thesfx ) {
|
|
|
|
continue;
|
|
|
|
}
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
// local and first person sounds will always be full volume
|
|
|
|
if (ch->fullVolume) {
|
2011-02-18 14:31:32 +00:00
|
|
|
ch->leftvol = ch->master_vol;
|
|
|
|
ch->rightvol = ch->master_vol;
|
|
|
|
} else {
|
|
|
|
if (ch->fixed_origin) {
|
|
|
|
VectorCopy( ch->origin, origin );
|
|
|
|
} else {
|
|
|
|
VectorCopy( loopSounds[ ch->entnum ].origin, origin );
|
|
|
|
}
|
|
|
|
|
|
|
|
S_SpatializeOrigin (origin, ch->master_vol, &ch->leftvol, &ch->rightvol);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add loopsounds
|
|
|
|
S_AddLoopSounds ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
========================
|
|
|
|
S_ScanChannelStarts
|
|
|
|
|
|
|
|
Returns qtrue if any new sounds were started since the last mix
|
|
|
|
========================
|
|
|
|
*/
|
|
|
|
qboolean S_ScanChannelStarts( void ) {
|
|
|
|
channel_t *ch;
|
|
|
|
int i;
|
|
|
|
qboolean newSamples;
|
|
|
|
|
|
|
|
newSamples = qfalse;
|
|
|
|
ch = s_channels;
|
|
|
|
|
|
|
|
for (i=0; i<MAX_CHANNELS ; i++, ch++) {
|
|
|
|
if ( !ch->thesfx ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// if this channel was just started this frame,
|
|
|
|
// set the sample count to it begins mixing
|
|
|
|
// into the very first sample
|
|
|
|
if ( ch->startSample == START_SAMPLE_IMMEDIATE ) {
|
|
|
|
ch->startSample = s_paintedtime;
|
|
|
|
newSamples = qtrue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if it is completely finished by now, clear it
|
|
|
|
if ( ch->startSample + (ch->thesfx->soundLength) <= s_paintedtime ) {
|
|
|
|
S_ChannelFree(ch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newSamples;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
============
|
|
|
|
S_Update
|
|
|
|
|
|
|
|
Called once each time through the main loop
|
|
|
|
============
|
|
|
|
*/
|
|
|
|
void S_Base_Update( void ) {
|
|
|
|
int i;
|
|
|
|
int total;
|
|
|
|
channel_t *ch;
|
|
|
|
|
|
|
|
if ( !s_soundStarted || s_soundMuted ) {
|
|
|
|
// Com_DPrintf ("not started or muted\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// debugging output
|
|
|
|
//
|
|
|
|
if ( s_show->integer == 2 ) {
|
|
|
|
total = 0;
|
|
|
|
ch = s_channels;
|
|
|
|
for (i=0 ; i<MAX_CHANNELS; i++, ch++) {
|
|
|
|
if (ch->thesfx && (ch->leftvol || ch->rightvol) ) {
|
|
|
|
Com_Printf ("%d %d %s\n", ch->leftvol, ch->rightvol, ch->thesfx->soundName);
|
|
|
|
total++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Com_Printf ("----(%i)---- painted: %i\n", total, s_paintedtime);
|
|
|
|
}
|
|
|
|
|
|
|
|
// add raw data from streamed samples
|
|
|
|
S_UpdateBackgroundTrack();
|
|
|
|
|
|
|
|
// mix some sound
|
|
|
|
S_Update_();
|
|
|
|
}
|
|
|
|
|
|
|
|
void S_GetSoundtime(void)
|
|
|
|
{
|
|
|
|
int samplepos;
|
|
|
|
static int buffers;
|
|
|
|
static int oldsamplepos;
|
|
|
|
int fullsamples;
|
|
|
|
|
|
|
|
fullsamples = dma.samples / dma.channels;
|
|
|
|
|
|
|
|
if( CL_VideoRecording( ) )
|
|
|
|
{
|
2017-07-10 01:33:41 +00:00
|
|
|
float fps = MIN(cl_aviFrameRate->value, 1000.0f);
|
|
|
|
float frameDuration = MAX(dma.speed / fps, 1.0f) + clc.aviSoundFrameRemainder;
|
|
|
|
|
|
|
|
int msec = (int)frameDuration;
|
|
|
|
s_soundtime += msec;
|
|
|
|
clc.aviSoundFrameRemainder = frameDuration - msec;
|
|
|
|
|
2011-02-18 14:31:32 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// it is possible to miscount buffers if it has wrapped twice between
|
|
|
|
// calls to S_Update. Oh well.
|
|
|
|
samplepos = SNDDMA_GetDMAPos();
|
|
|
|
if (samplepos < oldsamplepos)
|
|
|
|
{
|
|
|
|
buffers++; // buffer wrapped
|
|
|
|
|
|
|
|
if (s_paintedtime > 0x40000000)
|
|
|
|
{ // time to chop things off to avoid 32 bit limits
|
|
|
|
buffers = 0;
|
|
|
|
s_paintedtime = fullsamples;
|
|
|
|
S_Base_StopAllSounds ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
oldsamplepos = samplepos;
|
|
|
|
|
|
|
|
s_soundtime = buffers*fullsamples + samplepos/dma.channels;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
// check to make sure that we haven't overshot
|
|
|
|
if (s_paintedtime < s_soundtime)
|
|
|
|
{
|
|
|
|
Com_DPrintf ("S_Update_ : overflow\n");
|
|
|
|
s_paintedtime = s_soundtime;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( dma.submission_chunk < 256 ) {
|
|
|
|
s_paintedtime = s_soundtime + s_mixPreStep->value * dma.speed;
|
|
|
|
} else {
|
|
|
|
s_paintedtime = s_soundtime + dma.submission_chunk;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void S_Update_(void) {
|
|
|
|
unsigned endtime;
|
|
|
|
int samps;
|
|
|
|
static float lastTime = 0.0f;
|
|
|
|
float ma, op;
|
|
|
|
float thisTime, sane;
|
|
|
|
static int ot = -1;
|
|
|
|
|
|
|
|
if ( !s_soundStarted || s_soundMuted ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
thisTime = Com_Milliseconds();
|
|
|
|
|
|
|
|
// Updates s_soundtime
|
|
|
|
S_GetSoundtime();
|
|
|
|
|
|
|
|
if (s_soundtime == ot) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ot = s_soundtime;
|
|
|
|
|
|
|
|
// clear any sound effects that end before the current time,
|
|
|
|
// and start any new sounds
|
|
|
|
S_ScanChannelStarts();
|
|
|
|
|
|
|
|
sane = thisTime - lastTime;
|
|
|
|
if (sane<11) {
|
|
|
|
sane = 11; // 85hz
|
|
|
|
}
|
|
|
|
|
|
|
|
ma = s_mixahead->value * dma.speed;
|
|
|
|
op = s_mixPreStep->value + sane*dma.speed*0.01;
|
|
|
|
|
|
|
|
if (op < ma) {
|
|
|
|
ma = op;
|
|
|
|
}
|
|
|
|
|
|
|
|
// mix ahead of current position
|
|
|
|
endtime = s_soundtime + ma;
|
|
|
|
|
|
|
|
// mix to an even submission block size
|
|
|
|
endtime = (endtime + dma.submission_chunk-1)
|
|
|
|
& ~(dma.submission_chunk-1);
|
|
|
|
|
|
|
|
// never mix more than the complete buffer
|
|
|
|
samps = dma.samples >> (dma.channels-1);
|
|
|
|
if (endtime - s_soundtime > samps)
|
|
|
|
endtime = s_soundtime + samps;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SNDDMA_BeginPainting ();
|
|
|
|
|
|
|
|
S_PaintChannels (endtime);
|
|
|
|
|
|
|
|
SNDDMA_Submit ();
|
|
|
|
|
|
|
|
lastTime = thisTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============================================================================
|
|
|
|
|
|
|
|
background music functions
|
|
|
|
|
|
|
|
===============================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
======================
|
|
|
|
S_StopBackgroundTrack
|
|
|
|
======================
|
|
|
|
*/
|
|
|
|
void S_Base_StopBackgroundTrack( void ) {
|
|
|
|
if(!s_backgroundStream)
|
|
|
|
return;
|
|
|
|
S_CodecCloseStream(s_backgroundStream);
|
|
|
|
s_backgroundStream = NULL;
|
|
|
|
s_rawend[0] = 0;
|
|
|
|
}
|
|
|
|
|
2017-07-10 01:33:41 +00:00
|
|
|
/*
|
|
|
|
======================
|
|
|
|
S_OpenBackgroundStream
|
|
|
|
======================
|
|
|
|
*/
|
|
|
|
static void S_OpenBackgroundStream( const char *filename ) {
|
|
|
|
// close the background track, but DON'T reset s_rawend
|
|
|
|
// if restarting the same back ground track
|
|
|
|
if(s_backgroundStream)
|
|
|
|
{
|
|
|
|
S_CodecCloseStream(s_backgroundStream);
|
|
|
|
s_backgroundStream = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Open stream
|
|
|
|
s_backgroundStream = S_CodecOpenStream(filename);
|
|
|
|
if(!s_backgroundStream) {
|
|
|
|
Com_Printf( S_COLOR_YELLOW "WARNING: couldn't open music file %s\n", filename );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(s_backgroundStream->info.channels != 2 || s_backgroundStream->info.rate != 22050) {
|
|
|
|
Com_Printf(S_COLOR_YELLOW "WARNING: music file %s is not 22k stereo\n", filename );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-18 14:31:32 +00:00
|
|
|
/*
|
|
|
|
======================
|
|
|
|
S_StartBackgroundTrack
|
|
|
|
======================
|
|
|
|
*/
|
|
|
|
void S_Base_StartBackgroundTrack( const char *intro, const char *loop ){
|
|
|
|
if ( !intro ) {
|
|
|
|
intro = "";
|
|
|
|
}
|
|
|
|
if ( !loop || !loop[0] ) {
|
|
|
|
loop = intro;
|
|
|
|
}
|
|
|
|
Com_DPrintf( "S_StartBackgroundTrack( %s, %s )\n", intro, loop );
|
|
|
|
|
|
|
|
if(!*intro)
|
|
|
|
{
|
|
|
|
S_Base_StopBackgroundTrack();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-07-10 01:33:41 +00:00
|
|
|
Q_strncpyz( s_backgroundLoop, loop, sizeof( s_backgroundLoop ) );
|
2011-02-18 14:31:32 +00:00
|
|
|
|
2017-07-10 01:33:41 +00:00
|
|
|
S_OpenBackgroundStream( intro );
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
======================
|
|
|
|
S_UpdateBackgroundTrack
|
|
|
|
======================
|
|
|
|
*/
|
|
|
|
void S_UpdateBackgroundTrack( void ) {
|
|
|
|
int bufferSamples;
|
|
|
|
int fileSamples;
|
|
|
|
byte raw[30000]; // just enough to fit in a mac stack frame
|
|
|
|
int fileBytes;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if(!s_backgroundStream) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// don't bother playing anything if musicvolume is 0
|
|
|
|
if ( s_musicVolume->value <= 0 ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// see how many samples should be copied into the raw buffer
|
|
|
|
if ( s_rawend[0] < s_soundtime ) {
|
|
|
|
s_rawend[0] = s_soundtime;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( s_rawend[0] < s_soundtime + MAX_RAW_SAMPLES ) {
|
|
|
|
bufferSamples = MAX_RAW_SAMPLES - (s_rawend[0] - s_soundtime);
|
|
|
|
|
|
|
|
// decide how much data needs to be read from the file
|
|
|
|
fileSamples = bufferSamples * s_backgroundStream->info.rate / dma.speed;
|
|
|
|
|
|
|
|
if (!fileSamples)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// our max buffer size
|
|
|
|
fileBytes = fileSamples * (s_backgroundStream->info.width * s_backgroundStream->info.channels);
|
|
|
|
if ( fileBytes > sizeof(raw) ) {
|
|
|
|
fileBytes = sizeof(raw);
|
|
|
|
fileSamples = fileBytes / (s_backgroundStream->info.width * s_backgroundStream->info.channels);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read
|
|
|
|
r = S_CodecReadStream(s_backgroundStream, fileBytes, raw);
|
|
|
|
if(r < fileBytes)
|
|
|
|
{
|
|
|
|
fileSamples = r / (s_backgroundStream->info.width * s_backgroundStream->info.channels);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(r > 0)
|
|
|
|
{
|
|
|
|
// add to raw buffer
|
2011-07-29 17:52:36 +00:00
|
|
|
S_Base_RawSamples(0, fileSamples, s_backgroundStream->info.rate,
|
|
|
|
s_backgroundStream->info.width, s_backgroundStream->info.channels, raw, s_musicVolume->value, -1);
|
2011-02-18 14:31:32 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// loop
|
|
|
|
if(s_backgroundLoop[0])
|
|
|
|
{
|
2017-07-10 01:33:41 +00:00
|
|
|
S_OpenBackgroundStream( s_backgroundLoop );
|
2011-02-18 14:31:32 +00:00
|
|
|
if(!s_backgroundStream)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
S_Base_StopBackgroundTrack();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
======================
|
|
|
|
S_FreeOldestSound
|
|
|
|
======================
|
|
|
|
*/
|
|
|
|
|
|
|
|
void S_FreeOldestSound( void ) {
|
|
|
|
int i, oldest, used;
|
|
|
|
sfx_t *sfx;
|
|
|
|
sndBuffer *buffer, *nbuffer;
|
|
|
|
|
|
|
|
oldest = Com_Milliseconds();
|
|
|
|
used = 0;
|
|
|
|
|
|
|
|
for (i=1 ; i < s_numSfx ; i++) {
|
|
|
|
sfx = &s_knownSfx[i];
|
|
|
|
if (sfx->inMemory && sfx->lastTimeUsed<oldest) {
|
|
|
|
used = i;
|
|
|
|
oldest = sfx->lastTimeUsed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sfx = &s_knownSfx[used];
|
|
|
|
|
|
|
|
Com_DPrintf("S_FreeOldestSound: freeing sound %s\n", sfx->soundName);
|
|
|
|
|
|
|
|
buffer = sfx->soundData;
|
|
|
|
while(buffer != NULL) {
|
|
|
|
nbuffer = buffer->next;
|
|
|
|
SND_free(buffer);
|
|
|
|
buffer = nbuffer;
|
|
|
|
}
|
|
|
|
sfx->inMemory = qfalse;
|
|
|
|
sfx->soundData = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// =======================================================================
|
|
|
|
// Shutdown sound engine
|
|
|
|
// =======================================================================
|
|
|
|
|
|
|
|
void S_Base_Shutdown( void ) {
|
|
|
|
if ( !s_soundStarted ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SNDDMA_Shutdown();
|
2011-07-26 08:52:24 +00:00
|
|
|
SND_shutdown();
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
s_soundStarted = 0;
|
2011-07-26 08:52:24 +00:00
|
|
|
s_numSfx = 0;
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
Cmd_RemoveCommand("s_info");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
S_Init
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
qboolean S_Base_Init( soundInterface_t *si ) {
|
|
|
|
qboolean r;
|
|
|
|
|
|
|
|
if( !si ) {
|
|
|
|
return qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
s_mixahead = Cvar_Get ("s_mixahead", "0.2", CVAR_ARCHIVE);
|
|
|
|
s_mixPreStep = Cvar_Get ("s_mixPreStep", "0.05", CVAR_ARCHIVE);
|
|
|
|
s_show = Cvar_Get ("s_show", "0", CVAR_CHEAT);
|
|
|
|
s_testsound = Cvar_Get ("s_testsound", "0", CVAR_CHEAT);
|
|
|
|
|
|
|
|
r = SNDDMA_Init();
|
|
|
|
|
|
|
|
if ( r ) {
|
|
|
|
s_soundStarted = 1;
|
|
|
|
s_soundMuted = 1;
|
|
|
|
// s_numSfx = 0;
|
|
|
|
|
|
|
|
Com_Memset(sfxHash, 0, sizeof(sfx_t *)*LOOP_HASH);
|
|
|
|
|
|
|
|
s_soundtime = 0;
|
|
|
|
s_paintedtime = 0;
|
|
|
|
|
|
|
|
S_Base_StopAllSounds( );
|
|
|
|
} else {
|
|
|
|
return qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
si->Shutdown = S_Base_Shutdown;
|
|
|
|
si->StartSound = S_Base_StartSound;
|
|
|
|
si->StartLocalSound = S_Base_StartLocalSound;
|
|
|
|
si->StartBackgroundTrack = S_Base_StartBackgroundTrack;
|
|
|
|
si->StopBackgroundTrack = S_Base_StopBackgroundTrack;
|
|
|
|
si->RawSamples = S_Base_RawSamples;
|
|
|
|
si->StopAllSounds = S_Base_StopAllSounds;
|
|
|
|
si->ClearLoopingSounds = S_Base_ClearLoopingSounds;
|
|
|
|
si->AddLoopingSound = S_Base_AddLoopingSound;
|
|
|
|
si->AddRealLoopingSound = S_Base_AddRealLoopingSound;
|
|
|
|
si->StopLoopingSound = S_Base_StopLoopingSound;
|
|
|
|
si->Respatialize = S_Base_Respatialize;
|
|
|
|
si->UpdateEntityPosition = S_Base_UpdateEntityPosition;
|
|
|
|
si->Update = S_Base_Update;
|
|
|
|
si->DisableSounds = S_Base_DisableSounds;
|
|
|
|
si->BeginRegistration = S_Base_BeginRegistration;
|
|
|
|
si->RegisterSound = S_Base_RegisterSound;
|
|
|
|
si->ClearSoundBuffer = S_Base_ClearSoundBuffer;
|
|
|
|
si->SoundInfo = S_Base_SoundInfo;
|
|
|
|
si->SoundList = S_Base_SoundList;
|
|
|
|
|
|
|
|
#ifdef USE_VOIP
|
|
|
|
si->StartCapture = S_Base_StartCapture;
|
|
|
|
si->AvailableCaptureSamples = S_Base_AvailableCaptureSamples;
|
|
|
|
si->Capture = S_Base_Capture;
|
|
|
|
si->StopCapture = S_Base_StopCapture;
|
|
|
|
si->MasterGain = S_Base_MasterGain;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return qtrue;
|
|
|
|
}
|