diff options
Diffstat (limited to 'ioq3-r437/src/client/snd_dma.c')
-rw-r--r-- | ioq3-r437/src/client/snd_dma.c | 1493 |
1 files changed, 0 insertions, 1493 deletions
diff --git a/ioq3-r437/src/client/snd_dma.c b/ioq3-r437/src/client/snd_dma.c deleted file mode 100644 index 39777034..00000000 --- a/ioq3-r437/src/client/snd_dma.c +++ /dev/null @@ -1,1493 +0,0 @@ -/* -=========================================================================== -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_Play_f(void); -void S_SoundList_f(void); -void S_Music_f(void); - -void S_Update_( void ); -void S_UpdateBackgroundTrack( 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_khz; -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; -portable_samplepair_t s_rawsamples[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); - 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("0x%x 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" ); -} - -/* -================= -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) { - Com_Error (ERR_FATAL, "S_FindName: NULL\n"); - } - if (!name[0]) { - Com_Error (ERR_FATAL, "S_FindName: empty name\n"); - } - - if (strlen(name) >= MAX_QPATH) { - Com_Error (ERR_FATAL, "Sound name too long: %s", name); - } - - 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; - } - - if ( strlen( name ) >= MAX_QPATH ) { - Com_Printf( "Sound name exceeds MAX_QPATH\n" ); - return 0; - } - - sfx = S_FindName( name ); - 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(); - - s_numSfx = 0; - Com_Memset( s_knownSfx, 0, sizeof( s_knownSfx ) ); - Com_Memset(sfxHash, 0, sizeof(sfx_t *)*LOOP_HASH); - - S_Base_RegisterSound("sound/feedback/hit.wav", qfalse); // changed to a sound in baseq3 - } -} - -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; - - // calculate stereo seperation and distance attenuation - 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 -// ======================================================================= - -/* -==================== -S_StartSound - -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 -==================== -*/ -void S_Base_StartSound(vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfxHandle ) { - channel_t *ch; - sfx_t *sfx; - int i, oldest, chosen, time; - int inplay, allowed; - - if ( !s_soundStarted || s_soundMuted ) { - return; - } - - if ( !origin && ( entityNum < 0 || entityNum > MAX_GENTITIES ) ) { - 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; - } - - ch = s_channels; - inplay = 0; - for ( i = 0; i < MAX_CHANNELS ; i++, ch++ ) { - if (ch[i].entnum == entityNum && ch[i].thesfx == sfx) { - if (time - ch[i].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) { - 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; -} - - -/* -================== -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; - } - - S_Base_StartSound (NULL, listener_number, channelNum, sfxHandle ); -} - - -/* -================== -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(); - - s_rawend = 0; - - if (dma.samplebits == 8) - clear = 0x80; - else - clear = 0; - - SNDDMA_BeginPainting (); - if (dma.buffer) - // TTimo: due to a particular bug workaround in linux sound code, - // have to optionally use a custom C implementation of Com_Memset - // not affecting win32, we have #define Snd_Memset Com_Memset - // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371 - Snd_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)) { - loopSounds[i].kill = qfalse; - 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; - 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] ); - } -} - -portable_samplepair_t *S_GetRawSamplePointer( void ) { - return s_rawsamples; -} - -/* -============ -S_RawSamples - -Music streaming -============ -*/ -void S_Base_RawSamples( int samples, int rate, int width, int s_channels, const byte *data, float volume ) { - int i; - int src, dst; - float scale; - int intVolume; - - if ( !s_soundStarted || s_soundMuted ) { - return; - } - - intVolume = 256 * volume; - - if ( s_rawend < s_soundtime ) { - Com_DPrintf( "S_RawSamples: resetting minimum: %i < %i\n", s_rawend, s_soundtime ); - s_rawend = s_soundtime; - } - - scale = (float)rate / dma.speed; - -//Com_Printf ("%i < %i < %i\n", s_soundtime, s_paintedtime, s_rawend); - if (s_channels == 2 && width == 2) - { - if (scale == 1.0) - { // optimized case - for (i=0 ; i<samples ; i++) - { - dst = s_rawend&(MAX_RAW_SAMPLES-1); - s_rawend++; - s_rawsamples[dst].left = ((short *)data)[i*2] * intVolume; - s_rawsamples[dst].right = ((short *)data)[i*2+1] * intVolume; - } - } - else - { - for (i=0 ; ; i++) - { - src = i*scale; - if (src >= samples) - break; - dst = s_rawend&(MAX_RAW_SAMPLES-1); - s_rawend++; - s_rawsamples[dst].left = ((short *)data)[src*2] * intVolume; - s_rawsamples[dst].right = ((short *)data)[src*2+1] * intVolume; - } - } - } - else if (s_channels == 1 && width == 2) - { - for (i=0 ; ; i++) - { - src = i*scale; - if (src >= samples) - break; - dst = s_rawend&(MAX_RAW_SAMPLES-1); - s_rawend++; - s_rawsamples[dst].left = ((short *)data)[src] * intVolume; - s_rawsamples[dst].right = ((short *)data)[src] * intVolume; - } - } - else if (s_channels == 2 && width == 1) - { - intVolume *= 256; - - for (i=0 ; ; i++) - { - src = i*scale; - if (src >= samples) - break; - dst = s_rawend&(MAX_RAW_SAMPLES-1); - s_rawend++; - s_rawsamples[dst].left = ((char *)data)[src*2] * intVolume; - s_rawsamples[dst].right = ((char *)data)[src*2+1] * intVolume; - } - } - else if (s_channels == 1 && width == 1) - { - intVolume *= 256; - - for (i=0 ; ; i++) - { - src = i*scale; - if (src >= samples) - break; - dst = s_rawend&(MAX_RAW_SAMPLES-1); - s_rawend++; - s_rawsamples[dst].left = (((byte *)data)[src]-128) * intVolume; - s_rawsamples[dst].right = (((byte *)data)[src]-128) * intVolume; - } - } - - if ( s_rawend > s_soundtime + MAX_RAW_SAMPLES ) { - Com_DPrintf( "S_RawSamples: overflowed %i > %i\n", s_rawend, s_soundtime ); - } -} - -//============================================================================= - -/* -===================== -S_UpdateEntityPosition - -let the sound system know where an entity currently is -====================== -*/ -void S_Base_UpdateEntityPosition( int entityNum, const vec3_t origin ) { - if ( entityNum < 0 || entityNum > MAX_GENTITIES ) { - 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; - } - // anything coming from the view entity will always be full volume - if (ch->entnum == listener_number) { - 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 ("%f %f %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; - - // 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; -} - -/* -====================== -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[0] ) { - return; - } - - if( !loop ) { - s_backgroundLoop[0] = 0; - } else { - Q_strncpyz( s_backgroundLoop, loop, sizeof( s_backgroundLoop ) ); - } - - // 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(intro); - if(!s_backgroundStream) { - Com_Printf( S_COLOR_YELLOW "WARNING: couldn't open music file %s\n", intro ); - 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", intro ); - } -} - -/* -====================== -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; - static float musicVolume = 0.5f; - - if(!s_backgroundStream) { - return; - } - - // graeme see if this is OK - musicVolume = (musicVolume + (s_musicVolume->value * 2))/4.0f; - - // don't bother playing anything if musicvolume is 0 - if ( musicVolume <= 0 ) { - return; - } - - // see how many samples should be copied into the raw buffer - if ( s_rawend < s_soundtime ) { - s_rawend = s_soundtime; - } - - while ( s_rawend < s_soundtime + MAX_RAW_SAMPLES ) { - bufferSamples = MAX_RAW_SAMPLES - (s_rawend - s_soundtime); - - // decide how much data needs to be read from the file - fileSamples = bufferSamples * s_backgroundStream->info.rate / dma.speed; - - // 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) - { - fileBytes = r; - fileSamples = r / (s_backgroundStream->info.width * s_backgroundStream->info.channels); - } - - if(r > 0) - { - // add to raw buffer - S_Base_RawSamples( fileSamples, s_backgroundStream->info.rate, - s_backgroundStream->info.width, s_backgroundStream->info.channels, raw, musicVolume ); - } - else - { - // loop - if(s_backgroundLoop[0]) - { - S_CodecCloseStream(s_backgroundStream); - s_backgroundStream = NULL; - S_Base_StartBackgroundTrack( s_backgroundLoop, s_backgroundLoop ); - 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(); - - s_soundStarted = 0; - - Cmd_RemoveCommand("s_info"); -} - -/* -================ -S_Init -================ -*/ -qboolean S_Base_Init( soundInterface_t *si ) { - qboolean r; - - if( !si ) { - return qfalse; - } - - s_khz = Cvar_Get ("s_khz", "22", CVAR_ARCHIVE); - 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; - - return qtrue; -} |