most of the hacking needed to break out the common code from snd_dma.c

This commit is contained in:
Bill Currie 2007-03-17 03:10:45 +00:00 committed by Jeff Teunissen
parent 0105754f6f
commit cde6e60848
16 changed files with 176 additions and 679 deletions

View file

@ -1032,6 +1032,30 @@ fi
AC_SUBST(ALSA_LIBS) AC_SUBST(ALSA_LIBS)
AC_SUBST(HAVE_ALSA) 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" SOUND_TYPES="$SOUND_TYPES DISK"
dnl MME dnl MME
@ -2015,6 +2039,9 @@ if test -n "$CL_TARGETS"; then
fi fi
if test "$SOUND_TYPES"; then if test "$SOUND_TYPES"; then
SND_REND_TARGETS="$SND_REND_TARGETS snd_render_default.la" 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 fi
# priority sorted list for default sound driver in order of increasing # priority sorted list for default sound driver in order of increasing

View file

@ -29,7 +29,6 @@
#define __QF_plugin_cd_h_ #define __QF_plugin_cd_h_
#include <QF/qtypes.h> #include <QF/qtypes.h>
#include <QF/plugin.h>
/* /*
All CDAudio plugins must export these functions All CDAudio plugins must export these functions

View file

@ -33,7 +33,6 @@
#include <QF/keys.h> #include <QF/keys.h>
#include <QF/qtypes.h> #include <QF/qtypes.h>
#include <QF/plugin.h>
typedef void (*P_C_Print) (const char *fmt, va_list args); typedef void (*P_C_Print) (const char *fmt, va_list args);
typedef void (*P_C_ProcessInput) (void); typedef void (*P_C_ProcessInput) (void);

View file

@ -30,7 +30,6 @@
#define __QF_plugin_general_h_ #define __QF_plugin_general_h_
#include <QF/qtypes.h> #include <QF/qtypes.h>
#include <QF/plugin.h>
/* /*
All plugins, of all types, must export these functions All plugins, of all types, must export these functions

View file

@ -30,7 +30,6 @@
#define __QF_plugin_input_h_ #define __QF_plugin_input_h_
#include <QF/qtypes.h> #include <QF/qtypes.h>
#include <QF/plugin.h>
/* /*
All input plugins must export these functions All input plugins must export these functions

View file

@ -29,7 +29,6 @@
#define __QF_plugin_snd_output_h_ #define __QF_plugin_snd_output_h_
#include <QF/qtypes.h> #include <QF/qtypes.h>
#include <QF/plugin.h>
/* /*
All sound plugins must export these functions All sound plugins must export these functions

View file

@ -29,7 +29,6 @@
#define __QF_plugin_snd_render_h_ #define __QF_plugin_snd_render_h_
#include <QF/qtypes.h> #include <QF/qtypes.h>
#include <QF/plugin.h>
/* /*
All sound plugins must export these functions 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 void (*P_S_StopSound) (int entnum, int entchannel);
typedef struct sfx_s * (*P_S_PrecacheSound) (const char *sample); 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_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_ExtraUpdate) (void);
typedef void (*P_S_LocalSound) (const char *s); typedef void (*P_S_LocalSound) (const char *s);
typedef void (*P_S_BlockSound) (void); typedef void (*P_S_BlockSound) (void);

View file

@ -119,10 +119,8 @@ void S_StaticSound (sfx_t *sfx, const vec3_t origin, float vol,
void S_StopSound (int entnum, int entchannel); void S_StopSound (int entnum, int entchannel);
/** Stop all sounds from playing. /** 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 /** Update the sound engine with the client's position and orientation and
render some sound. render some sound.

View file

@ -38,6 +38,8 @@
*/ */
//@{ //@{
#include "QF/plugin/snd_render.h"
#include "QF/quakeio.h"
#include "QF/sound.h" #include "QF/sound.h"
#include "QF/zone.h" #include "QF/zone.h"
@ -176,14 +178,42 @@ struct channel_s {
int oldphase; //!< phase shift between l-r in samples int oldphase; //!< phase shift between l-r in samples
}; };
extern struct cvar_s *snd_loadas8bit; extern struct cvar_s *snd_loadas8bit;
extern struct cvar_s *snd_volume; extern struct cvar_s *snd_volume;
extern struct cvar_s *snd_interp; extern struct cvar_s *snd_interp;
extern struct cvar_s *snd_stereo_phase_separation; extern struct cvar_s *snd_stereo_phase_separation;
extern volatile dma_t *snd_shm; 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 /** \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 #define MAX_DYNAMIC_CHANNELS 8 //!< number of dynamic channels
extern channel_t snd_channels[MAX_CHANNELS]; //!< pool of available channels extern channel_t snd_channels[MAX_CHANNELS]; //!< pool of available channels
extern int snd_total_channels; //!< number of active 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);
//@} //@}

View file

@ -8,12 +8,18 @@ plugin_libadd= @plugin_libadd@
EXEEXT= EXEEXT=
plugin_LTLIBRARIES= @SND_REND_TARGETS@ 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@ noinst_LTLIBRARIES= @SND_REND_STATIC@
snd_render_default_la_LDFLAGS= $(plugin_ldflags) 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 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_LIBADD= $(VORBISFILE_LIBS) $(VORBIS_LIBS) $(LIBFLAC_LIBS) $(OGG_LIBS) $(WM_LIBS)
snd_render_default_la_DEPENDENCIES= 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=

View file

@ -62,47 +62,21 @@ cvar_t *snd_loadas8bit;
cvar_t *snd_volume; cvar_t *snd_volume;
cvar_t *snd_interp; 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 qboolean snd_initialized = false;
static int snd_blocked = 0; 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 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 int sound_started = 0;
static cvar_t *ambient_fade;
static cvar_t *ambient_level;
static cvar_t *nosound; static cvar_t *nosound;
static cvar_t *precache;
static cvar_t *snd_mixahead; static cvar_t *snd_mixahead;
static cvar_t *snd_noextraupdate; static cvar_t *snd_noextraupdate;
static cvar_t *snd_phasesep;
static cvar_t *snd_show; static cvar_t *snd_show;
static cvar_t *snd_volumesep;
static general_data_t plugin_info_general_data; 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, 0,
0, 0,
@ -114,273 +88,9 @@ static snd_render_data_t render_data = {
static snd_output_funcs_t *snd_output_funcs; 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 ======================================================= // 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 static void
s_clear_buffer (void) s_clear_buffer (void)
@ -396,131 +106,18 @@ s_clear_buffer (void)
clear = 0; clear = 0;
for (i = 0; i < snd_shm->samples * snd_shm->samplebits / 8; i++) for (i = 0; i < snd_shm->samples * snd_shm->samplebits / 8; i++)
snd_shm->buffer[i] = 0; snd_shm->buffer[i] = clear;
} }
static void static void
s_stop_all_sounds (qboolean clear) s_stop_all_sounds (void)
{ {
int i; SND_StopAllSounds ();
s_clear_buffer ();
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)
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 static void
s_get_soundtime (void) s_get_soundtime (void)
{ {
@ -541,7 +138,7 @@ s_get_soundtime (void)
// 32 bit limits // 32 bit limits
buffers = 0; buffers = 0;
snd_paintedtime = fullsamples; snd_paintedtime = fullsamples;
s_stop_all_sounds (true); s_stop_all_sounds ();
} }
} }
oldsamplepos = samplepos; oldsamplepos = samplepos;
@ -575,18 +172,6 @@ s_update_ (void)
snd_output_funcs->pS_O_Submit (); 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 s_update
@ -596,72 +181,10 @@ static void
s_update (const vec3_t origin, const vec3_t forward, const vec3_t right, s_update (const vec3_t origin, const vec3_t forward, const vec3_t right,
const vec3_t up) const vec3_t up)
{ {
int total, i, j;
channel_t *ch, *combine;
if (!sound_started || (snd_blocked > 0)) if (!sound_started || (snd_blocked > 0))
return; return;
VectorCopy (origin, listener_origin); SND_SetListener (origin, forward, right, up);
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);
}
// mix some sound // mix some sound
s_update_ (); s_update_ ();
@ -675,24 +198,6 @@ s_extra_update (void)
s_update_ (); 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 static void
s_block_sound (void) s_block_sound (void)
{ {
@ -714,12 +219,6 @@ s_unblock_sound (void)
} }
} }
static void
s_gamedir (void)
{
num_sfx = 0;
}
/* console functions */ /* console functions */
static void static void
@ -740,106 +239,10 @@ s_soundinfo_f (void)
Sys_Printf ("%5d total_channels\n", snd_total_channels); 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 static void
s_stop_all_sounds_f (void) s_stop_all_sounds_f (void)
{ {
s_stop_all_sounds (true); s_stop_all_sounds ();
} }
static void static void
@ -862,39 +265,18 @@ s_startup (void)
static void static void
s_init (void) s_init (void)
{ {
int i; snd_output_funcs = snd_render_data.output->functions->snd_output;
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;
Sys_Printf ("\nSound Initialization\n"); 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, Cmd_AddCommand ("stopsound", s_stop_all_sounds_f,
"Stops all sounds currently being played"); "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, Cmd_AddCommand ("soundinfo", s_soundinfo_f,
"Report information on the sound system"); "Report information on the sound system");
snd_interp = Cvar_Get ("snd_interp", "1", CVAR_ARCHIVE, NULL, snd_interp = Cvar_Get ("snd_interp", "1", CVAR_ARCHIVE, NULL,
"control sample interpolation"); "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, nosound = Cvar_Get ("nosound", "0", CVAR_NONE, NULL,
"Set to turn sound off"); "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, snd_volume = Cvar_Get ("volume", "0.7", CVAR_ARCHIVE, NULL,
"Set the volume for sound playback"); "Set the volume for sound playback");
snd_interp = Cvar_Get ("snd_interp", "1", CVAR_ARCHIVE, NULL, snd_interp = Cvar_Get ("snd_interp", "1", CVAR_ARCHIVE, NULL,
@ -907,13 +289,8 @@ s_init (void)
"Toggles the correct value display in " "Toggles the correct value display in "
"host_speeds. Usually messes up sound " "host_speeds. Usually messes up sound "
"playback when in effect"); "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, snd_show = Cvar_Get ("snd_show", "0", CVAR_NONE, NULL,
"Toggles display of sounds currently being played"); "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 // FIXME
// if (host_parms.memsize < 0x800000) { // if (host_parms.memsize < 0x800000) {
// Cvar_Set (snd_loadas8bit, "1"); // Cvar_Set (snd_loadas8bit, "1");
@ -927,18 +304,12 @@ s_init (void)
if (sound_started == 0) // sound startup failed? Bail out. if (sound_started == 0) // sound startup failed? Bail out.
return; return;
SND_SFX_Init ();
SND_Channels_Init ();
SND_InitScaletable (); SND_InitScaletable ();
known_sfx = Hunk_AllocName (MAX_SFX * sizeof (sfx_t), "sfx_t"); s_stop_all_sounds ();
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);
} }
static void static void
@ -960,21 +331,21 @@ static general_funcs_t plugin_info_general_funcs = {
}; };
static snd_render_funcs_t plugin_info_render_funcs = { static snd_render_funcs_t plugin_info_render_funcs = {
s_ambient_off, SND_AmbientOff,
s_ambient_on, SND_AmbientOn,
s_touch_sound, SND_TouchSound,
s_static_sound, SND_StaticSound,
s_start_sound, SND_StartSound,
s_stop_sound, SND_StopSound,
s_precache_sound, SND_PrecacheSound,
s_update, s_update,
s_stop_all_sounds, s_stop_all_sounds,
s_extra_update, s_extra_update,
s_local_sound, SND_LocalSound,
s_block_sound, s_block_sound,
s_unblock_sound, s_unblock_sound,
s_load_sound, SND_LoadSound,
s_alloc_channel, SND_AllocChannel,
}; };
static plugin_funcs_t plugin_info_funcs = { static plugin_funcs_t plugin_info_funcs = {
@ -992,7 +363,7 @@ static plugin_data_t plugin_info_data = {
0, 0,
0, 0,
0, 0,
&render_data, &snd_render_data,
}; };
static plugin_t plugin_info = { static plugin_t plugin_info = {

View file

@ -219,8 +219,7 @@ SND_PaintChannels (unsigned int endtime)
ch->end = ltime + ch->sfx->length - ch->pos; ch->end = ltime + ch->sfx->length - ch->pos;
} else { // channel just stopped } else { // channel just stopped
ch->sfx->release (ch->sfx); ch->sfx->release (ch->sfx);
ch->sfx->close (ch->sfx); SND_ChannelStop (ch);
ch->sfx = NULL;
break; break;
} }
} }

View file

@ -185,10 +185,10 @@ S_Update (const vec3_t origin, const vec3_t v_forward, const vec3_t v_right,
} }
VISIBLE void VISIBLE void
S_StopAllSounds (qboolean clear) S_StopAllSounds (void)
{ {
if (snd_render_funcs) if (snd_render_funcs)
snd_render_funcs->pS_StopAllSounds (clear); snd_render_funcs->pS_StopAllSounds ();
} }
VISIBLE void VISIBLE void

View file

@ -202,7 +202,7 @@ void
CL_Disconnect (void) CL_Disconnect (void)
{ {
// stop sounds (especially looping!) // stop sounds (especially looping!)
S_StopAllSounds (true); S_StopAllSounds ();
// Clean the Cshifts // Clean the Cshifts
CL_StopCshifts (); CL_StopCshifts ();

View file

@ -268,7 +268,7 @@ CL_ParseServerInfo (void)
Con_DPrintf ("Serverinfo packet received.\n"); Con_DPrintf ("Serverinfo packet received.\n");
S_BlockSound (); S_BlockSound ();
S_StopAllSounds (true); S_StopAllSounds ();
// wipe the client_state_t struct // wipe the client_state_t struct
CL_ClearState (); CL_ClearState ();

View file

@ -393,7 +393,7 @@ CL_ClearState (void)
{ {
int i; int i;
S_StopAllSounds (true); S_StopAllSounds ();
// wipe the entire cl structure // wipe the entire cl structure
Info_Destroy (cl.serverinfo); Info_Destroy (cl.serverinfo);
@ -472,7 +472,7 @@ CL_Disconnect (void)
VID_SetCaption ("Disconnected"); VID_SetCaption ("Disconnected");
// stop sounds (especially looping!) // stop sounds (especially looping!)
S_StopAllSounds (true); S_StopAllSounds ();
// Clean the Cshifts // Clean the Cshifts
CL_StopCshifts (); CL_StopCshifts ();
@ -794,7 +794,7 @@ CL_Changing_f (void)
if (cls.download) // don't change when downloading if (cls.download) // don't change when downloading
return; return;
S_StopAllSounds (true); S_StopAllSounds ();
cl.intermission = 0; cl.intermission = 0;
r_force_fullscreen = 0; r_force_fullscreen = 0;
CL_SetState (ca_connected); // not active anymore, but not CL_SetState (ca_connected); // not active anymore, but not
@ -815,7 +815,7 @@ CL_Reconnect_f (void)
if (cls.demoplayback) if (cls.demoplayback)
return; return;
S_StopAllSounds (true); S_StopAllSounds ();
if (cls.state == ca_connected) { if (cls.state == ca_connected) {
Con_Printf ("reconnecting...\n"); Con_Printf ("reconnecting...\n");