diff --git a/engine/client/s_main.c b/engine/client/s_main.c index 9f569d28..474262ac 100644 --- a/engine/client/s_main.c +++ b/engine/client/s_main.c @@ -1605,7 +1605,6 @@ void SND_UpdateSound( void ) // release raw-channels that no longer used more than 10 secs S_FreeIdleRawChannels(); - VectorCopy( cl.simvel, s_listener.velocity ); s_listener.frametime = (cl.time - cl.oldtime); s_listener.waterlevel = cl.local.waterlevel; s_listener.active = CL_IsInGame(); diff --git a/engine/client/s_mix.c b/engine/client/s_mix.c index 19f5d26a..fc41b6ba 100644 --- a/engine/client/s_mix.c +++ b/engine/client/s_mix.c @@ -17,30 +17,56 @@ GNU General Public License for more details. #include "sound.h" #include "client.h" -#define IPAINTBUFFER 0 -#define IROOMBUFFER 1 -#define ISTREAMBUFFER 2 +enum +{ + IPAINTBUFFER = 0, + IROOMBUFFER, + ISTREAMBUFFER, + CPAINTBUFFERS, +}; -#define FILTERTYPE_NONE 0 -#define FILTERTYPE_LINEAR 1 -#define FILTERTYPE_CUBIC 2 +enum +{ + FILTERTYPE_NONE = 0, + FILTERTYPE_LINEAR, + FILTERTYPE_CUBIC, +}; #define CCHANVOLUMES 2 -#define SND_SCALE_BITS 7 -#define SND_SCALE_SHIFT (8 - SND_SCALE_BITS) -#define SND_SCALE_LEVELS (1 << SND_SCALE_BITS) +#define SND_SCALE_BITS 7 +#define SND_SCALE_SHIFT ( 8 - SND_SCALE_BITS ) +#define SND_SCALE_LEVELS ( 1 << SND_SCALE_BITS ) -portable_samplepair_t *g_curpaintbuffer; -portable_samplepair_t streambuffer[(PAINTBUFFER_SIZE+1)]; -portable_samplepair_t paintbuffer[(PAINTBUFFER_SIZE+1)]; -portable_samplepair_t roombuffer[(PAINTBUFFER_SIZE+1)]; -portable_samplepair_t facingbuffer[(PAINTBUFFER_SIZE+1)]; -portable_samplepair_t temppaintbuffer[(PAINTBUFFER_SIZE+1)]; -paintbuffer_t paintbuffers[CPAINTBUFFERS]; +// sound mixing buffer +#define CPAINTFILTERMEM 3 +#define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer -int snd_scaletable[SND_SCALE_LEVELS][256]; +// fixed point stuff for real-time resampling +#define FIX_BITS 28 +#define FIX_SCALE ( 1 << FIX_BITS ) +#define FIX_MASK (( 1 << FIX_BITS ) - 1 ) +#define FIX_FLOAT( a ) ((int)(( a ) * FIX_SCALE )) +#define FIX( a ) (((int)( a )) << FIX_BITS ) +#define FIX_INTPART( a ) (((int)( a )) >> FIX_BITS ) +#define FIX_FRACPART( a ) (( a ) & FIX_MASK ) +typedef struct +{ + qboolean factive; // if true, mix to this paintbuffer using flags + portable_samplepair_t *pbuf; // front stereo mix buffer, for 2 or 4 channel mixing + int ifilter; // current filter memory buffer to use for upsampling pass + portable_samplepair_t fltmem[CPAINTFILTERS][CPAINTFILTERMEM]; +} paintbuffer_t; + +static portable_samplepair_t *g_curpaintbuffer; +static portable_samplepair_t streambuffer[(PAINTBUFFER_SIZE+1)]; +static portable_samplepair_t paintbuffer[(PAINTBUFFER_SIZE+1)]; +static portable_samplepair_t roombuffer[(PAINTBUFFER_SIZE+1)]; +static portable_samplepair_t temppaintbuffer[(PAINTBUFFER_SIZE+1)]; +static paintbuffer_t paintbuffers[CPAINTBUFFERS]; + +static int snd_scaletable[SND_SCALE_LEVELS][256]; void S_InitScaletable( void ) { int i, j; @@ -67,7 +93,7 @@ static void S_TransferPaintBuffer( int endtime ) dword *pbuf; pbuf = (dword *)dma.buffer; - snd_p = (int *)PAINTBUFFER; + snd_p = (int *)g_curpaintbuffer; lpaintedtime = paintedtime; sampleMask = ((dma.samples >> 1) - 1); @@ -568,6 +594,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate // Don't mix sound data for sounds with zero volume. If it's a non-looping sound, // just remove the sound when its volume goes to zero. + bZeroVolume = !ch->leftvol && !ch->rightvol; if( !bZeroVolume ) @@ -839,6 +866,14 @@ static void MIX_MixPaintbuffers( int ibuf1, int ibuf2, int ibuf3, int count, flo pbuf2 = paintbuffers[ibuf2].pbuf; pbuf3 = paintbuffers[ibuf3].pbuf; + if( !gain ) + { + // do not mix buf2 into buf3, just copy + if( pbuf1 != pbuf3 ) + memcpy( pbuf3, pbuf1, sizeof( *pbuf1 ) * count ); + return; + } + // destination buffer stereo - average n chans down to stereo // destination 2ch: diff --git a/engine/client/sound.h b/engine/client/sound.h index 06bcc0d4..dd41329c 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -21,205 +21,170 @@ extern poolhandle_t sndpool; #include "xash3d_mathlib.h" // sound engine rate defines -#define SOUND_DMA_SPEED 44100 // hardware playback rate -#define SOUND_11k 11025 // 11khz sample rate -#define SOUND_16k 16000 // 16khz sample rate -#define SOUND_22k 22050 // 22khz sample rate -#define SOUND_32k 32000 // 32khz sample rate -#define SOUND_44k 44100 // 44khz sample rate -#define DMA_MSEC_PER_SAMPLE ((float)(1000.0 / SOUND_DMA_SPEED)) - -// fixed point stuff for real-time resampling -#define FIX_BITS 28 -#define FIX_SCALE (1 << FIX_BITS) -#define FIX_MASK ((1 << FIX_BITS)-1) -#define FIX_FLOAT(a) ((int)((a) * FIX_SCALE)) -#define FIX(a) (((int)(a)) << FIX_BITS) -#define FIX_INTPART(a) (((int)(a)) >> FIX_BITS) -#define FIX_FRACTION(a,b) (FIX(a)/(b)) -#define FIX_FRACPART(a) ((a) & FIX_MASK) +#define SOUND_11k 11025 // 11khz sample rate +#define SOUND_16k 16000 // 16khz sample rate +#define SOUND_22k 22050 // 22khz sample rate +#define SOUND_32k 32000 // 32khz sample rate +#define SOUND_44k 44100 // 44khz sample rate +#define SOUND_DMA_SPEED SOUND_44k // hardware playback rate // NOTE: clipped sound at 32760 to avoid overload -#define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x ))) +#define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x ))) -#define PAINTBUFFER_SIZE 1024 // 44k: was 512 -#define PAINTBUFFER (g_curpaintbuffer) -#define CPAINTBUFFERS 3 +#define PAINTBUFFER_SIZE 1024 // 44k: was 512 -// sound mixing buffer -#define CPAINTFILTERMEM 3 -#define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer - -#define S_RAW_SOUND_IDLE_SEC 10 // time interval for idling raw sound before it's freed -#define S_RAW_SOUND_BACKGROUNDTRACK -2 -#define S_RAW_SOUND_SOUNDTRACK -1 -#define S_RAW_SAMPLES_PRECISION_BITS 14 - -#define CIN_FRAMETIME (1.0f / 30.0f) +#define S_RAW_SOUND_IDLE_SEC 10 // time interval for idling raw sound before it's freed +#define S_RAW_SOUND_BACKGROUNDTRACK -2 +#define S_RAW_SOUND_SOUNDTRACK -1 +#define S_RAW_SAMPLES_PRECISION_BITS 14 typedef struct { - int left; - int right; + int left; + int right; } portable_samplepair_t; -typedef struct -{ - qboolean factive; // if true, mix to this paintbuffer using flags - portable_samplepair_t *pbuf; // front stereo mix buffer, for 2 or 4 channel mixing - int ifilter; // current filter memory buffer to use for upsampling pass - portable_samplepair_t fltmem[CPAINTFILTERS][CPAINTFILTERMEM]; -} paintbuffer_t; - typedef struct sfx_s { - char name[MAX_QPATH]; - wavdata_t *cache; + char name[MAX_QPATH]; + wavdata_t *cache; - int servercount; - uint hashValue; - struct sfx_s *hashNext; + int servercount; + uint hashValue; + struct sfx_s *hashNext; } sfx_t; -extern portable_samplepair_t paintbuffer[]; -extern portable_samplepair_t roombuffer[]; -extern portable_samplepair_t temppaintbuffer[]; -extern portable_samplepair_t *g_curpaintbuffer; -extern paintbuffer_t paintbuffers[]; - // structure used for fading in and out client sound volume. typedef struct { - float initial_percent; - float percent; // how far to adjust client's volume down by. - float starttime; // GetHostTime() when we started adjusting volume - float fadeouttime; // # of seconds to get to faded out state - float holdtime; // # of seconds to hold - float fadeintime; // # of seconds to restore + float initial_percent; + float percent; // how far to adjust client's volume down by. + float starttime; // GetHostTime() when we started adjusting volume + float fadeouttime; // # of seconds to get to faded out state + float holdtime; // # of seconds to hold + float fadeintime; // # of seconds to restore } soundfade_t; typedef struct { - float percent; + float percent; } musicfade_t; typedef struct snd_format_s { - unsigned int speed; - unsigned int width; - unsigned int channels; + uint speed; + byte width; + byte channels; } snd_format_t; typedef struct { - snd_format_t format; - int samples; // mono samples in buffer - int samplepos; // in mono samples - byte *buffer; - qboolean initialized; // sound engine is active - const char *backendName; + snd_format_t format; + int samples; // mono samples in buffer + int samplepos; // in mono samples + qboolean initialized; // sound engine is active + byte *buffer; + const char *backendName; } dma_t; #include "vox.h" typedef struct { - double sample; - - wavdata_t *pData; - double forcedEndSample; - qboolean finished; + double sample; + wavdata_t *pData; + double forcedEndSample; + qboolean finished; } mixer_t; typedef struct rawchan_s { - int entnum; - int master_vol; - int leftvol; // 0-255 left volume - int rightvol; // 0-255 right volume - float dist_mult; // distance multiplier (attenuation/clipK) - vec3_t origin; // only use if fixed_origin is set - volatile uint s_rawend; - wavdata_t sound_info; // advance play position - float oldtime; // catch time jumps - size_t max_samples; // buffer length - portable_samplepair_t rawsamples[1]; // variable sized + int entnum; + int master_vol; + int leftvol; // 0-255 left volume + int rightvol; // 0-255 right volume + float dist_mult; // distance multiplier (attenuation/clipK) + vec3_t origin; // only use if fixed_origin is set + volatile uint s_rawend; + float oldtime; // catch time jumps + wavdata_t sound_info; // advance play position + size_t max_samples; // buffer length + portable_samplepair_t rawsamples[1]; // variable sized } rawchan_t; typedef struct channel_s { - char name[16]; // keept sentence name - sfx_t *sfx; // sfx number + char name[16]; // keep sentence name + sfx_t *sfx; // sfx number - int leftvol; // 0-255 left volume - int rightvol; // 0-255 right volume + int leftvol; // 0-255 left volume + int rightvol; // 0-255 right volume - int entnum; // entity soundsource - int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.) - vec3_t origin; // only use if fixed_origin is set - float dist_mult; // distance multiplier (attenuation/clipK) - int master_vol; // 0-255 master volume - qboolean isSentence; // bit who indicated sentence - int basePitch; // base pitch percent (100% is normal pitch playback) - float pitch; // real-time pitch after any modulation or shift by dynamic data - qboolean use_loop; // don't loop default and local sounds - qboolean staticsound; // use origin instead of fetching entnum's origin - qboolean localsound; // it's a local menu sound (not looped, not paused) - mixer_t pMixer; + int entnum; // entity soundsource + int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.) + vec3_t origin; // only use if fixed_origin is set + float dist_mult; // distance multiplier (attenuation/clipK) + int master_vol; // 0-255 master volume + int basePitch; // base pitch percent (100% is normal pitch playback) + float pitch; // real-time pitch after any modulation or shift by dynamic data + qboolean use_loop; // don't loop default and local sounds + qboolean staticsound; // use origin instead of fetching entnum's origin + qboolean localsound; // it's a local menu sound (not looped, not paused) + mixer_t pMixer; // sentence mixer - int wordIndex; - mixer_t *currentWord; // NULL if sentence is finished - voxword_t words[CVOXWORDMAX]; + qboolean isSentence; // bit indicating sentence + int wordIndex; + mixer_t *currentWord; // NULL if sentence is finished + voxword_t words[CVOXWORDMAX]; } channel_t; typedef struct { - vec3_t origin; // simorg + view_ofs - vec3_t velocity; - vec3_t forward; - vec3_t right; - vec3_t up; + vec3_t origin; // simorg + view_ofs + vec3_t forward; + vec3_t right; + vec3_t up; - int entnum; - int waterlevel; - float frametime; // used for sound fade - qboolean active; - qboolean inmenu; // listener in-menu ? - qboolean paused; - qboolean streaming; // playing AVI-file - qboolean stream_paused; // pause only background track + int entnum; + int waterlevel; + float frametime; // used for sound fade + qboolean active; + qboolean inmenu; // listener in-menu ? + qboolean paused; + qboolean streaming; // playing AVI-file + qboolean stream_paused; // pause only background track } listener_t; typedef struct { - string current; // a currently playing track - string loopName; // may be empty - stream_t *stream; - int source; // may be game, menu, etc + string current; // a currently playing track + string loopName; // may be empty + stream_t *stream; + int source; // may be game, menu, etc } bg_track_t; //==================================================================== -#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS) -#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp -#define MAX_RAW_CHANNELS 48 -#define MAX_RAW_SAMPLES 8192 +#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS) +#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp +#define MAX_RAW_CHANNELS 48 +#define MAX_RAW_SAMPLES 8192 -extern sound_t ambient_sfx[NUM_AMBIENTS]; -extern qboolean snd_ambient; -extern channel_t channels[MAX_CHANNELS]; -extern rawchan_t *raw_channels[MAX_RAW_CHANNELS]; -extern int total_channels; -extern int paintedtime; -extern int soundtime; -extern listener_t s_listener; -extern int idsp_room; -extern dma_t dma; +extern sound_t ambient_sfx[NUM_AMBIENTS]; +extern qboolean snd_ambient; +extern channel_t channels[MAX_CHANNELS]; +extern rawchan_t *raw_channels[MAX_RAW_CHANNELS]; +extern int total_channels; +extern int paintedtime; +extern int soundtime; +extern listener_t s_listener; +extern int idsp_room; +extern dma_t dma; -extern convar_t s_musicvolume; -extern convar_t s_lerping; -extern convar_t s_test; // cvar to testify new effects +extern convar_t s_musicvolume; +extern convar_t s_lerping; +extern convar_t s_test; // cvar to test new effects extern convar_t s_samplecount; extern convar_t s_warn_late_precache; diff --git a/engine/client/vox.h b/engine/client/vox.h index e9966714..7432801a 100644 --- a/engine/client/vox.h +++ b/engine/client/vox.h @@ -16,21 +16,20 @@ GNU General Public License for more details. #ifndef VOX_H #define VOX_H -#define CVOXWORDMAX 64 - -#define SENTENCE_INDEX -99999 // unique sentence index +#define CVOXWORDMAX 64 +#define SENTENCE_INDEX -99999 // unique sentence index typedef struct voxword_s { - int volume; // increase percent, ie: 125 = 125% increase - int pitch; // pitch shift up percent - int start; // offset start of wave percent - int end; // offset end of wave percent - int cbtrim; // end of wave after being trimmed to 'end' - int fKeepCached; // 1 if this word was already in cache before sentence referenced it - int samplefrac; // if pitch shifting, this is position into wav * 256 - int timecompress; // % of wave to skip during playback (causes no pitch shift) - sfx_t *sfx; // name and cache pointer + int volume; // increase percent, ie: 125 = 125% increase + int pitch; // pitch shift up percent + int start; // offset start of wave percent + int end; // offset end of wave percent + int cbtrim; // end of wave after being trimmed to 'end' + int fKeepCached; // 1 if this word was already in cache before sentence referenced it + int samplefrac; // if pitch shifting, this is position into wav * 256 + int timecompress; // % of wave to skip during playback (causes no pitch shift) + sfx_t *sfx; // name and cache pointer } voxword_t; struct channel_s;