2009-02-28 14:41:18 +00:00
|
|
|
/*
|
2010-06-19 08:47:14 +00:00
|
|
|
* Copyright (C) 1997-2001 Id Software, Inc.
|
|
|
|
*
|
|
|
|
* 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
|
2010-07-13 18:19:42 +00:00
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
|
|
* USA.
|
2010-06-19 08:47:14 +00:00
|
|
|
*
|
|
|
|
* =======================================================================
|
|
|
|
*
|
2010-07-13 18:19:42 +00:00
|
|
|
* Upper layer of the sound output. This is implemented via DMA, thus
|
|
|
|
* needs a DMA capable lower level implementation for painting the
|
|
|
|
* sounds to the device. Otherwise it'll be horible slow and stuttering.
|
2010-06-19 08:47:14 +00:00
|
|
|
*
|
|
|
|
* =======================================================================
|
|
|
|
*/
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2009-03-03 13:43:32 +00:00
|
|
|
#include "../header/client.h"
|
2010-06-19 19:10:31 +00:00
|
|
|
#include "header/local.h"
|
2010-06-19 19:04:39 +00:00
|
|
|
#include "header/vorbis.h"
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
void S_Play ( void );
|
|
|
|
void S_SoundList ( void );
|
|
|
|
void S_Update_ ();
|
|
|
|
void S_StopAllSounds ( void );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* only begin attenuating sound volumes when outside the FULLVOLUME range */
|
2010-10-14 06:59:42 +00:00
|
|
|
#define SOUND_FULLVOLUME 80
|
|
|
|
#define SOUND_LOOPATTENUATE 0.003
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
int s_registration_sequence;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
channel_t channels [ MAX_CHANNELS ];
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
qboolean snd_initialized = false;
|
|
|
|
int sound_started = 0;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
dma_t dma;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
vec3_t listener_origin;
|
|
|
|
vec3_t listener_forward;
|
|
|
|
vec3_t listener_right;
|
|
|
|
vec3_t listener_up;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
static qboolean s_registering;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
static int soundtime;
|
|
|
|
int paintedtime;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* during registration it is possible to have more sounds
|
2010-10-14 06:59:42 +00:00
|
|
|
* than could actually be referenced during gameplay,
|
|
|
|
* because we don't want to free anything until we are
|
|
|
|
* sure we won't need it. */
|
|
|
|
#define MAX_SFX ( MAX_SOUNDS * 2 )
|
|
|
|
sfx_t known_sfx [ MAX_SFX ];
|
|
|
|
int num_sfx;
|
|
|
|
|
|
|
|
#define MAX_PLAYSOUNDS 128
|
|
|
|
playsound_t s_playsounds [ MAX_PLAYSOUNDS ];
|
|
|
|
playsound_t s_freeplays;
|
|
|
|
playsound_t s_pendingplays;
|
|
|
|
|
|
|
|
int s_beginofs;
|
|
|
|
|
|
|
|
cvar_t *s_volume;
|
|
|
|
cvar_t *s_testsound;
|
|
|
|
cvar_t *s_loadas8bit;
|
|
|
|
cvar_t *s_khz;
|
|
|
|
cvar_t *s_mixahead;
|
|
|
|
cvar_t *s_show;
|
|
|
|
|
|
|
|
int s_rawend;
|
|
|
|
portable_samplepair_t s_rawsamples [ MAX_RAW_SAMPLES ];
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/*
|
|
|
|
* User-setable variables
|
|
|
|
*/
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_SoundInfo_f ( void )
|
|
|
|
{
|
|
|
|
if ( !sound_started )
|
|
|
|
{
|
|
|
|
Com_Printf( "sound system not started\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
Com_Printf( "%5d stereo\n", dma.channels - 1 );
|
|
|
|
Com_Printf( "%5d samples\n", dma.samples );
|
|
|
|
Com_Printf( "%5d samplepos\n", dma.samplepos );
|
|
|
|
Com_Printf( "%5d samplebits\n", dma.samplebits );
|
|
|
|
Com_Printf( "%5d submission_chunk\n", dma.submission_chunk );
|
|
|
|
Com_Printf( "%5d speed\n", dma.speed );
|
|
|
|
Com_Printf( "%p dma buffer\n", dma.buffer );
|
2010-06-19 08:47:14 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_Init ( void )
|
|
|
|
{
|
|
|
|
cvar_t *cv;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
Com_Printf( "\n------- sound initialization -------\n" );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
cv = Cvar_Get( "s_initsound", "1", 0 );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !cv->value )
|
|
|
|
{
|
|
|
|
Com_Printf( "not initializing.\n" );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
s_volume = Cvar_Get( "s_volume", "0.7", CVAR_ARCHIVE );
|
|
|
|
s_khz = Cvar_Get( "s_khz", "22", 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 );
|
|
|
|
|
|
|
|
Cmd_AddCommand( "play", S_Play );
|
|
|
|
Cmd_AddCommand( "stopsound", S_StopAllSounds );
|
|
|
|
Cmd_AddCommand( "soundlist", S_SoundList );
|
|
|
|
Cmd_AddCommand( "soundinfo", S_SoundInfo_f );
|
|
|
|
Cmd_AddCommand( "ogg_init", OGG_Init );
|
|
|
|
Cmd_AddCommand( "ogg_shutdown", OGG_Shutdown );
|
|
|
|
|
|
|
|
if ( !SNDDMA_Init() )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
S_InitScaletable();
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
sound_started = 1;
|
|
|
|
num_sfx = 0;
|
|
|
|
|
|
|
|
soundtime = 0;
|
|
|
|
paintedtime = 0;
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
Com_Printf( "sound sampling rate: %i\n", dma.speed );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
S_StopAllSounds();
|
2009-10-03 16:06:45 +00:00
|
|
|
OGG_Init();
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-19 13:34:08 +00:00
|
|
|
Com_Printf( "------------------------------------\n\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/*
|
|
|
|
* Shutdown sound engine
|
|
|
|
*/
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_Shutdown ( void )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
sfx_t *sfx;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !sound_started )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
/* free all sounds */
|
|
|
|
for ( i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++ )
|
2010-10-13 17:07:29 +00:00
|
|
|
{
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !sfx->name [ 0 ] )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( sfx->cache )
|
|
|
|
{
|
|
|
|
Z_Free( sfx->cache );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
memset( known_sfx, 0, sizeof ( known_sfx ) );
|
2010-10-13 17:07:29 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
num_sfx = 0;
|
2010-10-13 17:07:29 +00:00
|
|
|
sound_started = 0;
|
|
|
|
|
|
|
|
OGG_Shutdown();
|
|
|
|
SNDDMA_Shutdown();
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
Cmd_RemoveCommand( "soundlist" );
|
|
|
|
Cmd_RemoveCommand( "soundinfo" );
|
|
|
|
Cmd_RemoveCommand( "play" );
|
|
|
|
Cmd_RemoveCommand( "stopsound" );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-19 17:04:32 +00:00
|
|
|
* Returns the name of a sound
|
2010-06-19 08:47:14 +00:00
|
|
|
*/
|
2010-10-14 06:59:42 +00:00
|
|
|
sfx_t *
|
|
|
|
S_FindName ( char *name, qboolean create )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
sfx_t *sfx;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !name )
|
|
|
|
{
|
|
|
|
Com_Error( ERR_FATAL, "S_FindName: NULL\n" );
|
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !name [ 0 ] )
|
|
|
|
{
|
|
|
|
Com_Error( ERR_FATAL, "S_FindName: empty name\n" );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( strlen( name ) >= MAX_QPATH )
|
|
|
|
{
|
|
|
|
Com_Error( ERR_FATAL, "Sound name too long: %s", name );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* see if already loaded */
|
2010-10-14 06:59:42 +00:00
|
|
|
for ( i = 0; i < num_sfx; i++ )
|
|
|
|
{
|
|
|
|
if ( !strcmp( known_sfx [ i ].name, name ) )
|
|
|
|
{
|
|
|
|
return ( &known_sfx [ i ] );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !create )
|
|
|
|
{
|
|
|
|
return ( NULL );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* find a free sfx */
|
2010-10-14 06:59:42 +00:00
|
|
|
for ( i = 0; i < num_sfx; i++ )
|
|
|
|
{
|
|
|
|
if ( !known_sfx [ i ].name [ 0 ] )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
break;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( i == num_sfx )
|
|
|
|
{
|
|
|
|
if ( num_sfx == MAX_SFX )
|
|
|
|
{
|
|
|
|
Com_Error( ERR_FATAL, "S_FindName: out of sfx_t" );
|
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
num_sfx++;
|
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( strlen( name ) >= MAX_QPATH - 1 )
|
|
|
|
{
|
|
|
|
Com_Error( ERR_FATAL, "Sound name too long: %s", name );
|
|
|
|
}
|
|
|
|
|
|
|
|
sfx = &known_sfx [ i ];
|
2010-10-13 17:07:29 +00:00
|
|
|
sfx->truename = NULL;
|
2010-10-14 06:59:42 +00:00
|
|
|
strcpy( sfx->name, name );
|
2009-02-28 14:41:18 +00:00
|
|
|
sfx->registration_sequence = s_registration_sequence;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
return ( sfx );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
sfx_t *
|
|
|
|
S_AliasName ( char *aliasname, char *truename )
|
|
|
|
{
|
|
|
|
sfx_t *sfx;
|
|
|
|
char *s;
|
|
|
|
int i;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
s = Z_Malloc( MAX_QPATH );
|
|
|
|
strcpy( s, truename );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* find a free sfx */
|
2010-10-14 06:59:42 +00:00
|
|
|
for ( i = 0; i < num_sfx; i++ )
|
|
|
|
{
|
|
|
|
if ( !known_sfx [ i ].name [ 0 ] )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
break;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( i == num_sfx )
|
|
|
|
{
|
|
|
|
if ( num_sfx == MAX_SFX )
|
|
|
|
{
|
|
|
|
Com_Error( ERR_FATAL, "S_FindName: out of sfx_t" );
|
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
num_sfx++;
|
|
|
|
}
|
2010-10-14 06:59:42 +00:00
|
|
|
|
|
|
|
sfx = &known_sfx [ i ];
|
2010-10-13 17:07:29 +00:00
|
|
|
sfx->cache = NULL;
|
2010-10-14 06:59:42 +00:00
|
|
|
strcpy( sfx->name, aliasname );
|
2009-02-28 14:41:18 +00:00
|
|
|
sfx->registration_sequence = s_registration_sequence;
|
|
|
|
sfx->truename = s;
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
return ( sfx );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_BeginRegistration ( void )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
s_registration_sequence++;
|
|
|
|
s_registering = true;
|
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
sfx_t *
|
|
|
|
S_RegisterSound ( char *name )
|
|
|
|
{
|
|
|
|
sfx_t *sfx;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !sound_started )
|
|
|
|
{
|
|
|
|
return ( NULL );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
sfx = S_FindName( name, true );
|
2009-02-28 14:41:18 +00:00
|
|
|
sfx->registration_sequence = s_registration_sequence;
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !s_registering )
|
|
|
|
{
|
|
|
|
S_LoadSound( sfx );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
return ( sfx );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_EndRegistration ( void )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
sfx_t *sfx;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* free any sounds not from this registration sequence */
|
2010-10-14 06:59:42 +00:00
|
|
|
for ( i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++ )
|
|
|
|
{
|
|
|
|
if ( !sfx->name [ 0 ] )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( sfx->registration_sequence != s_registration_sequence )
|
|
|
|
{
|
|
|
|
/* it is possible to have a leftover */
|
|
|
|
if ( sfx->cache )
|
|
|
|
{
|
|
|
|
Z_Free( sfx->cache ); /* from a server that didn't finish loading */
|
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( sfx->truename )
|
|
|
|
{
|
|
|
|
Z_Free( sfx->truename ); /* memleak fix from echon */
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
sfx->cache = NULL;
|
|
|
|
sfx->name [ 0 ] = 0;
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* load everything in */
|
2010-10-14 06:59:42 +00:00
|
|
|
for ( i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++ )
|
|
|
|
{
|
|
|
|
if ( !sfx->name [ 0 ] )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
S_LoadSound( sfx );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
s_registering = false;
|
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
channel_t *
|
|
|
|
S_PickChannel ( int entnum, int entchannel )
|
|
|
|
{
|
|
|
|
int ch_idx;
|
|
|
|
int first_to_die;
|
|
|
|
int life_left;
|
|
|
|
channel_t *ch;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( entchannel < 0 )
|
|
|
|
{
|
|
|
|
Com_Error( ERR_DROP, "S_PickChannel: entchannel<0" );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* Check for replacement sound, or find the best one to replace */
|
|
|
|
first_to_die = -1;
|
|
|
|
life_left = 0x7fffffff;
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
for ( ch_idx = 0; ch_idx < MAX_CHANNELS; ch_idx++ )
|
|
|
|
{
|
|
|
|
/* channel 0 never overrides */
|
|
|
|
if ( ( entchannel != 0 ) &&
|
|
|
|
( channels [ ch_idx ].entnum == entnum ) &&
|
|
|
|
( channels [ ch_idx ].entchannel == entchannel ) )
|
|
|
|
{
|
2010-06-19 08:47:14 +00:00
|
|
|
/* always override sound from same entity */
|
2009-02-28 14:41:18 +00:00
|
|
|
first_to_die = ch_idx;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* don't let monster sounds override player sounds */
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( ( channels [ ch_idx ].entnum == cl.playernum + 1 ) && ( entnum != cl.playernum + 1 ) && channels [ ch_idx ].sfx )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( channels [ ch_idx ].end - paintedtime < life_left )
|
|
|
|
{
|
|
|
|
life_left = channels [ ch_idx ].end - paintedtime;
|
2009-02-28 14:41:18 +00:00
|
|
|
first_to_die = ch_idx;
|
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( first_to_die == -1 )
|
|
|
|
{
|
|
|
|
return ( NULL );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
ch = &channels [ first_to_die ];
|
|
|
|
memset( ch, 0, sizeof ( *ch ) );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
return ( ch );
|
2010-06-19 08:47:14 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
/*
|
2010-06-19 08:47:14 +00:00
|
|
|
* Used for spatializing channels and autosounds
|
|
|
|
*/
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_SpatializeOrigin ( vec3_t origin, float master_vol, float dist_mult, int *left_vol, int *right_vol )
|
|
|
|
{
|
|
|
|
vec_t dot;
|
|
|
|
vec_t dist;
|
|
|
|
vec_t lscale, rscale, scale;
|
|
|
|
vec3_t source_vec;
|
|
|
|
|
|
|
|
if ( cls.state != ca_active )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
*left_vol = *right_vol = 255;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* calculate stereo seperation and distance attenuation */
|
2010-10-14 06:59:42 +00:00
|
|
|
VectorSubtract( origin, listener_origin, source_vec );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
dist = VectorNormalize( source_vec );
|
2009-02-28 14:41:18 +00:00
|
|
|
dist -= SOUND_FULLVOLUME;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( dist < 0 )
|
|
|
|
{
|
2010-06-19 17:04:32 +00:00
|
|
|
dist = 0; /* close enough to be at full volume */
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-06-19 17:04:32 +00:00
|
|
|
dist *= dist_mult; /* different attenuation levels */
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
dot = DotProduct( listener_right, source_vec );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( ( dma.channels == 1 ) || !dist_mult )
|
|
|
|
{
|
2010-06-19 08:47:14 +00:00
|
|
|
/* no attenuation = no spatialization */
|
2009-03-03 11:00:08 +00:00
|
|
|
rscale = 1.0f;
|
|
|
|
lscale = 1.0f;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rscale = 0.5f * ( 1.0f + dot );
|
|
|
|
lscale = 0.5f * ( 1.0f - dot );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* add in distance effect */
|
2010-10-14 06:59:42 +00:00
|
|
|
scale = ( 1.0f - dist ) * rscale;
|
|
|
|
*right_vol = (int) ( master_vol * scale );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( *right_vol < 0 )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
*right_vol = 0;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
scale = ( 1.0 - dist ) * lscale;
|
|
|
|
*left_vol = (int) ( master_vol * scale );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( *left_vol < 0 )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
*left_vol = 0;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_Spatialize ( channel_t *ch )
|
|
|
|
{
|
|
|
|
vec3_t origin;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* anything coming from the view entity will always be full volume */
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( ch->entnum == cl.playernum + 1 )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ch->leftvol = ch->master_vol;
|
|
|
|
ch->rightvol = ch->master_vol;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( ch->fixed_origin )
|
|
|
|
{
|
|
|
|
VectorCopy( ch->origin, origin );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CL_GetEntitySoundOrigin( ch->entnum, origin );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
S_SpatializeOrigin( origin, (float) ch->master_vol, ch->dist_mult, &ch->leftvol, &ch->rightvol );
|
2010-06-19 08:47:14 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
playsound_t *
|
|
|
|
S_AllocPlaysound ( void )
|
|
|
|
{
|
|
|
|
playsound_t *ps;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
ps = s_freeplays.next;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( ps == &s_freeplays )
|
2010-10-13 18:00:39 +00:00
|
|
|
{
|
2010-10-14 06:59:42 +00:00
|
|
|
return ( NULL ); /* no free playsounds, this results in stuttering an cracking */
|
2010-10-13 18:00:39 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* unlink from freelist */
|
2009-02-28 14:41:18 +00:00
|
|
|
ps->prev->next = ps->next;
|
|
|
|
ps->next->prev = ps->prev;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
return ( ps );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_FreePlaysound ( playsound_t *ps )
|
|
|
|
{
|
2010-06-19 08:47:14 +00:00
|
|
|
/* unlink from channel */
|
2009-02-28 14:41:18 +00:00
|
|
|
ps->prev->next = ps->next;
|
|
|
|
ps->next->prev = ps->prev;
|
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* add to free list */
|
2009-02-28 14:41:18 +00:00
|
|
|
ps->next = s_freeplays.next;
|
|
|
|
s_freeplays.next->prev = ps;
|
|
|
|
ps->prev = &s_freeplays;
|
|
|
|
s_freeplays.next = ps;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-19 08:47:14 +00:00
|
|
|
* Take the next playsound and begin it on the channel
|
|
|
|
* This is never called directly by S_Play*, but only
|
|
|
|
* by the update loop.
|
2010-10-14 06:59:42 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
S_IssuePlaysound ( playsound_t *ps )
|
|
|
|
{
|
|
|
|
channel_t *ch;
|
|
|
|
sfxcache_t *sc;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !ps )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( s_show->value )
|
|
|
|
{
|
|
|
|
Com_Printf( "Issue %i\n", ps->begin );
|
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
|
|
|
/* pick a channel to play on */
|
2010-10-14 06:59:42 +00:00
|
|
|
ch = S_PickChannel( ps->entnum, ps->entchannel );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !ch )
|
|
|
|
{
|
|
|
|
S_FreePlaysound( ps );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* spatialize */
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( ps->attenuation == ATTN_STATIC )
|
|
|
|
{
|
2009-03-03 11:00:08 +00:00
|
|
|
ch->dist_mult = ps->attenuation * 0.001f;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
2010-10-14 06:59:42 +00:00
|
|
|
{
|
2009-03-03 11:00:08 +00:00
|
|
|
ch->dist_mult = ps->attenuation * 0.0005f;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
ch->master_vol = (int) ps->volume;
|
2009-02-28 14:41:18 +00:00
|
|
|
ch->entnum = ps->entnum;
|
|
|
|
ch->entchannel = ps->entchannel;
|
|
|
|
ch->sfx = ps->sfx;
|
2010-10-14 06:59:42 +00:00
|
|
|
VectorCopy( ps->origin, ch->origin );
|
2009-02-28 14:41:18 +00:00
|
|
|
ch->fixed_origin = ps->fixed_origin;
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
S_Spatialize( ch );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
ch->pos = 0;
|
2010-10-14 06:59:42 +00:00
|
|
|
sc = S_LoadSound( ch->sfx );
|
2010-06-19 08:47:14 +00:00
|
|
|
ch->end = paintedtime + sc->length;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* free the playsound */
|
2010-10-14 06:59:42 +00:00
|
|
|
S_FreePlaysound( ps );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
struct sfx_s *
|
|
|
|
S_RegisterSexedSound ( entity_state_t *ent, char *base )
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
char *p;
|
|
|
|
int len;
|
|
|
|
struct sfx_s *sfx;
|
|
|
|
char model [ MAX_QPATH ];
|
|
|
|
char sexedFilename [ MAX_QPATH ];
|
|
|
|
char maleFilename [ MAX_QPATH ];
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* determine what model the client is using */
|
2010-10-14 06:59:42 +00:00
|
|
|
model [ 0 ] = 0;
|
2009-02-28 14:41:18 +00:00
|
|
|
n = CS_PLAYERSKINS + ent->number - 1;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( cl.configstrings [ n ] [ 0 ] )
|
|
|
|
{
|
|
|
|
p = strchr( cl.configstrings [ n ], '\\' );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( p )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
p += 1;
|
2010-10-14 06:59:42 +00:00
|
|
|
strcpy( model, p );
|
|
|
|
p = strchr( model, '/' );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( p )
|
|
|
|
{
|
|
|
|
p [ 0 ] = 0;
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
|
|
|
/* if we can't figure it out, they're male */
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !model [ 0 ] )
|
|
|
|
{
|
|
|
|
strcpy( model, "male" );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* see if we already know of the model specific sound */
|
2010-10-14 06:59:42 +00:00
|
|
|
Com_sprintf( sexedFilename, sizeof ( sexedFilename ), "#players/%s/%s", model, base + 1 );
|
|
|
|
sfx = S_FindName( sexedFilename, false );
|
|
|
|
|
|
|
|
if ( !sfx )
|
|
|
|
{
|
|
|
|
/* no, so see if it exists */
|
|
|
|
len = FS_LoadFile( &sexedFilename [ 1 ], NULL );
|
|
|
|
|
|
|
|
if ( len != -1 )
|
2010-10-13 17:07:29 +00:00
|
|
|
{
|
2010-10-14 06:59:42 +00:00
|
|
|
/* yes, close the file and register it */
|
|
|
|
sfx = S_RegisterSound( sexedFilename );
|
2010-10-13 17:07:29 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-10-14 06:59:42 +00:00
|
|
|
/* no, revert to the male sound in the pak0.pak */
|
|
|
|
Com_sprintf( maleFilename, sizeof ( maleFilename ), "player/male/%s", base + 1 );
|
|
|
|
sfx = S_AliasName( sexedFilename, maleFilename );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
return ( sfx );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-19 08:47:14 +00:00
|
|
|
* 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
|
|
|
|
* override a playing sound
|
|
|
|
*/
|
2010-10-14 06:59:42 +00:00
|
|
|
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 )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !sfx )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( sfx->name [ 0 ] == '*' )
|
|
|
|
{
|
|
|
|
sfx = S_RegisterSexedSound( &cl_entities [ entnum ].current, sfx->name );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* make sure the sound is loaded */
|
2010-10-14 06:59:42 +00:00
|
|
|
sc = S_LoadSound( sfx );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !sc )
|
|
|
|
{
|
2010-06-19 08:47:14 +00:00
|
|
|
return; /* couldn't load the sound's data */
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
vol = fvol * 255;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* make the playsound_t */
|
2010-10-14 06:59:42 +00:00
|
|
|
ps = S_AllocPlaysound();
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !ps )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( origin )
|
|
|
|
{
|
|
|
|
VectorCopy( origin, ps->origin );
|
2009-02-28 14:41:18 +00:00
|
|
|
ps->fixed_origin = true;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ps->fixed_origin = false;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
ps->entnum = entnum;
|
|
|
|
ps->entchannel = entchannel;
|
|
|
|
ps->attenuation = attenuation;
|
|
|
|
ps->volume = vol;
|
|
|
|
ps->sfx = sfx;
|
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* drift s_beginofs */
|
2010-10-14 06:59:42 +00:00
|
|
|
start = (int) ( cl.frame.servertime * 0.001f * dma.speed + s_beginofs );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( start < paintedtime )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
start = paintedtime;
|
2010-10-14 06:59:42 +00:00
|
|
|
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;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !timeofs )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ps->begin = paintedtime;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
2010-10-14 06:59:42 +00:00
|
|
|
{
|
|
|
|
ps->begin = (int) ( start + timeofs * dma.speed );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
ps->volume = fvol * 255;
|
2009-03-10 20:29:15 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* sort into the pending sound list */
|
2010-10-14 06:59:42 +00:00
|
|
|
for ( sort = s_pendingplays.next;
|
|
|
|
sort != &s_pendingplays && sort->begin < ps->begin;
|
|
|
|
sort = sort->next )
|
|
|
|
{
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
ps->next = sort;
|
|
|
|
ps->prev = sort->prev;
|
|
|
|
|
|
|
|
ps->next->prev = ps;
|
|
|
|
ps->prev->next = ps;
|
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_StartLocalSound ( char *sound )
|
|
|
|
{
|
|
|
|
sfx_t *sfx;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !sound_started )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
sfx = S_RegisterSound( sound );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !sfx )
|
|
|
|
{
|
|
|
|
Com_Printf( "S_StartLocalSound: can't cache %s\n", sound );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
S_StartSound( NULL, cl.playernum + 1, 0, sfx, 1, 1, 0 );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_ClearBuffer ( void )
|
|
|
|
{
|
|
|
|
int clear;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !sound_started )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
s_rawend = 0;
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( dma.samplebits == 8 )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
clear = 0x80;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
2010-10-14 06:59:42 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
clear = 0;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
SNDDMA_BeginPainting();
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( dma.buffer )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
unsigned char *ptr = (unsigned char *) dma.buffer;
|
2010-10-13 18:00:39 +00:00
|
|
|
|
|
|
|
i = dma.samples * dma.samplebits / 8;
|
2010-10-14 06:59:42 +00:00
|
|
|
|
|
|
|
while ( i-- )
|
|
|
|
{
|
2010-10-13 18:00:39 +00:00
|
|
|
*ptr = clear;
|
|
|
|
ptr++;
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
SNDDMA_Submit();
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_StopAllSounds ( void )
|
|
|
|
{
|
|
|
|
int i;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !sound_started )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* clear all the playsounds */
|
2010-10-14 06:59:42 +00:00
|
|
|
memset( s_playsounds, 0, sizeof ( s_playsounds ) );
|
2009-02-28 14:41:18 +00:00
|
|
|
s_freeplays.next = s_freeplays.prev = &s_freeplays;
|
|
|
|
s_pendingplays.next = s_pendingplays.prev = &s_pendingplays;
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
for ( i = 0; i < MAX_PLAYSOUNDS; i++ )
|
|
|
|
{
|
|
|
|
s_playsounds [ i ].prev = &s_freeplays;
|
|
|
|
s_playsounds [ i ].next = s_freeplays.next;
|
|
|
|
s_playsounds [ i ].prev->next = &s_playsounds [ i ];
|
|
|
|
s_playsounds [ i ].next->prev = &s_playsounds [ i ];
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* clear all the channels */
|
2010-10-14 06:59:42 +00:00
|
|
|
memset( channels, 0, sizeof ( channels ) );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
S_ClearBuffer();
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-19 08:47:14 +00:00
|
|
|
* Entities with a ->sound field will generated looped sounds
|
|
|
|
* that are automatically started, stopped, and merged together
|
|
|
|
* as the entities are sent to the client
|
|
|
|
*/
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_AddLoopSounds ( void )
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
int sounds [ MAX_EDICTS ];
|
|
|
|
int left, right, left_total, right_total;
|
|
|
|
channel_t *ch;
|
|
|
|
sfx_t *sfx;
|
|
|
|
sfxcache_t *sc;
|
|
|
|
int num;
|
|
|
|
entity_state_t *ent;
|
|
|
|
vec3_t origin;
|
|
|
|
|
|
|
|
if ( cl_paused->value )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( cls.state != ca_active )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !cl.sound_prepped )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
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;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
for ( i = 0; i < cl.frame.num_entities; i++ )
|
|
|
|
{
|
|
|
|
if ( !sounds [ i ] )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
sfx = cl.sound_precache [ sounds [ i ] ];
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !sfx )
|
|
|
|
{
|
2010-06-19 08:47:14 +00:00
|
|
|
continue; /* bad sound effect */
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
sc = sfx->cache;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !sc )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
num = ( cl.frame.parse_entities + i ) & ( MAX_PARSE_ENTITIES - 1 );
|
|
|
|
ent = &cl_parse_entities [ num ];
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
CL_GetEntitySoundOrigin( ent->number, origin );
|
2010-10-13 17:07:29 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* find the total contribution of all sounds of this type */
|
2010-10-14 06:59:42 +00:00
|
|
|
S_SpatializeOrigin( ent->origin, 255.0f, SOUND_LOOPATTENUATE, &left_total, &right_total );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
for ( j = i + 1; j < cl.frame.num_entities; j++ )
|
|
|
|
{
|
|
|
|
if ( sounds [ j ] != sounds [ i ] )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
sounds [ j ] = 0; /* don't check this again later */
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
num = ( cl.frame.parse_entities + j ) & ( MAX_PARSE_ENTITIES - 1 );
|
|
|
|
ent = &cl_parse_entities [ num ];
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
S_SpatializeOrigin( ent->origin, 255.0f, SOUND_LOOPATTENUATE,
|
|
|
|
&left, &right );
|
2009-02-28 14:41:18 +00:00
|
|
|
left_total += left;
|
|
|
|
right_total += right;
|
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( ( left_total == 0 ) && ( right_total == 0 ) )
|
|
|
|
{
|
2010-06-19 08:47:14 +00:00
|
|
|
continue; /* not audible */
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* allocate a channel */
|
2010-10-14 06:59:42 +00:00
|
|
|
ch = S_PickChannel( 0, 0 );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !ch )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( left_total > 255 )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
left_total = 255;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( right_total > 255 )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
right_total = 255;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
ch->leftvol = left_total;
|
|
|
|
ch->rightvol = right_total;
|
2010-06-19 17:04:32 +00:00
|
|
|
ch->autosound = true; /* remove next frame */
|
2009-02-28 14:41:18 +00:00
|
|
|
ch->sfx = sfx;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
|
|
|
/* Sometimes, the sc->length argument can become 0,
|
|
|
|
and in that case we get a SIGFPE in the next
|
|
|
|
modulo operation. The workaround checks for this
|
|
|
|
situation and in that case, sets the pos and end
|
2010-10-14 06:59:42 +00:00
|
|
|
parameters to 0. */
|
|
|
|
if ( sc->length == 0 )
|
|
|
|
{
|
2010-06-19 08:47:14 +00:00
|
|
|
ch->pos = 0;
|
|
|
|
ch->end = 0;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-19 08:47:14 +00:00
|
|
|
ch->pos = paintedtime % sc->length;
|
|
|
|
ch->end = paintedtime + sc->length - ch->pos;
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-19 08:47:14 +00:00
|
|
|
* Cinematic streaming and voice over network
|
2010-07-13 08:54:23 +00:00
|
|
|
* This could be used for chat over network, but that
|
2010-10-14 06:59:42 +00:00
|
|
|
* would be terrible slow.
|
2010-06-19 08:47:14 +00:00
|
|
|
*/
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_RawSamples ( int samples, int rate, int width, int channels, byte *data )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int src, dst;
|
|
|
|
float scale;
|
|
|
|
|
|
|
|
if ( !sound_started )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( s_rawend < paintedtime )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
s_rawend = paintedtime;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
scale = (float) rate / dma.speed;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( ( channels == 2 ) && ( width == 2 ) )
|
|
|
|
{
|
|
|
|
for ( i = 0; ; i++ )
|
|
|
|
{
|
|
|
|
src = (int) ( i * scale );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( src >= samples )
|
|
|
|
{
|
|
|
|
break;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
dst = s_rawend & ( MAX_RAW_SAMPLES - 1 );
|
|
|
|
s_rawend++;
|
|
|
|
s_rawsamples [ dst ].left = LittleShort( ( (short *) data ) [ src * 2 ] ) << 8;
|
|
|
|
s_rawsamples [ dst ].right = LittleShort( ( (short *) data ) [ src * 2 + 1 ] ) << 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( ( channels == 1 ) && ( width == 2 ) )
|
|
|
|
{
|
|
|
|
for ( i = 0; ; i++ )
|
|
|
|
{
|
|
|
|
src = (int) ( i * scale );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( src >= samples )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
break;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
dst = s_rawend & ( MAX_RAW_SAMPLES - 1 );
|
2009-02-28 14:41:18 +00:00
|
|
|
s_rawend++;
|
2010-10-14 06:59:42 +00:00
|
|
|
s_rawsamples [ dst ].left = LittleShort( ( (short *) data ) [ src ] ) << 8;
|
|
|
|
s_rawsamples [ dst ].right = LittleShort( ( (short *) data ) [ src ] ) << 8;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
|
|
|
else if ( ( channels == 2 ) && ( width == 1 ) )
|
|
|
|
{
|
|
|
|
for ( i = 0; ; i++ )
|
|
|
|
{
|
|
|
|
src = (int) ( i * scale );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( src >= samples )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
break;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
dst = s_rawend & ( MAX_RAW_SAMPLES - 1 );
|
2009-02-28 14:41:18 +00:00
|
|
|
s_rawend++;
|
2010-10-14 06:59:42 +00:00
|
|
|
s_rawsamples [ dst ].left = ( (char *) data ) [ src * 2 ] << 16;
|
|
|
|
s_rawsamples [ dst ].right = ( (char *) data ) [ src * 2 + 1 ] << 16;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
|
|
|
else if ( ( channels == 1 ) && ( width == 1 ) )
|
|
|
|
{
|
|
|
|
for ( i = 0; ; i++ )
|
|
|
|
{
|
|
|
|
src = (int) ( i * scale );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( src >= samples )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
break;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
dst = s_rawend & ( MAX_RAW_SAMPLES - 1 );
|
2009-02-28 14:41:18 +00:00
|
|
|
s_rawend++;
|
2010-10-14 06:59:42 +00:00
|
|
|
s_rawsamples [ dst ].left = ( ( (byte *) data ) [ src ] - 128 ) << 16;
|
|
|
|
s_rawsamples [ dst ].right = ( ( (byte *) data ) [ src ] - 128 ) << 16;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
GetSoundtime ( void )
|
|
|
|
{
|
|
|
|
int samplepos;
|
|
|
|
static int buffers;
|
|
|
|
static int oldsamplepos;
|
|
|
|
int fullsamples;
|
|
|
|
|
|
|
|
fullsamples = dma.samples / dma.channels;
|
|
|
|
|
|
|
|
/* it is possible to miscount buffers if it has wrapped twice between
|
|
|
|
calls to S_Update. Oh well. This a hack around that. */
|
|
|
|
samplepos = SNDDMA_GetDMAPos();
|
|
|
|
|
|
|
|
if ( samplepos < oldsamplepos )
|
|
|
|
{
|
|
|
|
buffers++; /* buffer wrapped */
|
|
|
|
|
|
|
|
if ( paintedtime > 0x40000000 )
|
|
|
|
{
|
|
|
|
/* time to chop things off to avoid 32 bit limits */
|
|
|
|
buffers = 0;
|
|
|
|
paintedtime = fullsamples;
|
|
|
|
S_StopAllSounds();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
oldsamplepos = samplepos;
|
|
|
|
soundtime = buffers * fullsamples + samplepos / dma.channels;
|
|
|
|
}
|
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
/*
|
2010-06-19 08:47:14 +00:00
|
|
|
* Called once each time through the main loop
|
|
|
|
*/
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_Update ( vec3_t origin, vec3_t forward, vec3_t right, vec3_t up )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int total;
|
|
|
|
channel_t *ch;
|
|
|
|
unsigned endtime;
|
|
|
|
int samps;
|
|
|
|
|
|
|
|
if ( !sound_started )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* if the laoding plaque is up, clear everything
|
2010-10-14 06:59:42 +00:00
|
|
|
* out to make sure we aren't looping a dirty
|
|
|
|
* dma buffer while loading */
|
|
|
|
if ( cls.disable_screen )
|
|
|
|
{
|
2010-10-13 17:07:29 +00:00
|
|
|
S_ClearBuffer();
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* rebuild scale tables if volume is modified */
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( s_volume->modified )
|
|
|
|
{
|
|
|
|
S_InitScaletable();
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
VectorCopy( origin, listener_origin );
|
|
|
|
VectorCopy( forward, listener_forward );
|
|
|
|
VectorCopy( right, listener_right );
|
|
|
|
VectorCopy( up, listener_up );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* update spatialization for dynamic sounds */
|
2009-02-28 14:41:18 +00:00
|
|
|
ch = channels;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
for ( i = 0; i < MAX_CHANNELS; i++, ch++ )
|
|
|
|
{
|
|
|
|
if ( !ch->sfx )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( ch->autosound )
|
|
|
|
{
|
2010-06-19 08:47:14 +00:00
|
|
|
/* autosounds are regenerated fresh each frame */
|
2010-10-14 06:59:42 +00:00
|
|
|
memset( ch, 0, sizeof ( *ch ) );
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
S_Spatialize( ch ); /* respatialize channel */
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !ch->leftvol && !ch->rightvol )
|
|
|
|
{
|
|
|
|
memset( ch, 0, sizeof ( *ch ) );
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* add loopsounds */
|
2010-10-14 06:59:42 +00:00
|
|
|
S_AddLoopSounds();
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* debugging output */
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( s_show->value )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
total = 0;
|
|
|
|
ch = channels;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
for ( i = 0; i < MAX_CHANNELS; i++, ch++ )
|
|
|
|
{
|
|
|
|
if ( ch->sfx && ( ch->leftvol || ch->rightvol ) )
|
|
|
|
{
|
|
|
|
Com_Printf( "%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name );
|
2009-02-28 14:41:18 +00:00
|
|
|
total++;
|
|
|
|
}
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
Com_Printf( "----(%i)---- painted: %i\n", total, paintedtime );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-10-14 06:59:42 +00:00
|
|
|
|
2009-10-03 16:06:45 +00:00
|
|
|
/* stream music */
|
2010-10-14 06:59:42 +00:00
|
|
|
OGG_Stream();
|
|
|
|
|
|
|
|
/* mix some sound */
|
|
|
|
if ( !sound_started )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
SNDDMA_BeginPainting();
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !dma.buffer )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* Updates DMA time */
|
2009-02-28 14:41:18 +00:00
|
|
|
GetSoundtime();
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !soundtime )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* check to make sure that we haven't overshot */
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( paintedtime < soundtime )
|
|
|
|
{
|
|
|
|
Com_DPrintf( "S_Update_ : overflow\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
paintedtime = soundtime;
|
|
|
|
}
|
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* mix ahead of current position */
|
2010-10-14 06:59:42 +00:00
|
|
|
endtime = (int) ( soundtime + s_mixahead->value * dma.speed );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-19 08:47:14 +00:00
|
|
|
/* mix to an even submission block size */
|
2010-10-14 06:59:42 +00:00
|
|
|
endtime = ( endtime + dma.submission_chunk - 1 ) & ~( dma.submission_chunk - 1 );
|
|
|
|
samps = dma.samples >> ( dma.channels - 1 );
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( endtime - soundtime > samps )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
endtime = soundtime + samps;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
S_PaintChannels( endtime );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
SNDDMA_Submit();
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_Play ( void )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char name [ 256 ];
|
|
|
|
sfx_t *sfx;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
i = 1;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
while ( i < Cmd_Argc() )
|
|
|
|
{
|
|
|
|
if ( !strrchr( Cmd_Argv( i ), '.' ) )
|
|
|
|
{
|
|
|
|
strncpy( name, Cmd_Argv( i ), sizeof ( name ) - 5 );
|
|
|
|
strcat( name, ".wav" );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
strncpy( name, Cmd_Argv( i ), sizeof ( name ) - 1 );
|
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( strstr( name, ".." ) || ( name [ 0 ] == '/' ) || ( name [ 0 ] == '\\' ) )
|
|
|
|
{
|
|
|
|
Com_Printf( "Bad filename %s\n", name );
|
2010-10-13 17:07:29 +00:00
|
|
|
return;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-10-13 17:07:29 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
sfx = S_RegisterSound( name );
|
2010-10-13 17:07:29 +00:00
|
|
|
{
|
2010-10-14 06:59:42 +00:00
|
|
|
S_StartSound( NULL, cl.playernum + 1, 0, sfx, 1.0, 1.0, 0 );
|
2010-10-13 17:07:29 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
void
|
|
|
|
S_SoundList ( void )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
sfx_t *sfx;
|
|
|
|
sfxcache_t *sc;
|
|
|
|
int size, total;
|
|
|
|
int numsounds;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
total = 0;
|
2010-10-13 17:07:29 +00:00
|
|
|
numsounds = 0;
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2010-10-14 06:59:42 +00:00
|
|
|
for ( sfx = known_sfx, i = 0; i < num_sfx; i++, sfx++ )
|
2010-10-13 17:07:29 +00:00
|
|
|
{
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( !sfx->name [ 0 ] )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
2010-10-14 06:59:42 +00:00
|
|
|
}
|
2010-06-19 08:47:14 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
sc = sfx->cache;
|
2010-10-14 06:59:42 +00:00
|
|
|
|
|
|
|
if ( sc )
|
2010-10-13 17:07:29 +00:00
|
|
|
{
|
2010-10-14 06:59:42 +00:00
|
|
|
size = sc->length * sc->width * ( sc->stereo + 1 );
|
2009-02-28 14:41:18 +00:00
|
|
|
total += size;
|
2010-10-14 06:59:42 +00:00
|
|
|
Com_Printf( "%s(%2db) %8i : %s\n", sc->loopstart != -1 ? "L" : " ", sc->width * 8, size, sfx->name );
|
2010-10-13 17:07:29 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-10-14 06:59:42 +00:00
|
|
|
if ( sfx->name [ 0 ] == '*' )
|
|
|
|
{
|
|
|
|
Com_Printf( " placeholder : %s\n", sfx->name );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
2010-10-14 06:59:42 +00:00
|
|
|
{
|
|
|
|
Com_Printf( " not loaded : %s\n", sfx->name );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-10-14 06:59:42 +00:00
|
|
|
|
2010-10-13 17:07:29 +00:00
|
|
|
numsounds++;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-10-14 06:59:42 +00:00
|
|
|
|
|
|
|
Com_Printf( "Total resident: %i bytes (%.2f MB) in %d sounds\n", total, (float) total / 1024 / 1024, numsounds );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-06-19 17:04:32 +00:00
|
|
|
|