mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-30 20:50:42 +00:00
whee, lockless channel management. still have a problem with unbalanced retain/release, though.
This commit is contained in:
parent
25fdbdab58
commit
5a0e2460a3
7 changed files with 185 additions and 67 deletions
|
@ -51,6 +51,7 @@ struct sfx_s
|
||||||
|
|
||||||
struct sfxbuffer_s *(*touch) (sfx_t *sfx);
|
struct sfxbuffer_s *(*touch) (sfx_t *sfx);
|
||||||
struct sfxbuffer_s *(*retain) (sfx_t *sfx);
|
struct sfxbuffer_s *(*retain) (sfx_t *sfx);
|
||||||
|
struct sfxbuffer_s *(*getbuffer) (sfx_t *sfx);
|
||||||
struct wavinfo_s *(*wavinfo) (sfx_t *sfx);
|
struct wavinfo_s *(*wavinfo) (sfx_t *sfx);
|
||||||
sfx_t *(*open) (sfx_t *sfx);
|
sfx_t *(*open) (sfx_t *sfx);
|
||||||
void (*close) (sfx_t *sfx);
|
void (*close) (sfx_t *sfx);
|
||||||
|
|
|
@ -160,11 +160,13 @@ struct sfxblock_s {
|
||||||
void *file; //!< handle for "file" representing the block
|
void *file; //!< handle for "file" representing the block
|
||||||
wavinfo_t wavinfo; //!< description of sound data
|
wavinfo_t wavinfo; //!< description of sound data
|
||||||
cache_user_t cache; //!< cached sound buffer (::sfxbuffer_s)
|
cache_user_t cache; //!< cached sound buffer (::sfxbuffer_s)
|
||||||
|
sfxbuffer_t *buffer; //!< pointer to cached buffer
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Representation of a sound being played.
|
/** Representation of a sound being played.
|
||||||
*/
|
*/
|
||||||
struct channel_s {
|
struct channel_s {
|
||||||
|
struct channel_s *next; //!< next channel in "free" list
|
||||||
sfx_t *sfx; //!< sound played by this channel
|
sfx_t *sfx; //!< sound played by this channel
|
||||||
int leftvol; //!< 0-255 volume
|
int leftvol; //!< 0-255 volume
|
||||||
int rightvol; //!< 0-255 volume
|
int rightvol; //!< 0-255 volume
|
||||||
|
@ -180,12 +182,18 @@ struct channel_s {
|
||||||
int oldphase; //!< phase shift between l-r in samples
|
int oldphase; //!< phase shift between l-r in samples
|
||||||
/** signal between main program and mixer thread that the channel is to be
|
/** signal between main program and mixer thread that the channel is to be
|
||||||
stopped.
|
stopped.
|
||||||
- 0 normal operation
|
- both \c stop and \c done are zero: normal operation
|
||||||
- 1 signal from main program to mixer the channel is to be stopped
|
- \c stop is non-zero: main program is done with channel. must wait
|
||||||
- 2 signal from the mixer to the main program indicating the mixer is
|
for mixer to finish with channel before re-using.
|
||||||
done with the channel and the main program is free to clear it.
|
- \c done is non-zero: mixer is done with channel. can be reused at
|
||||||
|
any time.
|
||||||
|
- both \c stop and \c done are non-zero: both are done with channel.
|
||||||
|
can be reused at any time.
|
||||||
*/
|
*/
|
||||||
int stopped;
|
//@{
|
||||||
|
int stop;
|
||||||
|
int done;
|
||||||
|
//@}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct cvar_s *snd_loadas8bit;
|
extern struct cvar_s *snd_loadas8bit;
|
||||||
|
@ -269,8 +277,9 @@ void SND_SFX_Init (void);
|
||||||
static sounds
|
static sounds
|
||||||
*/
|
*/
|
||||||
//@{
|
//@{
|
||||||
#define MAX_CHANNELS 256 //!< number of available mixing channels
|
#define MAX_CHANNELS 512 //!< number of available mixing channels
|
||||||
#define MAX_DYNAMIC_CHANNELS 8 //!< number of dynamic channels
|
#define MAX_DYNAMIC_CHANNELS 8 //!< number of dynamic channels
|
||||||
|
#define MAX_STATIC_CHANNELS 256 //!< number of static 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
|
||||||
|
|
||||||
|
@ -458,17 +467,33 @@ wavinfo_t *SND_StreamWavinfo (sfx_t *sfx);
|
||||||
*/
|
*/
|
||||||
sfxbuffer_t *SND_CacheTouch (sfx_t *sfx);
|
sfxbuffer_t *SND_CacheTouch (sfx_t *sfx);
|
||||||
|
|
||||||
/** Lock a cached sound into memory.
|
/** Get the pointer to the sound buffer.
|
||||||
|
\param sfx sound reference
|
||||||
|
\return sound buffer or null
|
||||||
|
\note The sound must be retained with SND_CacheRetain() for the returned
|
||||||
|
buffer to be valid.
|
||||||
|
*/
|
||||||
|
sfxbuffer_t *SND_CacheGetBuffer (sfx_t *sfx);
|
||||||
|
|
||||||
|
/** Lock a cached sound into memory. After calling this, SND_CacheGetBffer()
|
||||||
|
will return a valid buffer.
|
||||||
\param sfx sound reference
|
\param sfx sound reference
|
||||||
\return poitner to sound buffer
|
\return poitner to sound buffer
|
||||||
*/
|
*/
|
||||||
sfxbuffer_t *SND_CacheRetain (sfx_t *sfx);
|
sfxbuffer_t *SND_CacheRetain (sfx_t *sfx);
|
||||||
|
|
||||||
/** Unlock a cached sound from memory.
|
/** Unlock a cached sound from memory. After calling this, SND_CacheGetBffer()
|
||||||
|
will return a null buffer.
|
||||||
\param sfx sound reference
|
\param sfx sound reference
|
||||||
*/
|
*/
|
||||||
void SND_CacheRelease (sfx_t *sfx);
|
void SND_CacheRelease (sfx_t *sfx);
|
||||||
|
|
||||||
|
/** Get the pointer to the sound buffer.
|
||||||
|
\param sfx sound reference
|
||||||
|
\return poitner to sound buffer
|
||||||
|
*/
|
||||||
|
sfxbuffer_t *SND_StreamGetBuffer (sfx_t *sfx);
|
||||||
|
|
||||||
/** Lock a streamed sound into memory. Doesn't actually do anything other than
|
/** Lock a streamed sound into memory. Doesn't actually do anything other than
|
||||||
return a pointer to the buffer.
|
return a pointer to the buffer.
|
||||||
\param sfx sound reference
|
\param sfx sound reference
|
||||||
|
|
|
@ -48,12 +48,13 @@ static __attribute__ ((used)) const char rcsid[] =
|
||||||
|
|
||||||
#include "snd_render.h"
|
#include "snd_render.h"
|
||||||
|
|
||||||
|
static channel_t *free_channels;
|
||||||
channel_t snd_channels[MAX_CHANNELS];
|
channel_t snd_channels[MAX_CHANNELS];
|
||||||
int snd_total_channels;
|
int snd_total_channels;
|
||||||
|
|
||||||
static channel_t *ambient_channels[NUM_AMBIENTS];
|
static channel_t *ambient_channels[NUM_AMBIENTS];
|
||||||
static channel_t *dynamic_channels[MAX_DYNAMIC_CHANNELS];
|
static channel_t *dynamic_channels[MAX_DYNAMIC_CHANNELS];
|
||||||
static channel_t *static_channels[MAX_CHANNELS];
|
static channel_t *static_channels[MAX_STATIC_CHANNELS];
|
||||||
static int snd_num_statics;
|
static int snd_num_statics;
|
||||||
|
|
||||||
static qboolean snd_ambient = 1;
|
static qboolean snd_ambient = 1;
|
||||||
|
@ -75,19 +76,45 @@ static cvar_t *ambient_level;
|
||||||
channel_t *
|
channel_t *
|
||||||
SND_AllocChannel (void)
|
SND_AllocChannel (void)
|
||||||
{
|
{
|
||||||
if (snd_total_channels < MAX_CHANNELS)
|
channel_t **free = &free_channels;
|
||||||
return &snd_channels[snd_total_channels++];
|
channel_t *chan;
|
||||||
return 0;
|
|
||||||
|
if (!*free) // definitely nothing free
|
||||||
|
return 0;
|
||||||
|
while (*free) {
|
||||||
|
if (!(*free)->sfx) // free channel
|
||||||
|
break;
|
||||||
|
if ((*free)->done) // mixer is finished with this channel
|
||||||
|
break;
|
||||||
|
if (!(*free)->stop)
|
||||||
|
Sys_Error ("SND_AllocChannel: bogus channel free list");
|
||||||
|
free = &(*free)->next;
|
||||||
|
}
|
||||||
|
if (!*free)
|
||||||
|
return 0;
|
||||||
|
chan = *free;
|
||||||
|
*free = chan->next;
|
||||||
|
if (chan->sfx) {
|
||||||
|
chan->sfx->release (chan->sfx);
|
||||||
|
chan->sfx->close (chan->sfx);
|
||||||
|
chan->sfx = 0; // make sure mixer doesn't use channel during memset
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (chan, 0, sizeof (*chan));
|
||||||
|
chan->next = 0;
|
||||||
|
chan->sfx = 0;
|
||||||
|
|
||||||
|
return chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SND_ChannelStop (channel_t *chan)
|
SND_ChannelStop (channel_t *chan)
|
||||||
{
|
{
|
||||||
chan->end = 0;
|
if (chan->next)
|
||||||
if (chan->sfx) {
|
*(int*)0=0;
|
||||||
chan->sfx->close (chan->sfx);
|
chan->stop = 1;
|
||||||
}
|
chan->next = free_channels;
|
||||||
chan->sfx = 0;
|
free_channels = chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -97,9 +124,14 @@ SND_StopAllSounds (void)
|
||||||
|
|
||||||
snd_num_statics = 0;
|
snd_num_statics = 0;
|
||||||
for (i = 0; i < MAX_CHANNELS; i++)
|
for (i = 0; i < MAX_CHANNELS; i++)
|
||||||
SND_ChannelStop (&snd_channels[i]);
|
if (snd_channels[i].sfx && !snd_channels[i].stop)
|
||||||
|
SND_ChannelStop (&snd_channels[i]);
|
||||||
memset (snd_channels, 0, MAX_CHANNELS * sizeof (channel_t));
|
for (i = 0; i < NUM_AMBIENTS; i++)
|
||||||
|
ambient_channels[i] = 0;
|
||||||
|
for (i = 0; i < MAX_DYNAMIC_CHANNELS; i++)
|
||||||
|
dynamic_channels[i] = 0;
|
||||||
|
for (i = 0; i < MAX_STATIC_CHANNELS; i++)
|
||||||
|
static_channels[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -192,10 +224,10 @@ SND_Channels_Init (void)
|
||||||
Cmd_AddCommand ("playvol", s_playvol_f, "Play selected sound effect at "
|
Cmd_AddCommand ("playvol", s_playvol_f, "Play selected sound effect at "
|
||||||
"selected volume (playvol pathto/sound.wav num");
|
"selected volume (playvol pathto/sound.wav num");
|
||||||
|
|
||||||
for (i = 0; i < NUM_AMBIENTS; i++)
|
for (i = 0; i < MAX_CHANNELS - 1; i++)
|
||||||
ambient_channels[i] = SND_AllocChannel ();
|
snd_channels[i].next = &snd_channels[i + 1];
|
||||||
for (i = 0; i < MAX_DYNAMIC_CHANNELS; i++)
|
free_channels = &snd_channels[0];
|
||||||
dynamic_channels[i] = SND_AllocChannel ();
|
snd_total_channels = MAX_CHANNELS;
|
||||||
|
|
||||||
snd_num_statics = 0;
|
snd_num_statics = 0;
|
||||||
|
|
||||||
|
@ -206,40 +238,54 @@ SND_Channels_Init (void)
|
||||||
static channel_t *
|
static channel_t *
|
||||||
s_pick_channel (int entnum, int entchannel)
|
s_pick_channel (int entnum, int entchannel)
|
||||||
{
|
{
|
||||||
int ch_idx;
|
int best, i;
|
||||||
unsigned life_left;
|
unsigned life_left;
|
||||||
channel_t *ch, *first_to_die;
|
channel_t *ch;
|
||||||
|
|
||||||
// Check for replacement sound, or find the best one to replace
|
for (i = 0; i < MAX_DYNAMIC_CHANNELS; i++) {
|
||||||
first_to_die = 0;
|
ch = dynamic_channels[i];
|
||||||
|
if (ch) {
|
||||||
|
if (ch->done) {
|
||||||
|
SND_ChannelStop (ch);
|
||||||
|
dynamic_channels[i] = ch = 0;
|
||||||
|
} else if (!ch->sfx) {
|
||||||
|
dynamic_channels[i] = ch = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ch) {
|
||||||
|
dynamic_channels[i] = ch = SND_AllocChannel ();
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
best = -1;
|
||||||
life_left = 0x7fffffff;
|
life_left = 0x7fffffff;
|
||||||
for (ch_idx = 0; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++) {
|
for (i = 0; i < MAX_DYNAMIC_CHANNELS; i++) {
|
||||||
ch = dynamic_channels[ch_idx];
|
ch = dynamic_channels[i];
|
||||||
if (entchannel != 0 // channel 0 never overrides
|
if (entchannel == 0) // channel 0 never overrides
|
||||||
&& ch->entnum == entnum
|
continue;
|
||||||
|
if (ch->entnum == entnum
|
||||||
&& (ch->entchannel == entchannel || entchannel == -1)) {
|
&& (ch->entchannel == entchannel || entchannel == -1)) {
|
||||||
// always override sound from same entity
|
best = i;
|
||||||
first_to_die = ch;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// don't let monster sounds override player sounds
|
// don't let monster sounds override player sounds
|
||||||
if (ch->entnum == *snd_render_data.viewentity
|
if (ch->entnum == *snd_render_data.viewentity
|
||||||
&& entnum != *snd_render_data.viewentity
|
&& entnum != *snd_render_data.viewentity)
|
||||||
&& ch->sfx)
|
|
||||||
continue;
|
continue;
|
||||||
|
if (ch->end - snd_paintedtime < life_left) {
|
||||||
if (snd_paintedtime + life_left > ch->end) {
|
|
||||||
life_left = ch->end - snd_paintedtime;
|
life_left = ch->end - snd_paintedtime;
|
||||||
first_to_die = ch;
|
best = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!first_to_die)
|
if (best == -1)
|
||||||
return NULL;
|
return 0;
|
||||||
|
|
||||||
SND_ChannelStop (first_to_die);
|
SND_ChannelStop (dynamic_channels[best]);
|
||||||
|
dynamic_channels[best] = SND_AllocChannel ();
|
||||||
|
|
||||||
return first_to_die;
|
return dynamic_channels[best];
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -276,6 +322,7 @@ s_updateAmbientSounds (void)
|
||||||
for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
|
for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
|
||||||
ambient_channel++) {
|
ambient_channel++) {
|
||||||
SND_ChannelStop (ambient_channels[ambient_channel]);
|
SND_ChannelStop (ambient_channels[ambient_channel]);
|
||||||
|
ambient_channels[ambient_channel] = 0;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -283,12 +330,29 @@ s_updateAmbientSounds (void)
|
||||||
for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
|
for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
|
||||||
ambient_channel++) {
|
ambient_channel++) {
|
||||||
chan = ambient_channels[ambient_channel];
|
chan = ambient_channels[ambient_channel];
|
||||||
|
if (chan && chan->done) {
|
||||||
|
SND_ChannelStop (chan);
|
||||||
|
chan = ambient_channels[ambient_channel] = 0;
|
||||||
|
}
|
||||||
sfx = ambient_sfx[ambient_channel];
|
sfx = ambient_sfx[ambient_channel];
|
||||||
if (!sfx) {
|
if (!sfx) {
|
||||||
SND_ChannelStop (chan);
|
if (chan && chan->sfx && !chan->stop)
|
||||||
|
SND_ChannelStop (chan);
|
||||||
|
ambient_channels[ambient_channel] = 0;
|
||||||
continue;
|
continue;
|
||||||
} else if (!chan->sfx)
|
}
|
||||||
chan->sfx = sfx->open (sfx);
|
|
||||||
|
if (!chan)
|
||||||
|
chan = ambient_channels[ambient_channel] = SND_AllocChannel ();
|
||||||
|
if (!chan)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!chan->sfx)
|
||||||
|
sfx = sfx->open (sfx);
|
||||||
|
else
|
||||||
|
sfx = chan->sfx;
|
||||||
|
// sfx will be written to chan->sfx later to ensure mixer doesn't use
|
||||||
|
// channel prematurely.
|
||||||
|
|
||||||
vol = ambient_level->value * l->ambient_sound_level[ambient_channel];
|
vol = ambient_level->value * l->ambient_sound_level[ambient_channel];
|
||||||
if (vol < 8)
|
if (vol < 8)
|
||||||
|
@ -308,6 +372,7 @@ s_updateAmbientSounds (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
chan->leftvol = chan->rightvol = chan->master_vol;
|
chan->leftvol = chan->rightvol = chan->master_vol;
|
||||||
|
chan->sfx = sfx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,7 +461,8 @@ SND_SetListener (const vec3_t origin, const vec3_t forward, const vec3_t right,
|
||||||
|
|
||||||
// update spatialization for dynamic sounds
|
// update spatialization for dynamic sounds
|
||||||
for (i = 0; i < MAX_DYNAMIC_CHANNELS; i++)
|
for (i = 0; i < MAX_DYNAMIC_CHANNELS; i++)
|
||||||
s_update_channel (dynamic_channels[i]);
|
if (dynamic_channels[i])
|
||||||
|
s_update_channel (dynamic_channels[i]);
|
||||||
|
|
||||||
// update spatialization for static sounds
|
// update spatialization for static sounds
|
||||||
combine = 0;
|
combine = 0;
|
||||||
|
@ -436,6 +502,7 @@ SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
|
||||||
int ch_idx, vol;
|
int ch_idx, vol;
|
||||||
unsigned int skip;
|
unsigned int skip;
|
||||||
channel_t *target_chan, *check;
|
channel_t *target_chan, *check;
|
||||||
|
sfx_t *osfx;
|
||||||
|
|
||||||
if (!sfx)
|
if (!sfx)
|
||||||
return;
|
return;
|
||||||
|
@ -459,26 +526,23 @@ SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
|
||||||
return; // not audible at all
|
return; // not audible at all
|
||||||
|
|
||||||
// new channel
|
// new channel
|
||||||
if (!sfx->retain (sfx)) {
|
if (!sfx->retain (sfx))
|
||||||
SND_ChannelStop (target_chan);
|
|
||||||
return; // couldn't load the sound's data
|
return; // couldn't load the sound's data
|
||||||
}
|
|
||||||
|
|
||||||
if (!(target_chan->sfx = sfx->open (sfx))) {
|
if (!(osfx = sfx->open (sfx))) {
|
||||||
sfx->release (sfx);
|
sfx->release (sfx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
target_chan->pos = 0.0;
|
target_chan->pos = 0.0;
|
||||||
target_chan->end = snd_paintedtime + target_chan->sfx->length;
|
target_chan->end = snd_paintedtime + osfx->length;
|
||||||
sfx->release (sfx);
|
|
||||||
|
|
||||||
// if an identical sound has also been started this frame, offset the pos
|
// 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
|
// a bit to keep it from just making the first one louder
|
||||||
for (ch_idx = 0; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++) {
|
for (ch_idx = 0; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++) {
|
||||||
check = dynamic_channels[ch_idx];
|
check = dynamic_channels[ch_idx];
|
||||||
if (check == target_chan)
|
if (!check || check == target_chan)
|
||||||
continue;
|
continue;
|
||||||
if (check->sfx == sfx && !check->pos) {
|
if (check->sfx == osfx && !check->pos) {
|
||||||
skip = rand () % (int) (0.1 * snd_shm->speed);
|
skip = rand () % (int) (0.1 * snd_shm->speed);
|
||||||
if (skip >= target_chan->end)
|
if (skip >= target_chan->end)
|
||||||
skip = target_chan->end - 1;
|
skip = target_chan->end - 1;
|
||||||
|
@ -487,6 +551,7 @@ SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
target_chan->sfx = osfx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -500,6 +565,7 @@ SND_StopSound (int entnum, int entchannel)
|
||||||
if (ch->entnum == entnum && ch->entchannel == entchannel) {
|
if (ch->entnum == entnum && ch->entchannel == entchannel) {
|
||||||
ch->end = 0;
|
ch->end = 0;
|
||||||
SND_ChannelStop (ch);
|
SND_ChannelStop (ch);
|
||||||
|
dynamic_channels[i] = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,6 +576,7 @@ SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol,
|
||||||
float attenuation)
|
float attenuation)
|
||||||
{
|
{
|
||||||
channel_t *ss;
|
channel_t *ss;
|
||||||
|
sfx_t *osfx;
|
||||||
|
|
||||||
if (!sfx)
|
if (!sfx)
|
||||||
return;
|
return;
|
||||||
|
@ -532,7 +599,7 @@ SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ss->sfx = sfx->open (sfx))) {
|
if (!(osfx = sfx->open (sfx))) {
|
||||||
sfx->release (sfx);
|
sfx->release (sfx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -540,11 +607,12 @@ SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol,
|
||||||
ss->master_vol = vol;
|
ss->master_vol = vol;
|
||||||
ss->dist_mult = (attenuation / 64) / sound_nominal_clip_dist;
|
ss->dist_mult = (attenuation / 64) / sound_nominal_clip_dist;
|
||||||
ss->end = snd_paintedtime + sfx->length;
|
ss->end = snd_paintedtime + sfx->length;
|
||||||
sfx->release (sfx);
|
|
||||||
|
|
||||||
s_spatialize (ss);
|
s_spatialize (ss);
|
||||||
ss->oldphase = ss->phase;
|
ss->oldphase = ss->phase;
|
||||||
snd_num_statics++;
|
snd_num_statics++;
|
||||||
|
|
||||||
|
ss->sfx = osfx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -83,16 +83,32 @@ SND_CacheTouch (sfx_t *sfx)
|
||||||
return Cache_Check (&((sfxblock_t *) sfx->data)->cache);
|
return Cache_Check (&((sfxblock_t *) sfx->data)->cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sfxbuffer_t *
|
||||||
|
SND_CacheGetBuffer (sfx_t *sfx)
|
||||||
|
{
|
||||||
|
return ((sfxblock_t *) sfx->data)->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
sfxbuffer_t *
|
sfxbuffer_t *
|
||||||
SND_CacheRetain (sfx_t *sfx)
|
SND_CacheRetain (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
return Cache_TryGet (&((sfxblock_t *) sfx->data)->cache);
|
sfxblock_t *block = (sfxblock_t *) sfx->data;
|
||||||
|
block->buffer = Cache_TryGet (&block->cache);
|
||||||
|
return block->buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SND_CacheRelease (sfx_t *sfx)
|
SND_CacheRelease (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
Cache_Release (&((sfxblock_t *) sfx->data)->cache);
|
sfxblock_t *block = (sfxblock_t *) sfx->data;
|
||||||
|
block->buffer = 0;
|
||||||
|
Cache_Release (&block->cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
sfxbuffer_t *
|
||||||
|
SND_StreamGetBuffer (sfx_t *sfx)
|
||||||
|
{
|
||||||
|
return &((sfxstream_t *) sfx->data)->buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
sfxbuffer_t *
|
sfxbuffer_t *
|
||||||
|
|
|
@ -78,9 +78,14 @@ SND_PaintChannels (unsigned int endtime)
|
||||||
for (i = 0; i < snd_total_channels; i++, ch++) {
|
for (i = 0; i < snd_total_channels; i++, ch++) {
|
||||||
if (!ch->sfx)
|
if (!ch->sfx)
|
||||||
continue;
|
continue;
|
||||||
|
if (ch->stop) {
|
||||||
|
if (!ch->done)
|
||||||
|
ch->done = 1; // acknowledge stopped signal
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!ch->leftvol && !ch->rightvol)
|
if (!ch->leftvol && !ch->rightvol)
|
||||||
continue;
|
continue;
|
||||||
sc = ch->sfx->retain (ch->sfx);
|
sc = ch->sfx->getbuffer (ch->sfx);
|
||||||
if (!sc)
|
if (!sc)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -102,20 +107,18 @@ SND_PaintChannels (unsigned int endtime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if at end of loop, restart
|
// if at end of loop, restart
|
||||||
if (ltime >= ch->end) {
|
if (!count || ltime >= ch->end) {
|
||||||
if (ch->sfx->loopstart != (unsigned int) -1) {
|
if (ch->sfx->loopstart != (unsigned int) -1) {
|
||||||
ch->pos = ch->sfx->loopstart;
|
ch->pos = ch->sfx->loopstart;
|
||||||
ch->end = ltime + ch->sfx->length - ch->pos;
|
ch->end = ltime + ch->sfx->length - ch->pos;
|
||||||
|
ch->done = 2;
|
||||||
|
break;
|
||||||
} else { // channel just stopped
|
} else { // channel just stopped
|
||||||
ch->sfx->release (ch->sfx);
|
ch->done = 2;
|
||||||
SND_ChannelStop (ch);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch->sfx)
|
|
||||||
ch->sfx->release (ch->sfx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// transfer out according to DMA format
|
// transfer out according to DMA format
|
||||||
|
|
|
@ -91,9 +91,9 @@ SND_ResampleMono (sfxbuffer_t *sc, byte *data, int length, void *prev)
|
||||||
stepscale = (float) inrate / snd_shm->speed;
|
stepscale = (float) inrate / snd_shm->speed;
|
||||||
|
|
||||||
outcount = length / stepscale;
|
outcount = length / stepscale;
|
||||||
// printf ("%d %d\n", length, outcount);
|
|
||||||
|
|
||||||
sc->sfx->length = info->samples / stepscale;
|
sc->sfx->length = info->samples / stepscale;
|
||||||
|
//printf ("%s %d %g %d\n", sc->sfx->name, length, stepscale, sc->sfx->length);
|
||||||
if (info->loopstart != (unsigned int)-1)
|
if (info->loopstart != (unsigned int)-1)
|
||||||
sc->sfx->loopstart = info->loopstart / stepscale;
|
sc->sfx->loopstart = info->loopstart / stepscale;
|
||||||
else
|
else
|
||||||
|
|
|
@ -83,6 +83,7 @@ SND_SFX_Cache (sfx_t *sfx, char *realname, wavinfo_t info,
|
||||||
sfx->touch = SND_CacheTouch;
|
sfx->touch = SND_CacheTouch;
|
||||||
sfx->retain = SND_CacheRetain;
|
sfx->retain = SND_CacheRetain;
|
||||||
sfx->release = SND_CacheRelease;
|
sfx->release = SND_CacheRelease;
|
||||||
|
sfx->getbuffer = SND_CacheGetBuffer;
|
||||||
|
|
||||||
block->sfx = sfx;
|
block->sfx = sfx;
|
||||||
block->file = realname;
|
block->file = realname;
|
||||||
|
@ -100,6 +101,7 @@ SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info,
|
||||||
sfx->wavinfo = SND_CacheWavinfo;
|
sfx->wavinfo = SND_CacheWavinfo;
|
||||||
sfx->touch = sfx->retain = SND_StreamRetain;
|
sfx->touch = sfx->retain = SND_StreamRetain;
|
||||||
sfx->release = SND_StreamRelease;
|
sfx->release = SND_StreamRelease;
|
||||||
|
sfx->getbuffer = SND_StreamGetBuffer;
|
||||||
sfx->data = stream;
|
sfx->data = stream;
|
||||||
|
|
||||||
stream->file = realname;
|
stream->file = realname;
|
||||||
|
@ -123,6 +125,7 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
||||||
new_sfx->wavinfo = SND_CacheWavinfo;
|
new_sfx->wavinfo = SND_CacheWavinfo;
|
||||||
new_sfx->touch = new_sfx->retain = SND_StreamRetain;
|
new_sfx->touch = new_sfx->retain = SND_StreamRetain;
|
||||||
new_sfx->release = SND_StreamRelease;
|
new_sfx->release = SND_StreamRelease;
|
||||||
|
new_sfx->getbuffer = SND_StreamGetBuffer;
|
||||||
new_sfx->close = close;
|
new_sfx->close = close;
|
||||||
|
|
||||||
samples = snd_shm->speed * 0.3;
|
samples = snd_shm->speed * 0.3;
|
||||||
|
@ -142,6 +145,8 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
||||||
stream->read = read;
|
stream->read = read;
|
||||||
stream->seek = seek;
|
stream->seek = seek;
|
||||||
|
|
||||||
|
stream->wavinfo = *sfx->wavinfo (sfx);
|
||||||
|
|
||||||
stream->buffer.length = samples;
|
stream->buffer.length = samples;
|
||||||
stream->buffer.advance = SND_StreamAdvance;
|
stream->buffer.advance = SND_StreamAdvance;
|
||||||
stream->buffer.setpos = SND_StreamSetPos;
|
stream->buffer.setpos = SND_StreamSetPos;
|
||||||
|
|
Loading…
Reference in a new issue