xash3d-fwgs/engine/client/s_load.c
Gleb Mazovetskiy 5e0a0765ce Trim all trailing whitespace
The `.editorconfig` file in this repo is configured to trim all trailing
whitespace regardless of whether the line is modified.

Trims all trailing whitespace in the repository to make the codebase easier
to work with in editors that respect `.editorconfig`.

`git blame` becomes less useful on these lines but it already isn't very useful.

Commands:

```
find . -type f -name '*.h' -exec sed --in-place 's/[[:space:]]\+$//' {} \+
find . -type f -name '*.c' -exec sed --in-place 's/[[:space:]]\+$//' {} \+
```
2021-01-04 20:55:10 +03:00

411 lines
8.5 KiB
C

/*
s_load.c - sounds managment
Copyright (C) 2007 Uncle Mike
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 3 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.
*/
#include "common.h"
#include "sound.h"
// during registration it is possible to have more sounds
// 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 8192
#define MAX_SFX_HASH (MAX_SFX/4)
static int s_numSfx = 0;
static sfx_t s_knownSfx[MAX_SFX];
static sfx_t *s_sfxHashList[MAX_SFX_HASH];
static string s_sentenceImmediateName; // keep dummy sentence name
qboolean s_registering = false;
int s_registration_sequence = 0;
/*
=================
S_SoundList_f
=================
*/
void S_SoundList_f( void )
{
sfx_t *sfx;
wavdata_t *sc;
int i, totalSfx = 0;
int totalSize = 0;
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
{
if( !sfx->name[0] )
continue;
sc = sfx->cache;
if( sc )
{
totalSize += sc->size;
if( sc->loopStart >= 0 ) Con_Printf( "L" );
else Con_Printf( " " );
if( sfx->name[0] == '*' )
Con_Printf( " (%2db) %s : %s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
else Con_Printf( " (%2db) %s : " DEFAULT_SOUNDPATH "%s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
totalSfx++;
}
}
Con_Printf( "-------------------------------------------\n" );
Con_Printf( "%i total sounds\n", totalSfx );
Con_Printf( "%s total memory\n", Q_memprint( totalSize ));
Con_Printf( "\n" );
}
// return true if char 'c' is one of 1st 2 characters in pch
qboolean S_TestSoundChar( const char *pch, char c )
{
char *pcht = (char *)pch;
int i;
if( !pch || !*pch )
return false;
// check first 2 characters
for( i = 0; i < 2; i++ )
{
if( *pcht == c )
return true;
pcht++;
}
return false;
}
// return pointer to first valid character in file name
char *S_SkipSoundChar( const char *pch )
{
char *pcht = (char *)pch;
// check first character
if( *pcht == '!' )
pcht++;
return pcht;
}
/*
=================
S_CreateDefaultSound
=================
*/
static wavdata_t *S_CreateDefaultSound( void )
{
wavdata_t *sc;
sc = Mem_Calloc( sndpool, sizeof( wavdata_t ));
sc->width = 2;
sc->channels = 1;
sc->loopStart = -1;
sc->rate = SOUND_DMA_SPEED;
sc->samples = SOUND_DMA_SPEED;
sc->size = sc->samples * sc->width * sc->channels;
sc->buffer = Mem_Calloc( sndpool, sc->size );
return sc;
}
/*
=================
S_LoadSound
=================
*/
wavdata_t *S_LoadSound( sfx_t *sfx )
{
wavdata_t *sc = NULL;
if( !sfx ) return NULL;
// see if still in memory
if( sfx->cache )
return sfx->cache;
if( !COM_CheckString( sfx->name ))
return NULL;
// load it from disk
if( Q_stricmp( sfx->name, "*default" ))
{
// load it from disk
if( sfx->name[0] == '*' )
sc = FS_LoadSound( sfx->name + 1, NULL, 0 );
else sc = FS_LoadSound( sfx->name, NULL, 0 );
}
if( !sc ) sc = S_CreateDefaultSound();
if( sc->rate < SOUND_11k ) // some bad sounds
Sound_Process( &sc, SOUND_11k, sc->width, SOUND_RESAMPLE );
else if( sc->rate > SOUND_11k && sc->rate < SOUND_22k ) // some bad sounds
Sound_Process( &sc, SOUND_22k, sc->width, SOUND_RESAMPLE );
else if( sc->rate > SOUND_22k && sc->rate <= SOUND_32k ) // some bad sounds
Sound_Process( &sc, SOUND_44k, sc->width, SOUND_RESAMPLE );
sfx->cache = sc;
return sfx->cache;
}
// =======================================================================
// Load a sound
// =======================================================================
/*
==================
S_FindName
==================
*/
sfx_t *S_FindName( const char *pname, int *pfInCache )
{
sfx_t *sfx;
uint i, hash;
string name;
if( !COM_CheckString( pname ) || !dma.initialized )
return NULL;
if( Q_strlen( pname ) >= sizeof( sfx->name ))
return NULL;
Q_strncpy( name, pname, sizeof( name ));
COM_FixSlashes( name );
// see if already loaded
hash = COM_HashKey( name, MAX_SFX_HASH );
for( sfx = s_sfxHashList[hash]; sfx; sfx = sfx->hashNext )
{
if( !Q_strcmp( sfx->name, name ))
{
if( pfInCache )
{
// indicate whether or not sound is currently in the cache.
*pfInCache = ( sfx->cache != NULL ) ? true : false;
}
// prolonge registration
sfx->servercount = s_registration_sequence;
return sfx;
}
}
// find a free sfx slot spot
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++)
if( !sfx->name[0] ) break; // free spot
if( i == s_numSfx )
{
if( s_numSfx == MAX_SFX )
return NULL;
s_numSfx++;
}
sfx = &s_knownSfx[i];
memset( sfx, 0, sizeof( *sfx ));
if( pfInCache ) *pfInCache = false;
Q_strncpy( sfx->name, name, MAX_STRING );
sfx->servercount = s_registration_sequence;
sfx->hashValue = COM_HashKey( sfx->name, MAX_SFX_HASH );
// link it in
sfx->hashNext = s_sfxHashList[sfx->hashValue];
s_sfxHashList[sfx->hashValue] = sfx;
return sfx;
}
/*
==================
S_FreeSound
==================
*/
void S_FreeSound( sfx_t *sfx )
{
sfx_t *hashSfx;
sfx_t **prev;
if( !sfx || !sfx->name[0] )
return;
// de-link it from the hash tree
prev = &s_sfxHashList[sfx->hashValue];
while( 1 )
{
hashSfx = *prev;
if( !hashSfx )
break;
if( hashSfx == sfx )
{
*prev = hashSfx->hashNext;
break;
}
prev = &hashSfx->hashNext;
}
if( sfx->cache )
FS_FreeSound( sfx->cache );
memset( sfx, 0, sizeof( *sfx ));
}
/*
=====================
S_BeginRegistration
=====================
*/
void S_BeginRegistration( void )
{
int i;
s_registration_sequence++;
snd_ambient = false;
// check for automatic ambient sounds
for( i = 0; i < NUM_AMBIENTS; i++ )
{
if( !GI->ambientsound[i][0] )
continue; // empty slot
ambient_sfx[i] = S_RegisterSound( GI->ambientsound[i] );
if( ambient_sfx[i] ) snd_ambient = true; // allow auto-ambients
}
s_registering = true;
}
/*
=====================
S_EndRegistration
=====================
*/
void S_EndRegistration( void )
{
sfx_t *sfx;
int i;
if( !s_registering || !dma.initialized )
return;
// free any sounds not from this registration sequence
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
{
if( !sfx->name[0] || !Q_stricmp( sfx->name, "*default" ))
continue; // don't release default sound
if( sfx->servercount != s_registration_sequence )
S_FreeSound( sfx ); // don't need this sound
}
// load everything in
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
{
if( !sfx->name[0] )
continue;
S_LoadSound( sfx );
}
s_registering = false;
}
/*
==================
S_RegisterSound
==================
*/
sound_t S_RegisterSound( const char *name )
{
sfx_t *sfx;
if( !COM_CheckString( name ) || !dma.initialized )
return -1;
if( S_TestSoundChar( name, '!' ))
{
Q_strncpy( s_sentenceImmediateName, name, sizeof( s_sentenceImmediateName ));
return SENTENCE_INDEX;
}
// some stupid mappers used leading '/' or '\' in path to models or sounds
if( name[0] == '/' || name[0] == '\\' ) name++;
if( name[0] == '/' || name[0] == '\\' ) name++;
sfx = S_FindName( name, NULL );
if( !sfx ) return -1;
sfx->servercount = s_registration_sequence;
if( !s_registering ) S_LoadSound( sfx );
return sfx - s_knownSfx;
}
sfx_t *S_GetSfxByHandle( sound_t handle )
{
if( !dma.initialized )
return NULL;
// create new sfx
if( handle == SENTENCE_INDEX )
return S_FindName( s_sentenceImmediateName, NULL );
if( handle < 0 || handle >= s_numSfx )
return NULL;
return &s_knownSfx[handle];
}
/*
=================
S_InitSounds
=================
*/
void S_InitSounds( void )
{
// create unused 0-entry
Q_strncpy( s_knownSfx->name, "*default", MAX_QPATH );
s_knownSfx->hashValue = COM_HashKey( s_knownSfx->name, MAX_SFX_HASH );
s_knownSfx->hashNext = s_sfxHashList[s_knownSfx->hashValue];
s_sfxHashList[s_knownSfx->hashValue] = s_knownSfx;
s_knownSfx->cache = S_CreateDefaultSound();
s_numSfx = 1;
}
/*
=================
S_FreeSounds
=================
*/
void S_FreeSounds( void )
{
sfx_t *sfx;
int i;
if( !dma.initialized )
return;
// stop all sounds
S_StopAllSounds( true );
// free all sounds
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
S_FreeSound( sfx );
memset( s_knownSfx, 0, sizeof( s_knownSfx ));
memset( s_sfxHashList, 0, sizeof( s_sfxHashList ));
s_numSfx = 0;
}