summaryrefslogtreecommitdiff
path: root/src/s_sound.c
diff options
context:
space:
mode:
authorSimon Howard2007-06-16 16:04:00 +0000
committerSimon Howard2007-06-16 16:04:00 +0000
commite91f243989fc8f617ad89fd41b2887174c39e817 (patch)
treebca962387be615175423635ec617a83cf4afafc7 /src/s_sound.c
parent304a0037773d8dde95ee912b8b7e67f314a7c53e (diff)
downloadchocolate-doom-e91f243989fc8f617ad89fd41b2887174c39e817.tar.gz
chocolate-doom-e91f243989fc8f617ad89fd41b2887174c39e817.tar.bz2
chocolate-doom-e91f243989fc8f617ad89fd41b2887174c39e817.zip
Clean up sound code
Subversion-branch: /trunk/chocolate-doom Subversion-revision: 911
Diffstat (limited to 'src/s_sound.c')
-rw-r--r--src/s_sound.c1129
1 files changed, 493 insertions, 636 deletions
diff --git a/src/s_sound.c b/src/s_sound.c
index 56cb18c9..1477415e 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -23,10 +23,6 @@
//
//-----------------------------------------------------------------------------
-
-
-
-
#include <stdio.h>
#include <stdlib.h>
@@ -45,42 +41,30 @@
#include "doomstat.h"
-
-// Purpose?
-const char snd_prefixen[]
-= { 'P', 'P', 'A', 'S', 'S', 'S', 'M', 'M', 'M', 'S', 'S', 'S' };
-
-#define S_MAX_VOLUME 127
-
// when to clip out sounds
// Does not fit the large outdoor areas.
-#define S_CLIPPING_DIST (1200*0x10000)
+
+#define S_CLIPPING_DIST (1200 * FRACUNIT)
// Distance tp origin when sounds should be maxed out.
// This should relate to movement clipping resolution
// (see BLOCKMAP handling).
-// In the source code release: (160*0x10000). Changed back to the
+// In the source code release: (160*FRACUNIT). Changed back to the
// Vanilla value of 200 (why was this changed?)
-#define S_CLOSE_DIST (200*0x10000)
-
-#define S_ATTENUATOR ((S_CLIPPING_DIST-S_CLOSE_DIST)>>FRACBITS)
+#define S_CLOSE_DIST (200 * FRACUNIT)
-// Adjustable by menu.
-#define NORM_VOLUME snd_MaxVolume
+// The range over which sound attenuates
-#define NORM_PITCH 128
-#define NORM_PRIORITY 64
-#define NORM_SEP 128
+#define S_ATTENUATOR ((S_CLIPPING_DIST - S_CLOSE_DIST) >> FRACBITS)
-#define S_PITCH_PERTURB 1
-#define S_STEREO_SWING (96*0x10000)
+// Stereo separation
-// percent attenuation from front to back
-#define S_IFRACVOL 30
+#define S_STEREO_SWING (96 * FRACUNIT)
-#define NA 0
-#define S_NUMCHANNELS 2
+#define NORM_PITCH 128
+#define NORM_PRIORITY 64
+#define NORM_SEP 128
// Disable music on OSX by default; there are problems with SDL_mixer.
@@ -97,403 +81,476 @@ int snd_sfxdevice = SNDDEVICE_SB;
typedef struct
{
// sound information (if null, channel avail.)
- sfxinfo_t* sfxinfo;
+ sfxinfo_t *sfxinfo;
// origin of sound
- void* origin;
+ mobj_t *origin;
// handle of the sound being played
- int handle;
+ int handle;
} channel_t;
-// the set of channels available
-static channel_t* channels;
+// The set of channels available
+
+static channel_t *channels;
// Maximum volume of a sound effect.
// Internal default is max out of 0-15.
+
int sfxVolume = 8;
// Maximum volume of music.
+
int musicVolume = 8;
// Internal volume level, ranging from 0-127
-static int snd_SfxVolume;
-
-// whether songs are mus_paused
-static boolean mus_paused;
+static int snd_SfxVolume;
-// music currently being played
-static musicinfo_t* mus_playing=0;
+// Whether songs are mus_paused
-// following is set
-// by the defaults code in M_misc:
-// number of channels available
+static boolean mus_paused;
-int numChannels = 8;
+// Music currently being played
-static int nextcleanup;
+static musicinfo_t *mus_playing = NULL;
+// Number of channels to use
+int numChannels = 8;
//
-// Internals.
+// Initializes sound stuff, including volume
+// Sets channels, SFX and music volume,
+// allocates channel buffer, sets S_sfx lookup.
//
-int
-S_getChannel
-( void* origin,
- sfxinfo_t* sfxinfo );
+void S_Init(int sfxVolume, int musicVolume)
+{
+ int i;
-int
-S_AdjustSoundParams
-( mobj_t* listener,
- mobj_t* source,
- int* vol,
- int* sep,
- int* pitch );
+ I_InitSound();
-void S_StopChannel(int cnum);
+ S_SetSfxVolume(sfxVolume);
+ S_SetMusicVolume(musicVolume);
+ // Allocating the internal channels for mixing
+ // (the maximum numer of sounds rendered
+ // simultaneously) within zone memory.
+ channels = Z_Malloc(numChannels*sizeof(channel_t), PU_STATIC, 0);
+ // Free all channels for use
+ for (i=0 ; i<numChannels ; i++)
+ {
+ channels[i].sfxinfo = 0;
+ }
-//
-// Initializes sound stuff, including volume
-// Sets channels, SFX and music volume,
-// allocates channel buffer, sets S_sfx lookup.
-//
-void S_Init
-( int sfxVolume,
- int musicVolume )
-{
- int i;
-
- I_InitSound();
-
- // Whatever these did with DMX, these are rather dummies now.
- I_SetChannels();
-
- S_SetSfxVolume(sfxVolume);
- // No music with Linux - another dummy.
- S_SetMusicVolume(musicVolume);
-
- // Allocating the internal channels for mixing
- // (the maximum numer of sounds rendered
- // simultaneously) within zone memory.
- channels =
- (channel_t *) Z_Malloc(numChannels*sizeof(channel_t), PU_STATIC, 0);
-
- // Free all channels for use
- for (i=0 ; i<numChannels ; i++)
- channels[i].sfxinfo = 0;
-
- // no sounds are playing, and they are not mus_paused
- mus_paused = 0;
-
- // Note that sounds have not been cached (yet).
- for (i=1 ; i<NUMSFX ; i++)
- S_sfx[i].lumpnum = S_sfx[i].usefulness = -1;
-}
+ // no sounds are playing, and they are not mus_paused
+ mus_paused = 0;
+ // Note that sounds have not been cached (yet).
+ for (i=1 ; i<NUMSFX ; i++)
+ {
+ S_sfx[i].lumpnum = S_sfx[i].usefulness = -1;
+ }
+}
void S_Shutdown(void)
{
- I_ShutdownSound();
+ I_ShutdownSound();
}
+static void S_StopChannel(int cnum)
+{
+ int i;
+ channel_t *c;
+
+ c = &channels[cnum];
+
+ if (c->sfxinfo)
+ {
+ // stop the sound playing
+ if (I_SoundIsPlaying(c->handle))
+ {
+ I_StopSound(c->handle);
+ }
+
+ // check to see if other channels are playing the sound
+
+ for (i=0; i<numChannels; i++)
+ {
+ if (cnum != i && c->sfxinfo == channels[i].sfxinfo)
+ {
+ break;
+ }
+ }
+
+ // degrade usefulness of sound data
+
+ c->sfxinfo->usefulness--;
+ c->sfxinfo = NULL;
+ }
+}
//
// Per level startup code.
// Kills playing sounds at start of level,
// determines music if any, changes music.
//
+
void S_Start(void)
{
- int cnum;
- int mnum;
-
- // kill all playing sounds at start of level
- // (trust me - a good idea)
- for (cnum=0 ; cnum<numChannels ; cnum++)
- if (channels[cnum].sfxinfo)
- S_StopChannel(cnum);
-
- // start new music for the level
- mus_paused = 0;
-
- if (gamemode == commercial)
- mnum = mus_runnin + gamemap - 1;
- else
- {
- int spmus[]=
- {
- // Song - Who? - Where?
-
- mus_e3m4, // American e4m1
- mus_e3m2, // Romero e4m2
- mus_e3m3, // Shawn e4m3
- mus_e1m5, // American e4m4
- mus_e2m7, // Tim e4m5
- mus_e2m4, // Romero e4m6
- mus_e2m6, // J.Anderson e4m7 CHIRON.WAD
- mus_e2m5, // Shawn e4m8
- mus_e1m9 // Tim e4m9
- };
-
- if (gameepisode < 4)
- mnum = mus_e1m1 + (gameepisode-1)*9 + gamemap-1;
+ int cnum;
+ int mnum;
+
+ // kill all playing sounds at start of level
+ // (trust me - a good idea)
+ for (cnum=0 ; cnum<numChannels ; cnum++)
+ {
+ if (channels[cnum].sfxinfo)
+ {
+ S_StopChannel(cnum);
+ }
+ }
+
+ // start new music for the level
+ mus_paused = 0;
+
+ if (gamemode == commercial)
+ {
+ mnum = mus_runnin + gamemap - 1;
+ }
else
- mnum = spmus[gamemap-1];
- }
-
- // HACK FOR COMMERCIAL
- // if (commercial && mnum > mus_e3m9)
- // mnum -= mus_e3m9;
-
- S_ChangeMusic(mnum, true);
-
- nextcleanup = 15;
-}
+ {
+ int spmus[]=
+ {
+ // Song - Who? - Where?
+
+ mus_e3m4, // American e4m1
+ mus_e3m2, // Romero e4m2
+ mus_e3m3, // Shawn e4m3
+ mus_e1m5, // American e4m4
+ mus_e2m7, // Tim e4m5
+ mus_e2m4, // Romero e4m6
+ mus_e2m6, // J.Anderson e4m7 CHIRON.WAD
+ mus_e2m5, // Shawn e4m8
+ mus_e1m9 // Tim e4m9
+ };
+
+ if (gameepisode < 4)
+ {
+ mnum = mus_e1m1 + (gameepisode-1)*9 + gamemap-1;
+ }
+ else
+ {
+ mnum = spmus[gamemap-1];
+ }
+ }
+
+ S_ChangeMusic(mnum, true);
+}
+
+void S_StopSound(mobj_t *origin)
+{
+ int cnum;
+ for (cnum=0 ; cnum<numChannels ; cnum++)
+ {
+ if (channels[cnum].sfxinfo && channels[cnum].origin == origin)
+ {
+ S_StopChannel(cnum);
+ break;
+ }
+ }
+}
+//
+// S_GetChannel :
+// If none available, return -1. Otherwise channel #.
+//
+static int S_GetChannel(mobj_t *origin, sfxinfo_t *sfxinfo)
+{
+ // channel number to use
+ int cnum;
+
+ channel_t* c;
+ // Find an open channel
+ for (cnum=0 ; cnum<numChannels ; cnum++)
+ {
+ if (!channels[cnum].sfxinfo)
+ {
+ break;
+ }
+ else if (origin && channels[cnum].origin == origin)
+ {
+ S_StopChannel(cnum);
+ break;
+ }
+ }
-void
-S_StartSoundAtVolume
-( void* origin_p,
- int sfx_id,
- int volume )
+ // None available
+ if (cnum == numChannels)
+ {
+ // Look for lower priority
+ for (cnum=0 ; cnum<numChannels ; cnum++)
+ {
+ if (channels[cnum].sfxinfo->priority >= sfxinfo->priority)
+ {
+ break;
+ }
+ }
+
+ if (cnum == numChannels)
+ {
+ // FUCK! No lower priority. Sorry, Charlie.
+ return -1;
+ }
+ else
+ {
+ // Otherwise, kick out lower priority.
+ S_StopChannel(cnum);
+ }
+ }
+
+ c = &channels[cnum];
+
+ // channel is decided to be cnum.
+ c->sfxinfo = sfxinfo;
+ c->origin = origin;
+
+ return cnum;
+}
+
+//
+// Changes volume, stereo-separation, and pitch variables
+// from the norm of a sound effect to be played.
+// If the sound is not audible, returns a 0.
+// Otherwise, modifies parameters and returns 1.
+//
+
+static int S_AdjustSoundParams(mobj_t *listener, mobj_t *source,
+ int *vol, int *sep, int *pitch)
{
+ fixed_t approx_dist;
+ fixed_t adx;
+ fixed_t ady;
+ angle_t angle;
- int rc;
- int sep;
- int pitch;
- int priority;
- sfxinfo_t* sfx;
- int cnum;
-
- mobj_t* origin = (mobj_t *) origin_p;
-
-
- // Debug.
- /*fprintf( stderr,
- "S_StartSoundAtVolume: playing sound %d (%s)\n",
- sfx_id, S_sfx[sfx_id].name );*/
-
- // check for bogus sound #
- if (sfx_id < 1 || sfx_id > NUMSFX)
- I_Error("Bad sfx #: %d", sfx_id);
-
- sfx = &S_sfx[sfx_id];
-
- // Initialize sound parameters
- if (sfx->link)
- {
- pitch = sfx->pitch;
- priority = sfx->priority;
- volume += sfx->volume;
-
- if (volume < 1)
- return;
+ // calculate the distance to sound origin
+ // and clip it if necessary
+ adx = abs(listener->x - source->x);
+ ady = abs(listener->y - source->y);
+
+ // From _GG1_ p.428. Appox. eucledian distance fast.
+ approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1);
- if (volume > snd_SfxVolume)
- volume = snd_SfxVolume;
- }
- else
- {
- pitch = NORM_PITCH;
- priority = NORM_PRIORITY;
- }
-
-
- // Check to see if it is audible,
- // and if not, modify the params
- if (origin && origin != players[consoleplayer].mo)
- {
- rc = S_AdjustSoundParams(players[consoleplayer].mo,
- origin,
- &volume,
- &sep,
- &pitch);
-
- if ( origin->x == players[consoleplayer].mo->x
- && origin->y == players[consoleplayer].mo->y)
- {
- sep = NORM_SEP;
+ if (gamemap != 8 && approx_dist > S_CLIPPING_DIST)
+ {
+ return 0;
}
- if (!rc)
- return;
- }
- else
- {
- sep = NORM_SEP;
- }
-
- // hacks to vary the sfx pitches
- if (sfx_id >= sfx_sawup
- && sfx_id <= sfx_sawhit)
- {
- pitch += 8 - (M_Random()&15);
-
- if (pitch<0)
- pitch = 0;
- else if (pitch>255)
- pitch = 255;
- }
- else if (sfx_id != sfx_itemup
- && sfx_id != sfx_tink)
- {
- pitch += 16 - (M_Random()&31);
-
- if (pitch<0)
- pitch = 0;
- else if (pitch>255)
- pitch = 255;
- }
-
- // kill old sound
- S_StopSound(origin);
-
- // try to find a channel
- cnum = S_getChannel(origin, sfx);
-
- if (cnum<0)
- return;
-
- //
- // This is supposed to handle the loading/caching.
- // For some odd reason, the caching is done nearly
- // each time the sound is needed?
- //
-
- // get lumpnum if necessary
- if (sfx->lumpnum < 0)
- sfx->lumpnum = I_GetSfxLumpNum(sfx);
-
- // increase the usefulness
- if (sfx->usefulness++ < 0)
- sfx->usefulness = 1;
-
- // Assigns the handle to one of the channels in the
- // mix/output buffer.
- channels[cnum].handle = I_StartSound(sfx_id,
- cnum,
- volume,
- sep,
- pitch,
- priority);
-}
-
-void
-S_StartSound
-( void* origin,
- int sfx_id )
-{
-#ifdef SAWDEBUG
- // if (sfx_id == sfx_sawful)
- // sfx_id = sfx_itemup;
-#endif
-
- S_StartSoundAtVolume(origin, sfx_id, snd_SfxVolume);
+ // angle of source to listener
+ angle = R_PointToAngle2(listener->x,
+ listener->y,
+ source->x,
+ source->y);
+
+ if (angle > listener->angle)
+ {
+ angle = angle - listener->angle;
+ }
+ else
+ {
+ angle = angle + (0xffffffff - listener->angle);
+ }
+
+ angle >>= ANGLETOFINESHIFT;
+ // stereo separation
+ *sep = 128 - (FixedMul(S_STEREO_SWING, finesine[angle]) >> FRACBITS);
- // UNUSED. We had problems, had we not?
-#ifdef SAWDEBUG
-{
- int i;
- int n;
-
- static mobj_t* last_saw_origins[10] = {1,1,1,1,1,1,1,1,1,1};
- static int first_saw=0;
- static int next_saw=0;
-
- if (sfx_id == sfx_sawidl
- || sfx_id == sfx_sawful
- || sfx_id == sfx_sawhit)
- {
- for (i=first_saw;i!=next_saw;i=(i+1)%10)
- if (last_saw_origins[i] != origin)
- fprintf(stderr, "old origin 0x%lx != "
- "origin 0x%lx for sfx %d\n",
- last_saw_origins[i],
- origin,
- sfx_id);
-
- last_saw_origins[next_saw] = origin;
- next_saw = (next_saw + 1) % 10;
- if (next_saw == first_saw)
- first_saw = (first_saw + 1) % 10;
-
- for (n=i=0; i<numChannels ; i++)
- {
- if (channels[i].sfxinfo == &S_sfx[sfx_sawidl]
- || channels[i].sfxinfo == &S_sfx[sfx_sawful]
- || channels[i].sfxinfo == &S_sfx[sfx_sawhit]) n++;
- }
-
- if (n>1)
- {
- for (i=0; i<numChannels ; i++)
- {
- if (channels[i].sfxinfo == &S_sfx[sfx_sawidl]
- || channels[i].sfxinfo == &S_sfx[sfx_sawful]
- || channels[i].sfxinfo == &S_sfx[sfx_sawhit])
- {
- fprintf(stderr,
- "chn: sfxinfo=0x%lx, origin=0x%lx, "
- "handle=%d\n",
- channels[i].sfxinfo,
- channels[i].origin,
- channels[i].handle);
- }
- }
- fprintf(stderr, "\n");
- }
+ // volume calculation
+ if (approx_dist < S_CLOSE_DIST)
+ {
+ *vol = snd_SfxVolume;
}
+ else if (gamemap == 8)
+ {
+ if (approx_dist > S_CLIPPING_DIST)
+ {
+ approx_dist = S_CLIPPING_DIST;
+ }
+
+ *vol = 15+ ((snd_SfxVolume-15)
+ *((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
+ / S_ATTENUATOR;
+ }
+ else
+ {
+ // distance effect
+ *vol = (snd_SfxVolume
+ * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
+ / S_ATTENUATOR;
+ }
+
+ return (*vol > 0);
}
-#endif
-
-}
+void S_StartSound(void *origin_p, int sfx_id)
+{
+ sfxinfo_t *sfx;
+ mobj_t *origin;
+ int rc;
+ int sep;
+ int pitch;
+ int priority;
+ int cnum;
+ int volume;
+
+ origin = (mobj_t *) origin_p;
+ volume = snd_SfxVolume;
+ // check for bogus sound #
+ if (sfx_id < 1 || sfx_id > NUMSFX)
+ {
+ I_Error("Bad sfx #: %d", sfx_id);
+ }
+ sfx = &S_sfx[sfx_id];
-void S_StopSound(void *origin)
-{
+ // Initialize sound parameters
+ if (sfx->link)
+ {
+ pitch = sfx->pitch;
+ priority = sfx->priority;
+ volume += sfx->volume;
+
+ if (volume < 1)
+ {
+ return;
+ }
+
+ if (volume > snd_SfxVolume)
+ {
+ volume = snd_SfxVolume;
+ }
+ }
+ else
+ {
+ pitch = NORM_PITCH;
+ priority = NORM_PRIORITY;
+ }
- int cnum;
- for (cnum=0 ; cnum<numChannels ; cnum++)
+ // Check to see if it is audible,
+ // and if not, modify the params
+ if (origin && origin != players[consoleplayer].mo)
{
- if (channels[cnum].sfxinfo && channels[cnum].origin == origin)
- {
- S_StopChannel(cnum);
- break;
- }
+ rc = S_AdjustSoundParams(players[consoleplayer].mo,
+ origin,
+ &volume,
+ &sep,
+ &pitch);
+
+ if (origin->x == players[consoleplayer].mo->x
+ && origin->y == players[consoleplayer].mo->y)
+ {
+ sep = NORM_SEP;
+ }
+
+ if (!rc)
+ {
+ return;
+ }
+ }
+ else
+ {
+ sep = NORM_SEP;
}
-}
+ // hacks to vary the sfx pitches
+ if (sfx_id >= sfx_sawup
+ && sfx_id <= sfx_sawhit)
+ {
+ pitch += 8 - (M_Random()&15);
+
+ if (pitch < 0)
+ {
+ pitch = 0;
+ }
+ else if (pitch > 255)
+ {
+ pitch = 255;
+ }
+ }
+ else if (sfx_id != sfx_itemup
+ && sfx_id != sfx_tink)
+ {
+ pitch += 16 - (M_Random()&31);
+
+ if (pitch < 0)
+ {
+ pitch = 0;
+ }
+ else if (pitch > 255)
+ {
+ pitch = 255;
+ }
+ }
+ // kill old sound
+ S_StopSound(origin);
+ // try to find a channel
+ cnum = S_GetChannel(origin, sfx);
+ if (cnum < 0)
+ {
+ return;
+ }
+ //
+ // This is supposed to handle the loading/caching.
+ // For some odd reason, the caching is done nearly
+ // each time the sound is needed?
+ //
+ // get lumpnum if necessary
+ if (sfx->lumpnum < 0)
+ {
+ sfx->lumpnum = I_GetSfxLumpNum(sfx);
+ }
+ // increase the usefulness
+ if (sfx->usefulness++ < 0)
+ {
+ sfx->usefulness = 1;
+ }
+ // Assigns the handle to one of the channels in the
+ // mix/output buffer.
+ channels[cnum].handle = I_StartSound(sfx_id,
+ cnum,
+ volume,
+ sep,
+ pitch,
+ priority);
+}
//
// Stop and resume music, during game PAUSE.
//
+
void S_PauseSound(void)
{
if (mus_playing && !mus_paused)
{
- I_PauseSong(mus_playing->handle);
- mus_paused = true;
+ I_PauseSong(mus_playing->handle);
+ mus_paused = true;
}
}
@@ -501,162 +558,133 @@ void S_ResumeSound(void)
{
if (mus_playing && mus_paused)
{
- I_ResumeSong(mus_playing->handle);
- mus_paused = false;
+ I_ResumeSong(mus_playing->handle);
+ mus_paused = false;
}
}
-
//
// Updates music & sounds
//
-void S_UpdateSounds(void* listener_p)
-{
- int audible;
- int cnum;
- int volume;
- int sep;
- int pitch;
- sfxinfo_t* sfx;
- channel_t* c;
-
- mobj_t* listener = (mobj_t*)listener_p;
-
-
- // Clean up unused data.
- // This is currently not done for 16bit (sounds cached static).
- // DOS 8bit remains.
- /*if (gametic > nextcleanup)
- {
- for (i=1 ; i<NUMSFX ; i++)
- {
- if (S_sfx[i].usefulness < 1
- && S_sfx[i].usefulness > -1)
- {
- if (--S_sfx[i].usefulness == -1)
- {
- Z_ChangeTag(S_sfx[i].data, PU_CACHE);
- S_sfx[i].data = 0;
- }
- }
- }
- nextcleanup = gametic + 15;
- }*/
-
- for (cnum=0 ; cnum<numChannels ; cnum++)
+void S_UpdateSounds(mobj_t *listener)
+{
+ int audible;
+ int cnum;
+ int volume;
+ int sep;
+ int pitch;
+ sfxinfo_t* sfx;
+ channel_t* c;
+
+ for (cnum=0; cnum<numChannels; cnum++)
{
- c = &channels[cnum];
- sfx = c->sfxinfo;
-
- if (c->sfxinfo)
- {
- if (I_SoundIsPlaying(c->handle))
- {
- // initialize parameters
- volume = snd_SfxVolume;
- pitch = NORM_PITCH;
- sep = NORM_SEP;
-
- if (sfx->link)
- {
- pitch = sfx->pitch;
- volume += sfx->volume;
- if (volume < 1)
- {
- S_StopChannel(cnum);
- continue;
- }
- else if (volume > snd_SfxVolume)
- {
- volume = snd_SfxVolume;
- }
- }
-
- // check non-local sounds for distance clipping
- // or modify their params
- if (c->origin && listener_p != c->origin)
- {
- audible = S_AdjustSoundParams(listener,
- c->origin,
- &volume,
- &sep,
- &pitch);
-
- if (!audible)
- {
- S_StopChannel(cnum);
- }
- else
- I_UpdateSoundParams(c->handle, volume, sep, pitch);
- }
- }
- else
- {
- // if channel is allocated but sound has stopped,
- // free it
- S_StopChannel(cnum);
- }
- }
+ c = &channels[cnum];
+ sfx = c->sfxinfo;
+
+ if (c->sfxinfo)
+ {
+ if (I_SoundIsPlaying(c->handle))
+ {
+ // initialize parameters
+ volume = snd_SfxVolume;
+ pitch = NORM_PITCH;
+ sep = NORM_SEP;
+
+ if (sfx->link)
+ {
+ pitch = sfx->pitch;
+ volume += sfx->volume;
+ if (volume < 1)
+ {
+ S_StopChannel(cnum);
+ continue;
+ }
+ else if (volume > snd_SfxVolume)
+ {
+ volume = snd_SfxVolume;
+ }
+ }
+
+ // check non-local sounds for distance clipping
+ // or modify their params
+ if (c->origin && listener != c->origin)
+ {
+ audible = S_AdjustSoundParams(listener,
+ c->origin,
+ &volume,
+ &sep,
+ &pitch);
+
+ if (!audible)
+ {
+ S_StopChannel(cnum);
+ }
+ else
+ {
+ I_UpdateSoundParams(c->handle, volume, sep, pitch);
+ }
+ }
+ }
+ else
+ {
+ // if channel is allocated but sound has stopped,
+ // free it
+ S_StopChannel(cnum);
+ }
+ }
}
- // kill music if it is a single-play && finished
- // if ( mus_playing
- // && !I_QrySongPlaying(mus_playing->handle)
- // && !mus_paused )
- // S_StopMusic();
}
-
void S_SetMusicVolume(int volume)
{
if (volume < 0 || volume > 127)
{
- I_Error("Attempt to set music volume at %d",
- volume);
+ I_Error("Attempt to set music volume at %d",
+ volume);
}
I_SetMusicVolume(127);
I_SetMusicVolume(volume);
}
-
-
void S_SetSfxVolume(int volume)
{
-
if (volume < 0 || volume > 127)
- I_Error("Attempt to set sfx volume at %d", volume);
+ {
+ I_Error("Attempt to set sfx volume at %d", volume);
+ }
snd_SfxVolume = volume;
-
}
//
// Starts some music with the music id found in sounds.h.
//
+
void S_StartMusic(int m_id)
{
S_ChangeMusic(m_id, false);
}
-void
-S_ChangeMusic
-( int musicnum,
- int looping )
+void S_ChangeMusic(int musicnum, int looping)
{
- musicinfo_t* music = NULL;
- char namebuf[9];
+ musicinfo_t* music = NULL;
+ char namebuf[9];
- if ( (musicnum <= mus_None)
- || (musicnum >= NUMMUSIC) )
+ if (musicnum <= mus_None || musicnum >= NUMMUSIC)
{
- I_Error("Bad music number %d", musicnum);
+ I_Error("Bad music number %d", musicnum);
}
else
- music = &S_music[musicnum];
+ {
+ music = &S_music[musicnum];
+ }
if (mus_playing == music)
- return;
+ {
+ return;
+ }
// shutdown old music
S_StopMusic();
@@ -664,12 +692,12 @@ S_ChangeMusic
// get lumpnum if neccessary
if (!music->lumpnum)
{
- sprintf(namebuf, "d_%s", DEH_String(music->name));
- music->lumpnum = W_GetNumForName(namebuf);
+ sprintf(namebuf, "d_%s", DEH_String(music->name));
+ music->lumpnum = W_GetNumForName(namebuf);
}
// load & register it
- music->data = (void *) W_CacheLumpNum(music->lumpnum, PU_MUSIC);
+ music->data = W_CacheLumpNum(music->lumpnum, PU_MUSIC);
music->handle = I_RegisterSong(music->data, W_LumpLength(music->lumpnum));
// play it
@@ -683,192 +711,21 @@ boolean S_MusicPlaying(void)
return I_QrySongPlaying(NULL);
}
-
void S_StopMusic(void)
{
if (mus_playing)
{
- if (mus_paused)
- I_ResumeSong(mus_playing->handle);
-
- I_StopSong(mus_playing->handle);
- I_UnRegisterSong(mus_playing->handle);
- Z_ChangeTag(mus_playing->data, PU_CACHE);
-
- mus_playing->data = 0;
- mus_playing = 0;
+ if (mus_paused)
+ {
+ I_ResumeSong(mus_playing->handle);
+ }
+
+ I_StopSong(mus_playing->handle);
+ I_UnRegisterSong(mus_playing->handle);
+ Z_ChangeTag(mus_playing->data, PU_CACHE);
+
+ mus_playing->data = 0;
+ mus_playing = 0;
}
}
-void S_StopChannel(int cnum)
-{
-
- int i;
- channel_t* c = &channels[cnum];
-
- if (c->sfxinfo)
- {
- // stop the sound playing
- if (I_SoundIsPlaying(c->handle))
- {
-#ifdef SAWDEBUG
- if (c->sfxinfo == &S_sfx[sfx_sawful])
- fprintf(stderr, "stopped\n");
-#endif
- I_StopSound(c->handle);
- }
-
- // check to see
- // if other channels are playing the sound
- for (i=0 ; i<numChannels ; i++)
- {
- if (cnum != i
- && c->sfxinfo == channels[i].sfxinfo)
- {
- break;
- }
- }
-
- // degrade usefulness of sound data
- c->sfxinfo->usefulness--;
-
- c->sfxinfo = 0;
- }
-}
-
-
-
-//
-// Changes volume, stereo-separation, and pitch variables
-// from the norm of a sound effect to be played.
-// If the sound is not audible, returns a 0.
-// Otherwise, modifies parameters and returns 1.
-//
-int
-S_AdjustSoundParams
-( mobj_t* listener,
- mobj_t* source,
- int* vol,
- int* sep,
- int* pitch )
-{
- fixed_t approx_dist;
- fixed_t adx;
- fixed_t ady;
- angle_t angle;
-
- // calculate the distance to sound origin
- // and clip it if necessary
- adx = abs(listener->x - source->x);
- ady = abs(listener->y - source->y);
-
- // From _GG1_ p.428. Appox. eucledian distance fast.
- approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1);
-
- if (gamemap != 8
- && approx_dist > S_CLIPPING_DIST)
- {
- return 0;
- }
-
- // angle of source to listener
- angle = R_PointToAngle2(listener->x,
- listener->y,
- source->x,
- source->y);
-
- if (angle > listener->angle)
- angle = angle - listener->angle;
- else
- angle = angle + (0xffffffff - listener->angle);
-
- angle >>= ANGLETOFINESHIFT;
-
- // stereo separation
- *sep = 128 - (FixedMul(S_STEREO_SWING,finesine[angle])>>FRACBITS);
-
- // volume calculation
- if (approx_dist < S_CLOSE_DIST)
- {
- *vol = snd_SfxVolume;
- }
- else if (gamemap == 8)
- {
- if (approx_dist > S_CLIPPING_DIST)
- approx_dist = S_CLIPPING_DIST;
-
- *vol = 15+ ((snd_SfxVolume-15)
- *((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
- / S_ATTENUATOR;
- }
- else
- {
- // distance effect
- *vol = (snd_SfxVolume
- * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
- / S_ATTENUATOR;
- }
-
- return (*vol > 0);
-}
-
-
-
-
-//
-// S_getChannel :
-// If none available, return -1. Otherwise channel #.
-//
-int
-S_getChannel
-( void* origin,
- sfxinfo_t* sfxinfo )
-{
- // channel number to use
- int cnum;
-
- channel_t* c;
-
- // Find an open channel
- for (cnum=0 ; cnum<numChannels ; cnum++)
- {
- if (!channels[cnum].sfxinfo)
- break;
- else if (origin && channels[cnum].origin == origin)
- {
- S_StopChannel(cnum);
- break;
- }
- }
-
- // None available
- if (cnum == numChannels)
- {
- // Look for lower priority
- for (cnum=0 ; cnum<numChannels ; cnum++)
- if (channels[cnum].sfxinfo->priority >= sfxinfo->priority) break;
-
- if (cnum == numChannels)
- {
- // FUCK! No lower priority. Sorry, Charlie.
- return -1;
- }
- else
- {
- // Otherwise, kick out lower priority.
- S_StopChannel(cnum);
- }
- }
-
- c = &channels[cnum];
-
- // channel is decided to be cnum.
- c->sfxinfo = sfxinfo;
- c->origin = origin;
-
- return cnum;
-}
-
-
-
-