mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
most of the hacking needed to break out the common code from snd_dma.c
This commit is contained in:
parent
0105754f6f
commit
cde6e60848
16 changed files with 176 additions and 679 deletions
27
configure.ac
27
configure.ac
|
@ -1032,6 +1032,30 @@ fi
|
|||
AC_SUBST(ALSA_LIBS)
|
||||
AC_SUBST(HAVE_ALSA)
|
||||
|
||||
AC_ARG_ENABLE(jack,
|
||||
[ --disable-jack disable jack support],
|
||||
)
|
||||
HAVE_JACK=no
|
||||
JACK_LIBS=""
|
||||
if test "x$enable_jack" != "xno"; then
|
||||
if test "x$PKG_CONFIG" != "x"; then
|
||||
PKG_CHECK_MODULES([JACK], [jack], HAVE_JACK=yes, HAVE_JACK=no)
|
||||
SOUND_TYPES="$SOUND_TYPES JACK"
|
||||
else
|
||||
AC_CHECK_LIB(jack, jack_client_open, HAVE_JACK=yes, HAVE_JACK=no,
|
||||
[$LIBS])
|
||||
if test "x$HAVE_JACK" = "xyes"; then
|
||||
AC_CHECK_HEADER(jack/jack.h, HAVE_JACK=yes, HAVE_JACK=no)
|
||||
if test "x$HAVE_JACK" = "xyes"; then
|
||||
JACK_LIBS="-ljack"
|
||||
AC_DEFINE(HAVE_JACK, 1, [Define if you have libjack])
|
||||
SOUND_TYPES="$SOUND_TYPES JACK"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(JACK_LIBS)
|
||||
|
||||
SOUND_TYPES="$SOUND_TYPES DISK"
|
||||
|
||||
dnl MME
|
||||
|
@ -2015,6 +2039,9 @@ if test -n "$CL_TARGETS"; then
|
|||
fi
|
||||
if test "$SOUND_TYPES"; then
|
||||
SND_REND_TARGETS="$SND_REND_TARGETS snd_render_default.la"
|
||||
if test "`echo $SOUND_TYPES | grep JACK`"; then
|
||||
SND_REND_TARGETS="$SND_REND_TARGETS snd_render_jack.la"
|
||||
fi
|
||||
fi
|
||||
|
||||
# priority sorted list for default sound driver in order of increasing
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#define __QF_plugin_cd_h_
|
||||
|
||||
#include <QF/qtypes.h>
|
||||
#include <QF/plugin.h>
|
||||
|
||||
/*
|
||||
All CDAudio plugins must export these functions
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
#include <QF/keys.h>
|
||||
#include <QF/qtypes.h>
|
||||
#include <QF/plugin.h>
|
||||
|
||||
typedef void (*P_C_Print) (const char *fmt, va_list args);
|
||||
typedef void (*P_C_ProcessInput) (void);
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#define __QF_plugin_general_h_
|
||||
|
||||
#include <QF/qtypes.h>
|
||||
#include <QF/plugin.h>
|
||||
|
||||
/*
|
||||
All plugins, of all types, must export these functions
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#define __QF_plugin_input_h_
|
||||
|
||||
#include <QF/qtypes.h>
|
||||
#include <QF/plugin.h>
|
||||
|
||||
/*
|
||||
All input plugins must export these functions
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#define __QF_plugin_snd_output_h_
|
||||
|
||||
#include <QF/qtypes.h>
|
||||
#include <QF/plugin.h>
|
||||
|
||||
/*
|
||||
All sound plugins must export these functions
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#define __QF_plugin_snd_render_h_
|
||||
|
||||
#include <QF/qtypes.h>
|
||||
#include <QF/plugin.h>
|
||||
|
||||
/*
|
||||
All sound plugins must export these functions
|
||||
|
@ -47,7 +46,7 @@ typedef void (*P_S_StaticSound) (struct sfx_s *sfx, const vec3_t origin, float v
|
|||
typedef void (*P_S_StopSound) (int entnum, int entchannel);
|
||||
typedef struct sfx_s * (*P_S_PrecacheSound) (const char *sample);
|
||||
typedef void (*P_S_Update) (const vec3_t origin, const vec3_t v_forward, const vec3_t v_right, const vec3_t v_up);
|
||||
typedef void (*P_S_StopAllSounds) (qboolean clear);
|
||||
typedef void (*P_S_StopAllSounds) (void);
|
||||
typedef void (*P_S_ExtraUpdate) (void);
|
||||
typedef void (*P_S_LocalSound) (const char *s);
|
||||
typedef void (*P_S_BlockSound) (void);
|
||||
|
|
|
@ -119,10 +119,8 @@ void S_StaticSound (sfx_t *sfx, const vec3_t origin, float vol,
|
|||
void S_StopSound (int entnum, int entchannel);
|
||||
|
||||
/** Stop all sounds from playing.
|
||||
\param clear if true, the buffer is cleared so sound stops immediately
|
||||
rather than trailing off
|
||||
*/
|
||||
void S_StopAllSounds(qboolean clear);
|
||||
void S_StopAllSounds(void);
|
||||
|
||||
/** Update the sound engine with the client's position and orientation and
|
||||
render some sound.
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
*/
|
||||
//@{
|
||||
|
||||
#include "QF/plugin/snd_render.h"
|
||||
#include "QF/quakeio.h"
|
||||
#include "QF/sound.h"
|
||||
#include "QF/zone.h"
|
||||
|
||||
|
@ -184,6 +186,34 @@ extern struct cvar_s *snd_stereo_phase_separation;
|
|||
|
||||
extern volatile dma_t *snd_shm;
|
||||
|
||||
extern snd_render_data_t snd_render_data;
|
||||
|
||||
//@}
|
||||
|
||||
/** \defgroup sound_render_sfx Sound sfx
|
||||
\ingroup sound_render_mix
|
||||
*/
|
||||
//@{
|
||||
/** Pre-load a sound into the cache.
|
||||
\param sample name of sound to precache
|
||||
*/
|
||||
sfx_t *SND_PrecacheSound (const char *sample);
|
||||
|
||||
/** Tag a cached sound to prevent it being flushed unnecessarily.
|
||||
\param sample name of sound touch
|
||||
\todo check that Cache_TryGet() does the right thing
|
||||
*/
|
||||
void SND_TouchSound (const char *sample);
|
||||
|
||||
/** Pre-load a sound.
|
||||
\param name name of sound to load
|
||||
*/
|
||||
sfx_t *SND_LoadSound (const char *name);
|
||||
|
||||
/** Initialize the sfx sub-subsystem
|
||||
*/
|
||||
void SND_SFX_Init (void);
|
||||
|
||||
//@}
|
||||
|
||||
/** \defgroup sound_render_mix_channels Sound channels
|
||||
|
@ -202,6 +232,78 @@ extern volatile dma_t *snd_shm;
|
|||
#define MAX_DYNAMIC_CHANNELS 8 //!< number of dynamic channels
|
||||
extern channel_t snd_channels[MAX_CHANNELS]; //!< pool of available channels
|
||||
extern int snd_total_channels; //!< number of active channels
|
||||
|
||||
/** Allocate a sound channel that can be used for playing sounds.
|
||||
*/
|
||||
struct channel_s *SND_AllocChannel (void);
|
||||
|
||||
/** Stop a channel from playing.
|
||||
\param chan the channel to stop
|
||||
*/
|
||||
void SND_ChannelStop (channel_t *chan);
|
||||
|
||||
/** Disable ambient sounds.
|
||||
\todo not used, remove?
|
||||
*/
|
||||
void SND_AmbientOff (void);
|
||||
|
||||
/** Enable ambient sounds.
|
||||
\todo not used, remove?
|
||||
*/
|
||||
void SND_AmbientOn (void);
|
||||
|
||||
/** Update the sound engine with the client's position and orientation and
|
||||
render some sound.
|
||||
\param origin 3d coords of the client
|
||||
\param v_forward 3d vector of the client's facing direction
|
||||
\param v_right 3d vector of the client's rightward direction
|
||||
\param v_up 3d vector of the client's upward direction
|
||||
*/
|
||||
void SND_SetListener (const vec3_t origin, const vec3_t v_forward,
|
||||
const vec3_t v_right, const vec3_t v_up);
|
||||
|
||||
/** Stop all sounds from playing.
|
||||
*/
|
||||
void SND_StopAllSounds(void);
|
||||
|
||||
/** Initialize the channels sub-subsystem
|
||||
*/
|
||||
void SND_Channels_Init (void);
|
||||
|
||||
/** Start a sound playing.
|
||||
\param entnum index of entity the sound is associated with.
|
||||
\param entchannel 0-7
|
||||
- 0 auto (never willingly overrides)
|
||||
- 1 weapon
|
||||
- 2 voice
|
||||
- 3 item
|
||||
- 4 body
|
||||
\param sfx sound to play
|
||||
\param origin 3d coords of where the sound originates
|
||||
\param fvol absolute volume of the sound
|
||||
\param attenuation rate of volume dropoff vs distance
|
||||
*/
|
||||
void SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
|
||||
float fvol, float attenuation);
|
||||
|
||||
/** Create a sound generated by the world.
|
||||
\param sfx sound to play
|
||||
\param origin 3d coords of where the sound originates
|
||||
\param vol absolute volume of the sound
|
||||
\param attenuation rate of volume dropoff vs distance
|
||||
*/
|
||||
void SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol,
|
||||
float attenuation);
|
||||
/** Stop an entity's sound.
|
||||
\param entnum index of entity the sound is associated with.
|
||||
\param entchannel channel to silence
|
||||
*/
|
||||
void SND_StopSound (int entnum, int entchannel);
|
||||
|
||||
/** Start a sound local to the client view.
|
||||
\param s name of sound to play
|
||||
*/
|
||||
void SND_LocalSound (const char *s);
|
||||
//@}
|
||||
|
||||
|
||||
|
|
|
@ -8,12 +8,18 @@ plugin_libadd= @plugin_libadd@
|
|||
EXEEXT=
|
||||
|
||||
plugin_LTLIBRARIES= @SND_REND_TARGETS@
|
||||
EXTRA_LTLIBRARIES= snd_render_default.la
|
||||
EXTRA_LTLIBRARIES= snd_render_default.la snd_render_jack.la
|
||||
|
||||
noinst_LTLIBRARIES= @SND_REND_STATIC@
|
||||
|
||||
snd_render_default_la_LDFLAGS= $(plugin_ldflags)
|
||||
snd_render_default_la_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_resample.c \
|
||||
snd_render_default_la_SOURCES= \
|
||||
snd_channels.c snd_dma.c snd_mem.c snd_mix.c snd_resample.c snd_sfx.c \
|
||||
flac.c vorbis.c wav.c midi.c
|
||||
snd_render_default_la_LIBADD= $(VORBISFILE_LIBS) $(VORBIS_LIBS) $(LIBFLAC_LIBS) $(OGG_LIBS) $(WM_LIBS)
|
||||
snd_render_default_la_DEPENDENCIES=
|
||||
|
||||
snd_render_jack_la_LDFLAGS= $(plugin_ldflags)
|
||||
snd_render_jack_la_SOURCES= snd_channels.c snd_jack.c snd_sfx.c
|
||||
snd_render_jack_la_LIBADD= $(VORBISFILE_LIBS) $(VORBIS_LIBS) $(LIBFLAC_LIBS) $(OGG_LIBS) $(WM_LIBS)
|
||||
snd_render_jack_la_DEPENDENCIES=
|
||||
|
|
|
@ -62,47 +62,21 @@ cvar_t *snd_loadas8bit;
|
|||
cvar_t *snd_volume;
|
||||
cvar_t *snd_interp;
|
||||
|
||||
channel_t snd_channels[MAX_CHANNELS];
|
||||
int snd_total_channels;
|
||||
|
||||
static channel_t *ambient_channels[NUM_AMBIENTS];
|
||||
static channel_t *dynamic_channels[MAX_DYNAMIC_CHANNELS];
|
||||
static channel_t *static_channels[MAX_CHANNELS];
|
||||
static int num_statics;
|
||||
|
||||
static qboolean snd_initialized = false;
|
||||
static int snd_blocked = 0;
|
||||
static qboolean snd_ambient = 1;
|
||||
|
||||
static vec3_t listener_origin;
|
||||
static vec3_t listener_forward;
|
||||
static vec3_t listener_right;
|
||||
static vec3_t listener_up;
|
||||
static vec_t sound_nominal_clip_dist = 1000.0;
|
||||
|
||||
static unsigned soundtime; // sample PAIRS
|
||||
|
||||
#define MAX_SFX 512
|
||||
static sfx_t *known_sfx; // hunk allocated [MAX_SFX]
|
||||
static int num_sfx;
|
||||
|
||||
static sfx_t *ambient_sfx[NUM_AMBIENTS];
|
||||
|
||||
static int sound_started = 0;
|
||||
|
||||
|
||||
static cvar_t *ambient_fade;
|
||||
static cvar_t *ambient_level;
|
||||
static cvar_t *nosound;
|
||||
static cvar_t *precache;
|
||||
static cvar_t *snd_mixahead;
|
||||
static cvar_t *snd_noextraupdate;
|
||||
static cvar_t *snd_phasesep;
|
||||
static cvar_t *snd_show;
|
||||
static cvar_t *snd_volumesep;
|
||||
|
||||
static general_data_t plugin_info_general_data;
|
||||
static snd_render_data_t render_data = {
|
||||
snd_render_data_t snd_render_data = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
@ -114,273 +88,9 @@ static snd_render_data_t render_data = {
|
|||
static snd_output_funcs_t *snd_output_funcs;
|
||||
|
||||
|
||||
// User-setable variables =====================================================
|
||||
|
||||
static void
|
||||
s_ambient_off (void)
|
||||
{
|
||||
snd_ambient = false;
|
||||
}
|
||||
|
||||
static void
|
||||
s_ambient_on (void)
|
||||
{
|
||||
snd_ambient = true;
|
||||
}
|
||||
|
||||
// Load a sound ===============================================================
|
||||
static sfx_t *
|
||||
s_load_sound (const char *name)
|
||||
{
|
||||
int i;
|
||||
sfx_t *sfx;
|
||||
|
||||
if (!known_sfx)
|
||||
return 0;
|
||||
|
||||
// see if already loaded
|
||||
for (i = 0; i < num_sfx; i++)
|
||||
if (known_sfx[i].name && !strcmp (known_sfx[i].name, name)) {
|
||||
return &known_sfx[i];
|
||||
}
|
||||
|
||||
if (num_sfx == MAX_SFX)
|
||||
Sys_Error ("S_FindName: out of sfx_t");
|
||||
|
||||
sfx = &known_sfx[i];
|
||||
if (sfx->name)
|
||||
free ((char *) sfx->name);
|
||||
sfx->name = strdup (name);
|
||||
SND_Load (sfx);
|
||||
|
||||
num_sfx++;
|
||||
|
||||
return sfx;
|
||||
}
|
||||
|
||||
static void
|
||||
s_touch_sound (const char *name)
|
||||
{
|
||||
sfx_t *sfx;
|
||||
|
||||
if (!sound_started)
|
||||
return;
|
||||
|
||||
if (!name)
|
||||
Sys_Error ("s_touch_sound: NULL");
|
||||
|
||||
name = va ("sound/%s", name);
|
||||
sfx = s_load_sound (name);
|
||||
sfx->touch (sfx);
|
||||
}
|
||||
|
||||
static sfx_t *
|
||||
s_precache_sound (const char *name)
|
||||
{
|
||||
sfx_t *sfx;
|
||||
|
||||
if (!sound_started || nosound->int_val)
|
||||
return NULL;
|
||||
|
||||
if (!name)
|
||||
Sys_Error ("s_precache_sound: NULL");
|
||||
|
||||
name = va ("sound/%s", name);
|
||||
sfx = s_load_sound (name);
|
||||
|
||||
// cache it in
|
||||
if (precache->int_val) {
|
||||
if (sfx->retain (sfx))
|
||||
sfx->release (sfx);
|
||||
}
|
||||
return sfx;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
static channel_t *
|
||||
s_alloc_channel (void)
|
||||
{
|
||||
if (snd_total_channels < MAX_CHANNELS)
|
||||
return &snd_channels[snd_total_channels++];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static channel_t *
|
||||
s_pick_channel (int entnum, int entchannel)
|
||||
{
|
||||
int ch_idx;
|
||||
unsigned life_left;
|
||||
channel_t *ch, *first_to_die;
|
||||
|
||||
// Check for replacement sound, or find the best one to replace
|
||||
first_to_die = 0;
|
||||
life_left = 0x7fffffff;
|
||||
for (ch_idx = 0; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++) {
|
||||
ch = dynamic_channels[ch_idx];
|
||||
if (entchannel != 0 // channel 0 never overrides
|
||||
&& ch->entnum == entnum
|
||||
&& (ch->entchannel == entchannel || entchannel == -1)) {
|
||||
// always override sound from same entity
|
||||
first_to_die = ch;
|
||||
break;
|
||||
}
|
||||
// don't let monster sounds override player sounds
|
||||
if (ch->entnum == *render_data.viewentity
|
||||
&& entnum != *render_data.viewentity
|
||||
&& ch->sfx)
|
||||
continue;
|
||||
|
||||
if (snd_paintedtime + life_left > ch->end) {
|
||||
life_left = ch->end - snd_paintedtime;
|
||||
first_to_die = ch;
|
||||
}
|
||||
}
|
||||
|
||||
if (!first_to_die)
|
||||
return NULL;
|
||||
|
||||
if (first_to_die->sfx) {
|
||||
first_to_die->sfx->close (first_to_die->sfx);
|
||||
first_to_die->sfx = NULL;
|
||||
}
|
||||
|
||||
return first_to_die;
|
||||
}
|
||||
|
||||
static void
|
||||
s_spatialize (channel_t *ch)
|
||||
{
|
||||
int phase; // in samples
|
||||
vec_t dist, dot, lscale, rscale, scale;
|
||||
vec3_t source_vec;
|
||||
|
||||
// anything coming from the view entity will always be full volume
|
||||
if (ch->entnum == *render_data.viewentity) {
|
||||
ch->leftvol = ch->master_vol;
|
||||
ch->rightvol = ch->master_vol;
|
||||
ch->phase = 0;
|
||||
return;
|
||||
}
|
||||
// calculate stereo seperation and distance attenuation
|
||||
|
||||
VectorSubtract (ch->origin, listener_origin, source_vec);
|
||||
|
||||
dist = VectorNormalize (source_vec) * ch->dist_mult;
|
||||
|
||||
dot = DotProduct (listener_right, source_vec);
|
||||
|
||||
if (snd_shm->channels == 1) {
|
||||
rscale = 1.0;
|
||||
lscale = 1.0;
|
||||
phase = 0;
|
||||
} else {
|
||||
rscale = 1.0 + dot * snd_volumesep->value;
|
||||
lscale = 1.0 - dot * snd_volumesep->value;
|
||||
phase = snd_phasesep->value * 0.001 * snd_shm->speed * dot;
|
||||
}
|
||||
|
||||
// add in distance effect
|
||||
scale = (1.0 - dist) * rscale;
|
||||
ch->rightvol = (int) (ch->master_vol * scale);
|
||||
if (ch->rightvol < 0)
|
||||
ch->rightvol = 0;
|
||||
|
||||
scale = (1.0 - dist) * lscale;
|
||||
ch->leftvol = (int) (ch->master_vol * scale);
|
||||
if (ch->leftvol < 0)
|
||||
ch->leftvol = 0;
|
||||
|
||||
ch->phase = phase;
|
||||
}
|
||||
|
||||
// Start a sound effect =======================================================
|
||||
static void
|
||||
s_start_sound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
|
||||
float fvol, float attenuation)
|
||||
{
|
||||
int ch_idx, vol;
|
||||
unsigned int skip;
|
||||
channel_t *target_chan, *check;
|
||||
|
||||
if (!sound_started)
|
||||
return;
|
||||
if (!sfx)
|
||||
return;
|
||||
if (nosound->int_val)
|
||||
return;
|
||||
// pick a channel to play on
|
||||
target_chan = s_pick_channel (entnum, entchannel);
|
||||
if (!target_chan)
|
||||
return;
|
||||
|
||||
vol = fvol * 255;
|
||||
|
||||
// spatialize
|
||||
memset (target_chan, 0, sizeof (*target_chan));
|
||||
VectorCopy (origin, target_chan->origin);
|
||||
target_chan->dist_mult = attenuation / sound_nominal_clip_dist;
|
||||
target_chan->master_vol = vol;
|
||||
target_chan->entnum = entnum;
|
||||
target_chan->entchannel = entchannel;
|
||||
s_spatialize (target_chan);
|
||||
|
||||
if (!target_chan->leftvol && !target_chan->rightvol)
|
||||
return; // not audible at all
|
||||
|
||||
// new channel
|
||||
if (!sfx->retain (sfx)) {
|
||||
if (target_chan->sfx)
|
||||
target_chan->sfx->close (target_chan->sfx);
|
||||
target_chan->sfx = NULL;
|
||||
return; // couldn't load the sound's data
|
||||
}
|
||||
|
||||
if (!(target_chan->sfx = sfx->open (sfx))) {
|
||||
sfx->release (sfx);
|
||||
return;
|
||||
}
|
||||
target_chan->pos = 0.0;
|
||||
target_chan->end = snd_paintedtime + target_chan->sfx->length;
|
||||
sfx->release (sfx);
|
||||
|
||||
// if an identical sound has also been started this frame, offset the pos
|
||||
// a bit to keep it from just making the first one louder
|
||||
for (ch_idx = 0; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++) {
|
||||
check = dynamic_channels[ch_idx];
|
||||
if (check == target_chan)
|
||||
continue;
|
||||
if (check->sfx == sfx && !check->pos) {
|
||||
skip = rand () % (int) (0.1 * snd_shm->speed);
|
||||
if (skip >= target_chan->end)
|
||||
skip = target_chan->end - 1;
|
||||
target_chan->pos += skip;
|
||||
target_chan->end -= skip;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
s_stop_sound (int entnum, int entchannel)
|
||||
{
|
||||
int i;
|
||||
channel_t *ch;
|
||||
|
||||
if (!sound_started)
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAX_DYNAMIC_CHANNELS; i++) {
|
||||
ch = dynamic_channels[i];
|
||||
if (ch->entnum == entnum && ch->entchannel == entchannel) {
|
||||
ch->end = 0;
|
||||
if (ch->sfx)
|
||||
ch->sfx->close (ch->sfx);
|
||||
ch->sfx = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
s_clear_buffer (void)
|
||||
|
@ -396,131 +106,18 @@ s_clear_buffer (void)
|
|||
clear = 0;
|
||||
|
||||
for (i = 0; i < snd_shm->samples * snd_shm->samplebits / 8; i++)
|
||||
snd_shm->buffer[i] = 0;
|
||||
snd_shm->buffer[i] = clear;
|
||||
}
|
||||
|
||||
static void
|
||||
s_stop_all_sounds (qboolean clear)
|
||||
s_stop_all_sounds (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!sound_started)
|
||||
return;
|
||||
|
||||
num_statics = 0;
|
||||
|
||||
for (i = 0; i < MAX_CHANNELS; i++)
|
||||
if (snd_channels[i].sfx) {
|
||||
snd_channels[i].sfx->close (snd_channels[i].sfx);
|
||||
snd_channels[i].sfx = NULL;
|
||||
}
|
||||
|
||||
memset (snd_channels, 0, MAX_CHANNELS * sizeof (channel_t));
|
||||
|
||||
if (clear)
|
||||
SND_StopAllSounds ();
|
||||
s_clear_buffer ();
|
||||
}
|
||||
|
||||
static void
|
||||
s_static_sound (sfx_t *sfx, const vec3_t origin, float vol,
|
||||
float attenuation)
|
||||
{
|
||||
channel_t *ss;
|
||||
|
||||
if (!sound_started || !sfx)
|
||||
return;
|
||||
|
||||
if (!static_channels[num_statics]) {
|
||||
if (!(static_channels[num_statics] = s_alloc_channel ())) {
|
||||
Sys_Printf ("ran out of channels\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ss = static_channels[num_statics];
|
||||
|
||||
if (!sfx->retain (sfx))
|
||||
return;
|
||||
|
||||
if (sfx->loopstart == (unsigned int) -1) {
|
||||
Sys_Printf ("Sound %s not looped\n", sfx->name);
|
||||
sfx->release (sfx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(ss->sfx = sfx->open (sfx))) {
|
||||
sfx->release (sfx);
|
||||
return;
|
||||
}
|
||||
VectorCopy (origin, ss->origin);
|
||||
ss->master_vol = vol;
|
||||
ss->dist_mult = (attenuation / 64) / sound_nominal_clip_dist;
|
||||
ss->end = snd_paintedtime + sfx->length;
|
||||
sfx->release (sfx);
|
||||
|
||||
s_spatialize (ss);
|
||||
ss->oldphase = ss->phase;
|
||||
num_statics++;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
static void
|
||||
s_updateAmbientSounds (void)
|
||||
{
|
||||
float vol;
|
||||
int ambient_channel;
|
||||
channel_t *chan;
|
||||
mleaf_t *l;
|
||||
|
||||
if (!snd_ambient)
|
||||
return;
|
||||
// calc ambient sound levels
|
||||
if (!*render_data.worldmodel)
|
||||
return;
|
||||
|
||||
l = Mod_PointInLeaf (listener_origin, *render_data.worldmodel);
|
||||
if (!l || !ambient_level->value) {
|
||||
for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
|
||||
ambient_channel++) {
|
||||
chan = ambient_channels[ambient_channel];
|
||||
if (chan->sfx)
|
||||
chan->sfx->close (chan->sfx);
|
||||
chan->sfx = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
|
||||
ambient_channel++) {
|
||||
chan = ambient_channels[ambient_channel];
|
||||
if (!ambient_sfx[ambient_channel]) {
|
||||
chan->sfx = 0;
|
||||
continue;
|
||||
} else if (!chan->sfx)
|
||||
chan->sfx = ambient_sfx[ambient_channel]->open (ambient_sfx[ambient_channel]);
|
||||
|
||||
vol = ambient_level->value * l->ambient_sound_level[ambient_channel];
|
||||
if (vol < 8)
|
||||
vol = 0;
|
||||
|
||||
// don't adjust volume too fast
|
||||
if (chan->master_vol < vol) {
|
||||
chan->master_vol += *render_data.host_frametime
|
||||
* ambient_fade->value;
|
||||
if (chan->master_vol > vol)
|
||||
chan->master_vol = vol;
|
||||
} else if (chan->master_vol > vol) {
|
||||
chan->master_vol -= *render_data.host_frametime
|
||||
* ambient_fade->value;
|
||||
if (chan->master_vol < vol)
|
||||
chan->master_vol = vol;
|
||||
}
|
||||
|
||||
chan->leftvol = chan->rightvol = chan->master_vol;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
s_get_soundtime (void)
|
||||
{
|
||||
|
@ -541,7 +138,7 @@ s_get_soundtime (void)
|
|||
// 32 bit limits
|
||||
buffers = 0;
|
||||
snd_paintedtime = fullsamples;
|
||||
s_stop_all_sounds (true);
|
||||
s_stop_all_sounds ();
|
||||
}
|
||||
}
|
||||
oldsamplepos = samplepos;
|
||||
|
@ -575,18 +172,6 @@ s_update_ (void)
|
|||
snd_output_funcs->pS_O_Submit ();
|
||||
}
|
||||
|
||||
static inline int
|
||||
s_update_channel (channel_t *ch)
|
||||
{
|
||||
if (!ch->sfx)
|
||||
return 0;
|
||||
ch->oldphase = ch->phase; // prepare to lerp from prev to next phase
|
||||
s_spatialize (ch); // respatialize channel
|
||||
if (!ch->leftvol && !ch->rightvol)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
s_update
|
||||
|
||||
|
@ -596,72 +181,10 @@ static void
|
|||
s_update (const vec3_t origin, const vec3_t forward, const vec3_t right,
|
||||
const vec3_t up)
|
||||
{
|
||||
int total, i, j;
|
||||
channel_t *ch, *combine;
|
||||
|
||||
if (!sound_started || (snd_blocked > 0))
|
||||
return;
|
||||
|
||||
VectorCopy (origin, listener_origin);
|
||||
VectorCopy (forward, listener_forward);
|
||||
VectorCopy (right, listener_right);
|
||||
VectorCopy (up, listener_up);
|
||||
|
||||
// update general area ambient sound sources
|
||||
s_updateAmbientSounds ();
|
||||
|
||||
combine = NULL;
|
||||
|
||||
// update spatialization for static and dynamic sounds
|
||||
for (i = 0; i < MAX_DYNAMIC_CHANNELS; i++)
|
||||
s_update_channel (dynamic_channels[i]);
|
||||
|
||||
for (i = 0; i < num_statics; i++) {
|
||||
ch = static_channels[i];
|
||||
if (!s_update_channel (ch))
|
||||
continue;
|
||||
|
||||
// try to combine static sounds with a previous channel of the same
|
||||
// sound effect so we don't mix five torches every frame
|
||||
// see if it can just use the last one
|
||||
if (combine && combine->sfx == ch->sfx) {
|
||||
combine->leftvol += ch->leftvol;
|
||||
combine->rightvol += ch->rightvol;
|
||||
ch->leftvol = ch->rightvol = 0;
|
||||
continue;
|
||||
}
|
||||
// search for one
|
||||
for (j = 0; j < i; j++) {
|
||||
combine = static_channels[j];
|
||||
if (combine->sfx == ch->sfx)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == i) {
|
||||
combine = NULL;
|
||||
} else {
|
||||
if (combine != ch) {
|
||||
combine->leftvol += ch->leftvol;
|
||||
combine->rightvol += ch->rightvol;
|
||||
ch->leftvol = ch->rightvol = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// debugging output
|
||||
if (snd_show->int_val) {
|
||||
total = 0;
|
||||
ch = snd_channels;
|
||||
for (i = 0; i < snd_total_channels; i++, ch++)
|
||||
if (ch->sfx && (ch->leftvol || ch->rightvol)) {
|
||||
// Sys_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol,
|
||||
// ch->sfx->name);
|
||||
total++;
|
||||
}
|
||||
|
||||
Sys_Printf ("----(%i)----\n", total);
|
||||
}
|
||||
SND_SetListener (origin, forward, right, up);
|
||||
|
||||
// mix some sound
|
||||
s_update_ ();
|
||||
|
@ -675,24 +198,6 @@ s_extra_update (void)
|
|||
s_update_ ();
|
||||
}
|
||||
|
||||
static void
|
||||
s_local_sound (const char *sound)
|
||||
{
|
||||
sfx_t *sfx;
|
||||
|
||||
if (!sound_started)
|
||||
return;
|
||||
if (nosound->int_val)
|
||||
return;
|
||||
|
||||
sfx = s_precache_sound (sound);
|
||||
if (!sfx) {
|
||||
Sys_Printf ("S_LocalSound: can't cache %s\n", sound);
|
||||
return;
|
||||
}
|
||||
s_start_sound (*render_data.viewentity, -1, sfx, vec3_origin, 1, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
s_block_sound (void)
|
||||
{
|
||||
|
@ -714,12 +219,6 @@ s_unblock_sound (void)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
s_gamedir (void)
|
||||
{
|
||||
num_sfx = 0;
|
||||
}
|
||||
|
||||
/* console functions */
|
||||
|
||||
static void
|
||||
|
@ -740,106 +239,10 @@ s_soundinfo_f (void)
|
|||
Sys_Printf ("%5d total_channels\n", snd_total_channels);
|
||||
}
|
||||
|
||||
static void
|
||||
s_play_f (void)
|
||||
{
|
||||
dstring_t *name = dstring_new ();
|
||||
int i;
|
||||
static int hash = 345;
|
||||
sfx_t *sfx;
|
||||
|
||||
i = 1;
|
||||
while (i < Cmd_Argc ()) {
|
||||
if (!strrchr (Cmd_Argv (i), '.')) {
|
||||
dsprintf (name, "%s.wav", Cmd_Argv (i));
|
||||
} else {
|
||||
dsprintf (name, "%s", Cmd_Argv (i));
|
||||
}
|
||||
sfx = s_precache_sound (name->str);
|
||||
s_start_sound (hash++, 0, sfx, listener_origin, 1.0, 1.0);
|
||||
i++;
|
||||
}
|
||||
dstring_delete (name);
|
||||
}
|
||||
|
||||
static void
|
||||
s_playcenter_f (void)
|
||||
{
|
||||
dstring_t *name = dstring_new ();
|
||||
int i;
|
||||
sfx_t *sfx;
|
||||
|
||||
i = 1;
|
||||
while (i < Cmd_Argc ()) {
|
||||
if (!strrchr (Cmd_Argv (i), '.')) {
|
||||
dsprintf (name, "%s.wav", Cmd_Argv (i));
|
||||
} else {
|
||||
dsprintf (name, "%s", Cmd_Argv (i));
|
||||
}
|
||||
sfx = s_precache_sound (name->str);
|
||||
s_start_sound (*render_data.viewentity, 0, sfx, listener_origin, 1.0, 1.0);
|
||||
i++;
|
||||
}
|
||||
dstring_delete (name);
|
||||
}
|
||||
|
||||
static void
|
||||
s_playvol_f (void)
|
||||
{
|
||||
dstring_t *name = dstring_new ();
|
||||
float vol;
|
||||
int i;
|
||||
static int hash = 543;
|
||||
sfx_t *sfx;
|
||||
|
||||
i = 1;
|
||||
while (i < Cmd_Argc ()) {
|
||||
if (!strrchr (Cmd_Argv (i), '.')) {
|
||||
dsprintf (name, "%s.wav", Cmd_Argv (i));
|
||||
} else {
|
||||
dsprintf (name, "%s", Cmd_Argv (i));
|
||||
}
|
||||
sfx = s_precache_sound (name->str);
|
||||
vol = atof (Cmd_Argv (i + 1));
|
||||
s_start_sound (hash++, 0, sfx, listener_origin, vol, 1.0);
|
||||
i += 2;
|
||||
}
|
||||
dstring_delete (name);
|
||||
}
|
||||
|
||||
static void
|
||||
s_soundlist_f (void)
|
||||
{
|
||||
int load, total, i;
|
||||
sfx_t *sfx;
|
||||
|
||||
if (Cmd_Argc() >= 2 && Cmd_Argv (1)[0])
|
||||
load = 1;
|
||||
else
|
||||
load = 0;
|
||||
|
||||
total = 0;
|
||||
for (sfx = known_sfx, i = 0; i < num_sfx; i++, sfx++) {
|
||||
if (load) {
|
||||
if (!sfx->retain (sfx))
|
||||
continue;
|
||||
} else {
|
||||
if (!sfx->touch (sfx))
|
||||
continue;
|
||||
}
|
||||
total += sfx->length;
|
||||
Sys_Printf ("%6d %6d %s\n", sfx->loopstart, sfx->length, sfx->name);
|
||||
|
||||
if (load)
|
||||
sfx->release (sfx);
|
||||
}
|
||||
Sys_Printf ("Total resident: %i\n", total);
|
||||
}
|
||||
|
||||
static void
|
||||
s_stop_all_sounds_f (void)
|
||||
{
|
||||
s_stop_all_sounds (true);
|
||||
s_stop_all_sounds ();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -862,39 +265,18 @@ s_startup (void)
|
|||
static void
|
||||
s_init (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_AMBIENTS; i++)
|
||||
ambient_channels[i] = s_alloc_channel ();
|
||||
for (i = 0; i < MAX_DYNAMIC_CHANNELS; i++)
|
||||
dynamic_channels[i] = s_alloc_channel ();
|
||||
|
||||
snd_output_funcs = render_data.output->functions->snd_output;
|
||||
snd_output_funcs = snd_render_data.output->functions->snd_output;
|
||||
Sys_Printf ("\nSound Initialization\n");
|
||||
|
||||
Cmd_AddCommand ("play", s_play_f,
|
||||
"Play selected sound effect (play pathto/sound.wav)");
|
||||
Cmd_AddCommand ("playcenter", s_playcenter_f,
|
||||
"Play selected sound effect without 3D spatialization.");
|
||||
Cmd_AddCommand ("playvol", s_playvol_f, "Play selected sound effect at "
|
||||
"selected volume (playvol pathto/sound.wav num");
|
||||
Cmd_AddCommand ("stopsound", s_stop_all_sounds_f,
|
||||
"Stops all sounds currently being played");
|
||||
Cmd_AddCommand ("soundlist", s_soundlist_f,
|
||||
"Reports a list of sounds in the cache");
|
||||
Cmd_AddCommand ("soundinfo", s_soundinfo_f,
|
||||
"Report information on the sound system");
|
||||
|
||||
snd_interp = Cvar_Get ("snd_interp", "1", CVAR_ARCHIVE, NULL,
|
||||
"control sample interpolation");
|
||||
ambient_fade = Cvar_Get ("ambient_fade", "100", CVAR_NONE, NULL,
|
||||
"How quickly ambient sounds fade in or out");
|
||||
ambient_level = Cvar_Get ("ambient_level", "0.3", CVAR_NONE, NULL,
|
||||
"Ambient sounds' volume");
|
||||
nosound = Cvar_Get ("nosound", "0", CVAR_NONE, NULL,
|
||||
"Set to turn sound off");
|
||||
precache = Cvar_Get ("precache", "1", CVAR_NONE, NULL,
|
||||
"Toggle the use of a precache");
|
||||
snd_volume = Cvar_Get ("volume", "0.7", CVAR_ARCHIVE, NULL,
|
||||
"Set the volume for sound playback");
|
||||
snd_interp = Cvar_Get ("snd_interp", "1", CVAR_ARCHIVE, NULL,
|
||||
|
@ -907,13 +289,8 @@ s_init (void)
|
|||
"Toggles the correct value display in "
|
||||
"host_speeds. Usually messes up sound "
|
||||
"playback when in effect");
|
||||
snd_phasesep = Cvar_Get ("snd_phasesep", "0.0", CVAR_ARCHIVE, NULL,
|
||||
"max stereo phase separation in ms. 0.6 is for "
|
||||
"20cm head");
|
||||
snd_show = Cvar_Get ("snd_show", "0", CVAR_NONE, NULL,
|
||||
"Toggles display of sounds currently being played");
|
||||
snd_volumesep = Cvar_Get ("snd_volumesep", "1.0", CVAR_ARCHIVE, NULL,
|
||||
"max stereo volume separation. 1.0 is max");
|
||||
// FIXME
|
||||
// if (host_parms.memsize < 0x800000) {
|
||||
// Cvar_Set (snd_loadas8bit, "1");
|
||||
|
@ -927,18 +304,12 @@ s_init (void)
|
|||
if (sound_started == 0) // sound startup failed? Bail out.
|
||||
return;
|
||||
|
||||
SND_SFX_Init ();
|
||||
SND_Channels_Init ();
|
||||
|
||||
SND_InitScaletable ();
|
||||
|
||||
known_sfx = Hunk_AllocName (MAX_SFX * sizeof (sfx_t), "sfx_t");
|
||||
|
||||
num_sfx = 0;
|
||||
|
||||
ambient_sfx[AMBIENT_WATER] = s_precache_sound ("ambience/water1.wav");
|
||||
ambient_sfx[AMBIENT_SKY] = s_precache_sound ("ambience/wind2.wav");
|
||||
|
||||
s_stop_all_sounds (true);
|
||||
|
||||
QFS_GamedirCallback (s_gamedir);
|
||||
s_stop_all_sounds ();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -960,21 +331,21 @@ static general_funcs_t plugin_info_general_funcs = {
|
|||
};
|
||||
|
||||
static snd_render_funcs_t plugin_info_render_funcs = {
|
||||
s_ambient_off,
|
||||
s_ambient_on,
|
||||
s_touch_sound,
|
||||
s_static_sound,
|
||||
s_start_sound,
|
||||
s_stop_sound,
|
||||
s_precache_sound,
|
||||
SND_AmbientOff,
|
||||
SND_AmbientOn,
|
||||
SND_TouchSound,
|
||||
SND_StaticSound,
|
||||
SND_StartSound,
|
||||
SND_StopSound,
|
||||
SND_PrecacheSound,
|
||||
s_update,
|
||||
s_stop_all_sounds,
|
||||
s_extra_update,
|
||||
s_local_sound,
|
||||
SND_LocalSound,
|
||||
s_block_sound,
|
||||
s_unblock_sound,
|
||||
s_load_sound,
|
||||
s_alloc_channel,
|
||||
SND_LoadSound,
|
||||
SND_AllocChannel,
|
||||
};
|
||||
|
||||
static plugin_funcs_t plugin_info_funcs = {
|
||||
|
@ -992,7 +363,7 @@ static plugin_data_t plugin_info_data = {
|
|||
0,
|
||||
0,
|
||||
0,
|
||||
&render_data,
|
||||
&snd_render_data,
|
||||
};
|
||||
|
||||
static plugin_t plugin_info = {
|
||||
|
|
|
@ -219,8 +219,7 @@ SND_PaintChannels (unsigned int endtime)
|
|||
ch->end = ltime + ch->sfx->length - ch->pos;
|
||||
} else { // channel just stopped
|
||||
ch->sfx->release (ch->sfx);
|
||||
ch->sfx->close (ch->sfx);
|
||||
ch->sfx = NULL;
|
||||
SND_ChannelStop (ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -185,10 +185,10 @@ S_Update (const vec3_t origin, const vec3_t v_forward, const vec3_t v_right,
|
|||
}
|
||||
|
||||
VISIBLE void
|
||||
S_StopAllSounds (qboolean clear)
|
||||
S_StopAllSounds (void)
|
||||
{
|
||||
if (snd_render_funcs)
|
||||
snd_render_funcs->pS_StopAllSounds (clear);
|
||||
snd_render_funcs->pS_StopAllSounds ();
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
|
|
|
@ -202,7 +202,7 @@ void
|
|||
CL_Disconnect (void)
|
||||
{
|
||||
// stop sounds (especially looping!)
|
||||
S_StopAllSounds (true);
|
||||
S_StopAllSounds ();
|
||||
|
||||
// Clean the Cshifts
|
||||
CL_StopCshifts ();
|
||||
|
|
|
@ -268,7 +268,7 @@ CL_ParseServerInfo (void)
|
|||
Con_DPrintf ("Serverinfo packet received.\n");
|
||||
|
||||
S_BlockSound ();
|
||||
S_StopAllSounds (true);
|
||||
S_StopAllSounds ();
|
||||
|
||||
// wipe the client_state_t struct
|
||||
CL_ClearState ();
|
||||
|
|
|
@ -393,7 +393,7 @@ CL_ClearState (void)
|
|||
{
|
||||
int i;
|
||||
|
||||
S_StopAllSounds (true);
|
||||
S_StopAllSounds ();
|
||||
|
||||
// wipe the entire cl structure
|
||||
Info_Destroy (cl.serverinfo);
|
||||
|
@ -472,7 +472,7 @@ CL_Disconnect (void)
|
|||
VID_SetCaption ("Disconnected");
|
||||
|
||||
// stop sounds (especially looping!)
|
||||
S_StopAllSounds (true);
|
||||
S_StopAllSounds ();
|
||||
|
||||
// Clean the Cshifts
|
||||
CL_StopCshifts ();
|
||||
|
@ -794,7 +794,7 @@ CL_Changing_f (void)
|
|||
if (cls.download) // don't change when downloading
|
||||
return;
|
||||
|
||||
S_StopAllSounds (true);
|
||||
S_StopAllSounds ();
|
||||
cl.intermission = 0;
|
||||
r_force_fullscreen = 0;
|
||||
CL_SetState (ca_connected); // not active anymore, but not
|
||||
|
@ -815,7 +815,7 @@ CL_Reconnect_f (void)
|
|||
if (cls.demoplayback)
|
||||
return;
|
||||
|
||||
S_StopAllSounds (true);
|
||||
S_StopAllSounds ();
|
||||
|
||||
if (cls.state == ca_connected) {
|
||||
Con_Printf ("reconnecting...\n");
|
||||
|
|
Loading…
Reference in a new issue