- The sound code now handles restarting looping sounds itself. As far as

the rest of the game is concerned, these sounds will never stop once they
  have been started until they are explicitly stopped. If they are evicted
  from their channels, the sound code will restart them as soon as possible.
  This means that instead of this:
	if (!S_IsActorPlayingSomething(actor, CHAN_WEAPON, -1))
	{
		S_Sound(actor, CHAN_WEAPON|CHAN_LOOP, soundid, 1, ATTN_NORM);
	}
  The following is now just as effective:
	S_Sound(actor, CHAN_WEAPON|CHAN_LOOP, soundid, 1, ATTN_NORM);
  There are also a couple of other ramifications presented by this change:
    * The full state of the sound system (sans music) is now stored in save
      games. Any sounds that were playing when you saved will still be
      playing when you load. (Try saving while Korax is making a speech in
      Hexen to hear it.)
    * Using snd_reset will also preserve any playing sounds.
    * Movie playback is disabled, probably forever. I did not want to 
      update the MovieDisable/ResumeSound stuff for the new eviction
      tracking code. A properly updated movie player will use the VMR,
      which doesn't need these functions, since it would pipe the sound
      straight through the sound system like everything else, so I decided
      to dump them now, which leaves the movie player in a totally unworkable
      state.

June 26, 2008
- Changed S_Sound() to take the same floating point attenuation that the
  internal S_StartSound() uses. Now ambient sounds can use the public
  S_Sound() interface.
- Fixed: S_RelinkSound() compared the points of the channels against the
  from actor's point, rather than checking the channels' mover.
- Changed Strife's animated doors so that their sounds originate from the
  interior of the sector making them and not from the entire vertical height
  of the map.


SVN r1055 (trunk)
This commit is contained in:
Randy Heit 2008-06-29 04:19:38 +00:00
parent 095b482624
commit d0b2c41270
16 changed files with 726 additions and 219 deletions

View file

@ -8,7 +8,41 @@ June 28, 2008 (Changes by Graf Zahl)
- Fixed: Heretic's ActivatedTimeBomb had the same spawn ID as the inventory item.
- fixed: Heretic's mace did not have its spawn ID set.
June 28, 2008
- The sound code now handles restarting looping sounds itself. As far as
the rest of the game is concerned, these sounds will never stop once they
have been started until they are explicitly stopped. If they are evicted
from their channels, the sound code will restart them as soon as possible.
This means that instead of this:
if (!S_IsActorPlayingSomething(actor, CHAN_WEAPON, -1))
{
S_Sound(actor, CHAN_WEAPON|CHAN_LOOP, soundid, 1, ATTN_NORM);
}
The following is now just as effective:
S_Sound(actor, CHAN_WEAPON|CHAN_LOOP, soundid, 1, ATTN_NORM);
There are also a couple of other ramifications presented by this change:
* The full state of the sound system (sans music) is now stored in save
games. Any sounds that were playing when you saved will still be
playing when you load. (Try saving while Korax is making a speech in
Hexen to hear it.)
* Using snd_reset will also preserve any playing sounds.
* Movie playback is disabled, probably forever. I did not want to
update the MovieDisable/ResumeSound stuff for the new eviction
tracking code. A properly updated movie player will use the VMR,
which doesn't need these functions, since it would pipe the sound
straight through the sound system like everything else, so I decided
to dump them now, which leaves the movie player in a totally unworkable
state.
June 26, 2008
- Changed S_Sound() to take the same floating point attenuation that the
internal S_StartSound() uses. Now ambient sounds can use the public
S_Sound() interface.
- Fixed: S_RelinkSound() compared the points of the channels against the
from actor's point, rather than checking the channels' mover.
- Changed Strife's animated doors so that their sounds originate from the
interior of the sector making them and not from the entire vertical height
of the map.
- For controls that are not bound, the customize controls menu now displays
a black --- instead of ???.
- Applied Gez's BossBrainPatch3.

View file

@ -126,6 +126,18 @@ typedef struct _GUID
} GUID;
#endif
union QWORD_UNION
{
QWORD AsOne;
struct
{
#ifdef WORDS_BIG_ENDIAN
unsigned int Hi, Lo;
#else
unsigned int Lo, Hi;
#endif
};
};
// Bounding box coordinate storage.
enum

View file

@ -177,6 +177,7 @@ virtual void Read (void *mem, unsigned int len);
FArchive& operator<< (WORD &s);
FArchive& operator<< (DWORD &i);
FArchive& operator<< (QWORD &i);
FArchive& operator<< (QWORD_UNION &i) { return operator<< (i.AsOne); }
FArchive& operator<< (float &f);
FArchive& operator<< (double &d);
FArchive& operator<< (char *&str);

View file

@ -729,7 +729,7 @@ DAnimatedDoor::DAnimatedDoor (sector_t *sec, line_t *line, int speed, int delay)
MoveCeiling (2048*FRACUNIT, topdist, 1);
if (DoorAnimations[m_WhichDoorIndex].OpenSound != NAME_None)
{
SN_StartSequence (m_Sector, CHAN_FULLHEIGHT, DoorAnimations[m_WhichDoorIndex].OpenSound, 1);
SN_StartSequence (m_Sector, CHAN_INTERIOR, DoorAnimations[m_WhichDoorIndex].OpenSound, 1);
}
}

View file

@ -436,6 +436,7 @@ void P_SerializeThinkers (FArchive &arc, bool hubLoad)
void P_SerializeSounds (FArchive &arc)
{
S_SerializeSounds (arc);
DSeqNode::SerializeSequences (arc);
char *name = NULL;
BYTE order;

View file

@ -186,8 +186,6 @@ MidiDeviceMap MidiDevices;
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
FSoundChan *S_StartSound (fixed_t *pt, AActor *mover, sector_t *sec, int channel,
FSoundID sound_id, float volume, float attenuation);
extern bool IsFloat (const char *str);
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
@ -1873,35 +1871,28 @@ void AAmbientSound::Tick ()
return;
AmbientSound *ambient = Ambients[args[0]];
int loop = 0;
if ((ambient->type & CONTINUOUS) == CONTINUOUS)
{
if (S_IsActorPlayingSomething (this, CHAN_BODY, -1))
return;
loop = CHAN_LOOP;
}
if (ambient->sound[0])
if (ambient->sound[0])
{
S_Sound(this, CHAN_BODY | loop, ambient->sound, ambient->volume, ambient->attenuation);
if (!loop)
{
S_StartSound (&this->x, this, NULL, CHAN_BODY|CHAN_LOOP, ambient->sound,
ambient->volume, ambient->attenuation);
SetTicker (ambient);
}
else
{
Destroy ();
NextCheck = INT_MAX;
}
}
else
{
if (ambient->sound[0])
{
S_StartSound (NULL, this, NULL, CHAN_BODY, ambient->sound,
ambient->volume, ambient->attenuation);
SetTicker (ambient);
}
else
{
Destroy ();
}
Destroy ();
}
}

View file

@ -269,10 +269,6 @@ static FRandom pr_sndseq ("SndSeq");
void DSeqNode::SerializeSequences (FArchive &arc)
{
if (arc.IsLoading ())
{
SN_StopAllSequences ();
}
arc << SequenceListHead;
}

View file

@ -63,7 +63,6 @@
#define O_BINARY 0
#endif
#define SELECT_ATTEN(a) ((a)==ATTN_NONE ? 0 : (a)==ATTN_STATIC ? 3 : 1)
#ifndef FIXED2FLOAT
#define FIXED2FLOAT(f) (((float)(f))/(float)65536)
#endif
@ -91,16 +90,15 @@ extern float S_GetMusicVolume (const char *music);
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
FSoundChan *S_StartSound(fixed_t *pt, AActor *mover, sector_t *sec, int channel,
FSoundID sound_id, float volume, float attenuation);
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static fixed_t P_AproxDistance2(fixed_t *listener, fixed_t x, fixed_t y);
static bool S_CheckSoundLimit(sfxinfo_t *sfx, float pos[3], int NearLimit);
static bool S_CheckSoundLimit(sfxinfo_t *sfx, float pos[3], int near_limit);
static void S_ActivatePlayList(bool goBack);
static void CalcPosVel(fixed_t *pt, AActor *mover, int constz, float pos[3],
float vel[3]);
static FSoundChan *S_StartSound(fixed_t *pt, AActor *mover, sector_t *sec,
int channel, FSoundID sound_id, float volume, float attenuation);
static sfxinfo_t *S_LoadSound(sfxinfo_t *sfx);
// PRIVATE DATA DEFINITIONS ------------------------------------------------
@ -129,32 +127,6 @@ CVAR (Bool, snd_flipstereo, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
// CODE --------------------------------------------------------------------
//==========================================================================
//
// P_AproxDistance2
//
//==========================================================================
static fixed_t P_AproxDistance2 (fixed_t *listener, fixed_t x, fixed_t y)
{
// calculate the distance to sound origin
// and clip it if necessary
if (listener)
{
fixed_t adx = abs (listener[0] - x);
fixed_t ady = abs (listener[1] - y);
// From _GG1_ p.428. Appox. eucledian distance fast.
return adx + ady - ((adx < ady ? adx : ady)>>1);
}
else
return 0;
}
static fixed_t P_AproxDistance2 (AActor *listener, fixed_t x, fixed_t y)
{
return listener ? P_AproxDistance2 (&listener->x, x, y) : 0;
}
//==========================================================================
//
// S_NoiseDebug
@ -165,6 +137,7 @@ static fixed_t P_AproxDistance2 (AActor *listener, fixed_t x, fixed_t y)
void S_NoiseDebug (void)
{
FSoundChan *chan;
FVector3 listener;
fixed_t ox, oy, oz;
int y, color;
@ -179,6 +152,7 @@ void S_NoiseDebug (void)
screen->DrawText (CR_GOLD, 220, y, "vol", TAG_DONE);
screen->DrawText (CR_GOLD, 250, y, "dist", TAG_DONE);
screen->DrawText (CR_GOLD, 290, y, "chan", TAG_DONE);
screen->DrawText (CR_GOLD, 330, y, "flags", TAG_DONE);
y += 8;
if (Channels == NULL)
@ -186,48 +160,83 @@ void S_NoiseDebug (void)
return;
}
// Display the last channel first.
listener.X = FIXED2FLOAT(players[consoleplayer].camera->x);
listener.Y = FIXED2FLOAT(players[consoleplayer].camera->y);
listener.Z = FIXED2FLOAT(players[consoleplayer].camera->z);
// Display the oldest channel first.
for (chan = Channels; chan->NextChan != NULL; chan = chan->NextChan)
{ }
while (y < SCREENHEIGHT - 16)
{
char temp[16];
fixed_t *origin = chan->Pt;
char temp[32];
if (!(chan->ChanFlags & CHAN_IS3D))
{
ox = players[consoleplayer].camera->x;
oy = players[consoleplayer].camera->y;
oz = players[consoleplayer].camera->z;
}
else if (origin)
{
ox = origin[0];
oy = origin[1];
oz = origin[2];
}
else
{
ox = chan->X;
oy = chan->Y;
oz = chan->Z;
}
assert(chan->Pt != NULL);
ox = chan->Pt[0];
oy = chan->Pt[1];
oz = chan->Pt[2];
color = (chan->ChanFlags & CHAN_LOOP) ? CR_BROWN : CR_GREY;
// Name
Wads.GetLumpName (temp, chan->SfxInfo->lumpnum);
temp[8] = 0;
screen->DrawText (color, 0, y, temp, TAG_DONE);
sprintf (temp, "%d", ox >> FRACBITS);
screen->DrawText (color, 70, y, temp, TAG_DONE);
sprintf (temp, "%d", oy >> FRACBITS);
screen->DrawText (color, 120, y, temp, TAG_DONE);
sprintf (temp, "%d", oz >> FRACBITS);
screen->DrawText (color, 170, y, temp, TAG_DONE);
if (!(chan->ChanFlags & CHAN_IS3D))
{
screen->DrawText(color, 70, y, "---", TAG_DONE); // X
screen->DrawText(color, 120, y, "---", TAG_DONE); // Y
screen->DrawText(color, 170, y, "---", TAG_DONE); // Z
screen->DrawText(color, 250, y, "---", TAG_DONE); // Distance
}
else
{
// X coordinate
sprintf (temp, "%d", ox >> FRACBITS);
screen->DrawText (color, 70, y, temp, TAG_DONE);
// Y coordinate
sprintf (temp, "%d", oy >> FRACBITS);
screen->DrawText (color, 120, y, temp, TAG_DONE);
// Z coordinate
sprintf (temp, "%d", oz >> FRACBITS);
screen->DrawText (color, 170, y, temp, TAG_DONE);
// Distance
if (chan->DistanceScale > 0)
{
FVector3 sound(ox, oy, oz);
sound /= FRACUNIT;
sprintf (temp, "%.0f", (sound - listener).Length());
screen->DrawText (color, 250, y, temp, TAG_DONE);
}
else
{
screen->DrawText (color, 250, y, "---", TAG_DONE);
}
}
// Volume
sprintf (temp, "%g", chan->Volume);
screen->DrawText (color, 220, y, temp, TAG_DONE);
sprintf (temp, "%d", P_AproxDistance2 (players[consoleplayer].camera, ox, oy) / FRACUNIT);
screen->DrawText (color, 250, y, temp, TAG_DONE);
// Channel
sprintf (temp, "%d", chan->EntChannel);
screen->DrawText (color, 290, y, temp, TAG_DONE);
// Flags
sprintf (temp, "%s3%sZ%sI%sM%sN%sA%sL%sE",
(chan->ChanFlags & CHAN_IS3D) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
(chan->ChanFlags & CHAN_LISTENERZ) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
(chan->ChanFlags & CHAN_IMMOBILE) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
(chan->ChanFlags & CHAN_MAYBE_LOCAL) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
(chan->ChanFlags & CHAN_NOPAUSE) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
(chan->ChanFlags & CHAN_AREA) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
(chan->ChanFlags & CHAN_LOOP) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
(chan->ChanFlags & CHAN_EVICTED) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK);
screen->DrawText (color, 330, y, temp, TAG_DONE);
y += 8;
if (chan->PrevChan == &Channels)
{
@ -638,8 +647,8 @@ void CalcPosVel (fixed_t *pt, AActor *mover, int constz,
// calculating volume
//==========================================================================
FSoundChan *S_StartSound (fixed_t *pt, AActor *mover, sector_t *sec, int channel,
FSoundID sound_id, float volume, float attenuation)
static FSoundChan *S_StartSound (fixed_t *pt, AActor *mover, sector_t *sec,
int channel, FSoundID sound_id, float volume, float attenuation)
{
sfxinfo_t *sfx;
int chanflags;
@ -702,7 +711,7 @@ FSoundChan *S_StartSound (fixed_t *pt, AActor *mover, sector_t *sec, int channel
// When resolving a link we do not want to get the NearLimit of
// the referenced sound so some additional checks are required
int NearLimit = sfx->NearLimit;
int near_limit = sfx->NearLimit;
// Resolve player sounds, random sounds, and aliases
while (sfx->link != sfxinfo_t::NO_LINK)
@ -710,17 +719,17 @@ FSoundChan *S_StartSound (fixed_t *pt, AActor *mover, sector_t *sec, int channel
if (sfx->bPlayerReserve)
{
sound_id = FSoundID(S_FindSkinnedSound (mover, sound_id));
NearLimit = S_sfx[sound_id].NearLimit;
near_limit = S_sfx[sound_id].NearLimit;
}
else if (sfx->bRandomHeader)
{
sound_id = FSoundID(S_PickReplacement (sound_id));
if (NearLimit < 0) NearLimit = S_sfx[sound_id].NearLimit;
if (near_limit < 0) near_limit = S_sfx[sound_id].NearLimit;
}
else
{
sound_id = FSoundID(sfx->link);
if (NearLimit < 0) NearLimit = S_sfx[sound_id].NearLimit;
if (near_limit < 0) near_limit = S_sfx[sound_id].NearLimit;
}
sfx = &S_sfx[sound_id];
}
@ -729,21 +738,20 @@ FSoundChan *S_StartSound (fixed_t *pt, AActor *mover, sector_t *sec, int channel
if (sfx->bSingular && S_CheckSingular(sound_id))
return NULL;
// If the sound is unpositioned or comes from the listener, it is
// never limited.
if (pt == NULL || mover == players[consoleplayer].camera)
{
near_limit = 0;
}
// If this sound doesn't like playing near itself, don't play it if
// that's what would happen.
if (NearLimit > 0 && pt != NULL && mover != players[consoleplayer].camera &&
S_CheckSoundLimit(sfx, pos, NearLimit))
if (near_limit > 0 && S_CheckSoundLimit(sfx, pos, near_limit))
return NULL;
// Make sure the sound is loaded.
if (sfx->data == NULL)
{
GSnd->LoadSound (sfx);
if (sfx->link != sfxinfo_t::NO_LINK)
{
sfx = &S_sfx[sfx->link];
}
}
sfx = S_LoadSound(sfx);
// The empty sound never plays.
if (sfx->lumpnum == sfx_empty)
@ -811,18 +819,18 @@ FSoundChan *S_StartSound (fixed_t *pt, AActor *mover, sector_t *sec, int channel
if (attenuation > 0)
{
chan = GSnd->StartSound3D (sfx, volume, attenuation, pitch, basepriority, pos, vel, sec, channel, chanflags);
chanflags |= CHAN_IS3D;
chan = GSnd->StartSound3D (sfx, volume, attenuation, pitch, basepriority, pos, vel, sec, channel, chanflags, NULL);
chanflags |= CHAN_IS3D | CHAN_JUSTSTARTED;
}
else
{
chan = GSnd->StartSound (sfx, volume, pitch, chanflags);
chanflags |= CHAN_LISTENERZ;
chan = GSnd->StartSound (sfx, volume, pitch, chanflags, NULL);
chanflags |= CHAN_LISTENERZ | CHAN_JUSTSTARTED;
}
if (chan != NULL)
{
chan->SoundID = sound_id;
chan->OrgID = org_id;
chan->OrgID = FSoundID(org_id);
chan->Mover = mover;
chan->Pt = pt != NULL ? pt : &chan->X;
chan->Sector = sec;
@ -833,6 +841,9 @@ FSoundChan *S_StartSound (fixed_t *pt, AActor *mover, sector_t *sec, int channel
chan->Y = y;
chan->Z = z;
chan->ChanFlags |= chanflags;
chan->NearLimit = near_limit;
chan->Pitch = pitch;
chan->Priority = basepriority;
if (mover != NULL)
{
mover->SoundChans |= 1 << channel;
@ -841,15 +852,72 @@ FSoundChan *S_StartSound (fixed_t *pt, AActor *mover, sector_t *sec, int channel
return chan;
}
//==========================================================================
//
// S_RestartSound
//
// Attempts to restart looping sounds that were evicted from their channels.
//
//==========================================================================
void S_RestartSound(FSoundChan *chan)
{
assert(chan->ChanFlags & CHAN_EVICTED);
assert(chan->SfxInfo != NULL);
FSoundChan *ochan;
sfxinfo_t *sfx = chan->SfxInfo;
// If this is a singular sound, don't play it if it's already playing.
if (sfx->bSingular && S_CheckSingular(chan->SoundID))
return;
sfx = S_LoadSound(sfx);
// The empty sound never plays.
if (sfx->lumpnum == sfx_empty)
{
return;
}
if (chan->ChanFlags & CHAN_IS3D)
{
float pos[3], vel[3];
CalcPosVel(chan->Pt, chan->Mover, chan->ChanFlags & CHAN_LISTENERZ, pos, vel);
// If this sound doesn't like playing near itself, don't play it if
// that's what would happen.
ochan = GSnd->StartSound3D(sfx, chan->Volume, chan->DistanceScale, chan->Pitch,
chan->Priority, pos, vel, chan->Sector, chan->EntChannel, chan->ChanFlags, chan);
}
else
{
ochan = GSnd->StartSound(chan->SfxInfo, chan->Volume, chan->Pitch, chan->ChanFlags, chan);
}
assert(ochan == NULL || ochan == chan);
if (ochan != NULL)
{
ochan->ChanFlags &= ~CHAN_EVICTED;
// When called from the savegame loader, the actor's SoundChans
// flags will be cleared. During normal gameplay, they should still
// be set.
if (ochan->Mover != NULL)
{
ochan->Mover->SoundChans |= 1 << ochan->EntChannel;
}
}
}
//==========================================================================
//
// S_Sound - Unpositioned version
//
//==========================================================================
void S_Sound (int channel, FSoundID sound_id, float volume, int attenuation)
void S_Sound (int channel, FSoundID sound_id, float volume, float attenuation)
{
S_StartSound ((fixed_t *)NULL, NULL, NULL, channel, sound_id, volume, SELECT_ATTEN(attenuation));
S_StartSound ((fixed_t *)NULL, NULL, NULL, channel, sound_id, volume, attenuation);
}
//==========================================================================
@ -858,11 +926,11 @@ void S_Sound (int channel, FSoundID sound_id, float volume, int attenuation)
//
//==========================================================================
void S_Sound (AActor *ent, int channel, FSoundID sound_id, float volume, int attenuation)
void S_Sound (AActor *ent, int channel, FSoundID sound_id, float volume, float attenuation)
{
if (ent->Sector->Flags & SECF_SILENT)
return;
S_StartSound (&ent->x, ent, NULL, channel, sound_id, volume, SELECT_ATTEN(attenuation));
S_StartSound (&ent->x, ent, NULL, channel, sound_id, volume, attenuation);
}
//==========================================================================
@ -871,9 +939,9 @@ void S_Sound (AActor *ent, int channel, FSoundID sound_id, float volume, int att
//
//==========================================================================
void S_Sound (fixed_t *pt, int channel, FSoundID sound_id, float volume, int attenuation)
void S_Sound (fixed_t *pt, int channel, FSoundID sound_id, float volume, float attenuation)
{
S_StartSound (pt, NULL, NULL, channel, sound_id, volume, SELECT_ATTEN(attenuation));
S_StartSound (pt, NULL, NULL, channel, sound_id, volume, attenuation);
}
//==========================================================================
@ -882,13 +950,13 @@ void S_Sound (fixed_t *pt, int channel, FSoundID sound_id, float volume, int att
//
//==========================================================================
void S_Sound (fixed_t x, fixed_t y, fixed_t z, int channel, FSoundID sound_id, float volume, int attenuation)
void S_Sound (fixed_t x, fixed_t y, fixed_t z, int channel, FSoundID sound_id, float volume, float attenuation)
{
fixed_t pt[3];
pt[0] = x;
pt[1] = y;
pt[2] = z;
S_StartSound (pt, NULL, NULL, channel|CHAN_IMMOBILE, sound_id, volume, SELECT_ATTEN(attenuation));
S_StartSound (pt, NULL, NULL, channel|CHAN_IMMOBILE, sound_id, volume, attenuation);
}
//==========================================================================
@ -897,11 +965,32 @@ void S_Sound (fixed_t x, fixed_t y, fixed_t z, int channel, FSoundID sound_id, f
//
//==========================================================================
void S_Sound (sector_t *sec, int channel, FSoundID sfxid, float volume, int attenuation)
void S_Sound (sector_t *sec, int channel, FSoundID sfxid, float volume, float attenuation)
{
S_StartSound (sec->soundorg, NULL, sec, channel, sfxid, volume, attenuation);
}
//==========================================================================
//
// S_LoadSound
//
// Returns a pointer to the sfxinfo with the actual sound data.
//
//==========================================================================
sfxinfo_t *S_LoadSound(sfxinfo_t *sfx)
{
if (sfx->data == NULL)
{
GSnd->LoadSound (sfx);
if (sfx->link != sfxinfo_t::NO_LINK)
{
sfx = &S_sfx[sfx->link];
}
}
return sfx;
}
//==========================================================================
//
// S_CheckSingular
@ -933,14 +1022,14 @@ bool S_CheckSingular(int sound_id)
//
//==========================================================================
bool S_CheckSoundLimit(sfxinfo_t *sfx, float pos[3], int NearLimit)
bool S_CheckSoundLimit(sfxinfo_t *sfx, float pos[3], int near_limit)
{
FSoundChan *chan;
int count;
for (chan = Channels, count = 0; chan != NULL && count < NearLimit; chan = chan->NextChan)
for (chan = Channels, count = 0; chan != NULL && count < near_limit; chan = chan->NextChan)
{
if (chan->SfxInfo == sfx)
if (!(chan->ChanFlags & CHAN_EVICTED) && chan->SfxInfo == sfx)
{
double dx = FIXED2FLOAT(chan->Pt[0]) - pos[0];
double dy = FIXED2FLOAT(chan->Pt[1]) - pos[2];
@ -951,7 +1040,7 @@ bool S_CheckSoundLimit(sfxinfo_t *sfx, float pos[3], int NearLimit)
}
}
}
return count >= NearLimit;
return count >= near_limit;
}
//==========================================================================
@ -1015,19 +1104,19 @@ void S_RelinkSound (AActor *from, AActor *to)
if (from == NULL || GSnd == NULL)
return;
fixed_t *frompt = &from->x;
fixed_t *topt = to ? &to->x : NULL;
for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan)
{
if (chan->Pt == frompt)
if (chan->Mover == from)
{
if (to != NULL || !(chan->ChanFlags & CHAN_LOOP))
{
chan->Pt = topt ? topt : &chan->X;
chan->X = frompt[0];
chan->Y = frompt[1];
chan->Z = frompt[2];
if (chan->Pt == &from->x)
{
chan->Pt = to ? &to->x : &chan->X;
chan->X = from->x;
chan->Y = from->y;
chan->Z = from->z;
}
chan->Mover = to;
}
else
@ -1134,6 +1223,87 @@ void S_ResumeSound ()
}
}
//==========================================================================
//
// S_EvictAllChannels
//
// Forcibly evicts all channels so that there are none playing, but all
// information needed to restart them is retained.
//
//==========================================================================
void S_EvictAllChannels()
{
FSoundChan *chan, *next;
for (chan = Channels; chan != NULL; chan = next)
{
next = chan->NextChan;
if (!(chan->ChanFlags & CHAN_EVICTED))
{
chan->ChanFlags |= CHAN_EVICTED;
if (GSnd != NULL && chan->SysChannel != NULL)
{
GSnd->StopSound(chan);
}
assert(chan->NextChan == next);
}
}
}
//==========================================================================
//
// S_RestoreEvictedChannel
//
// Recursive helper for S_RestoreEvictedChannels().
//
//==========================================================================
void S_RestoreEvictedChannel(FSoundChan *chan)
{
if (chan == NULL)
{
return;
}
S_RestoreEvictedChannel(chan->NextChan);
if (chan->ChanFlags & CHAN_EVICTED)
{
S_RestartSound(chan);
if (!(chan->ChanFlags & CHAN_LOOP))
{
if (chan->ChanFlags & CHAN_EVICTED)
{ // Still evicted and not looping? Forget about it.
S_ReturnChannel(chan);
}
else if (!(chan->ChanFlags & CHAN_JUSTSTARTED))
{ // Should this sound become evicted again, it's okay to forget about it.
chan->ChanFlags |= CHAN_FORGETTABLE;
}
}
}
}
//==========================================================================
//
// S_RestoreEvictedChannels
//
// Restarts as many evicted channels as possible. Any channels that could
// not be started and are not looping are moved to the free pool.
//
//==========================================================================
void S_RestoreEvictedChannels()
{
if (GSnd == NULL)
{
return;
}
// Restart channels in the same order they were originally played.
S_RestoreEvictedChannel(Channels);
}
//==========================================================================
//
// S_UpdateSounds
@ -1163,22 +1333,25 @@ void S_UpdateSounds (void *listener_p)
for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan)
{
if (chan->ChanFlags & CHAN_IS3D)
if ((chan->ChanFlags & (CHAN_EVICTED | CHAN_IS3D)) == CHAN_IS3D)
{
CalcPosVel(chan->Pt, chan->Mover, chan->ChanFlags & CHAN_LISTENERZ, pos, vel);
GSnd->UpdateSoundParams3D(chan, pos, vel);
}
chan->ChanFlags &= ~CHAN_JUSTSTARTED;
}
SN_UpdateActiveSequences();
GSnd->UpdateListener();
GSnd->UpdateSounds();
S_RestoreEvictedChannels();
}
//==========================================================================
//
// FArchive & << FSoundID &
// (FArchive &) << (FSoundID &)
//
//==========================================================================
@ -1195,6 +1368,134 @@ FArchive &operator<<(FArchive &arc, FSoundID &sid)
return arc;
}
//==========================================================================
//
// (FArchive &) << (FSoundChan &)
//
//==========================================================================
static FArchive &operator<<(FArchive &arc, FSoundChan &chan)
{
BYTE pt_type;
if (arc.IsStoring())
{
if (chan.Pt == &chan.X)
{
pt_type = 2;
}
else if (chan.Pt == &chan.Mover->x)
{
pt_type = 1;
}
else
{ // WTF?
assert(0);
pt_type = 0;
}
}
arc << pt_type;
arc << chan.Mover;
arc << chan.Sector;
arc << chan.X;
arc << chan.Y;
arc << chan.Z;
arc << chan.SoundID;
arc << chan.OrgID;
arc << chan.Volume;
arc << chan.DistanceScale;
arc << chan.Pitch;
arc << chan.ChanFlags;
arc << chan.EntChannel;
arc << chan.Priority;
arc << chan.NearLimit;
arc << chan.StartTime;
if (arc.IsLoading())
{
chan.SfxInfo = &S_sfx[chan.SoundID];
if (pt_type == 1)
{
chan.Pt = &chan.Mover->x;
}
else if (pt_type == 2)
{
chan.Pt = &chan.X;
}
else
{
chan.Pt = &chan.Mover->x;
}
}
return arc;
}
//==========================================================================
//
// S_SerializeSounds
//
//==========================================================================
void S_SerializeSounds(FArchive &arc)
{
FSoundChan *chan;
if (GSnd != NULL)
{
GSnd->Sync(true);
}
if (arc.IsStoring())
{
TArray<FSoundChan *> chans;
// Count channels and accumulate them so we can store them in
// reverse order. That way, they will be in the same order when
// reloaded later as they are now.
for (chan = Channels; chan != NULL; chan = chan->NextChan)
{
// If the sound is forgettable, this is as good a time as
// any to forget about it.
if (!(chan->ChanFlags & CHAN_FORGETTABLE))
{
chans.Push(chan);
}
}
arc.WriteCount(chans.Size());
for (unsigned int i = chans.Size(); i-- != 0; )
{
// Replace start time with sample position.
QWORD start = chans[i]->StartTime.AsOne;
chans[i]->StartTime.AsOne = GSnd ? GSnd->GetPosition(chans[i]) : 0;
arc << *chans[i];
chans[i]->StartTime.AsOne = start;
}
}
else
{
unsigned int count;
S_StopAllChannels();
count = arc.ReadCount();
for (unsigned int i = 0; i < count; ++i)
{
chan = S_GetChannel(NULL);
arc << *chan;
// Sounds always start out evicted when restored from a save.
chan->ChanFlags |= CHAN_EVICTED;
}
S_RestoreEvictedChannels();
}
DSeqNode::SerializeSequences(arc);
if (GSnd != NULL)
{
GSnd->Sync(false);
GSnd->UpdateSounds();
}
}
//==========================================================================
//

View file

@ -177,17 +177,22 @@ struct FSoundChan
fixed_t *Pt; // Origin of sound.
sfxinfo_t *SfxInfo; // Sound information.
fixed_t X,Y,Z; // Origin if Mover is NULL.
int SoundID; // Sound ID of playing sound
int OrgID; // Sound ID of sound used to start this channel
FSoundID SoundID; // Sound ID of playing sound.
FSoundID OrgID; // Sound ID of sound used to start this channel.
float Volume;
float DistanceScale;
BYTE EntChannel; // Actor's sound channel.
int Pitch; // Pitch variation.
int ChanFlags;
BYTE EntChannel; // Actor's sound channel.
SBYTE Priority;
SWORD NearLimit;
QWORD_UNION StartTime; // Sound start time in DSP clocks.
};
extern FSoundChan *Channels;
FSoundChan *S_GetChannel(void *syschan);
void S_ReturnChannel(FSoundChan *chan);
void S_EvictAllChannels();
void S_LinkChannel(FSoundChan *chan, FSoundChan **head);
void S_UnlinkChannel(FSoundChan *chan);
@ -212,11 +217,11 @@ void S_PrecacheLevel ();
void S_CacheSound (sfxinfo_t *sfx);
// Start sound for thing at <ent>
void S_Sound (int channel, FSoundID sfxid, float volume, int attenuation);
void S_Sound (AActor *ent, int channel, FSoundID sfxid, float volume, int attenuation);
void S_Sound (fixed_t *pt, int channel, FSoundID sfxid, float volume, int attenuation);
void S_Sound (fixed_t x, fixed_t y, fixed_t z, int channel, FSoundID sfxid, float volume, int attenuation);
void S_Sound (sector_t *sec, int channel, FSoundID sfxid, float volume, int attenuation);
void S_Sound (int channel, FSoundID sfxid, float volume, float attenuation);
void S_Sound (AActor *ent, int channel, FSoundID sfxid, float volume, float attenuation);
void S_Sound (fixed_t *pt, int channel, FSoundID sfxid, float volume, float attenuation);
void S_Sound (fixed_t x, fixed_t y, fixed_t z, int channel, FSoundID sfxid, float volume, float attenuation);
void S_Sound (sector_t *sec, int channel, FSoundID sfxid, float volume, float attenuation);
// sound channels
// channel 0 never willingly overrides
@ -234,29 +239,34 @@ void S_Sound (sector_t *sec, int channel, FSoundID sfxid, float volume, int atte
#define CHAN_VOICE 2
#define CHAN_ITEM 3
#define CHAN_BODY 4
// modifier flags
#define CHAN_LISTENERZ 8
#define CHAN_IMMOBILE 16
#define CHAN_MAYBE_LOCAL 32
#define CHAN_NOPAUSE 64 // do not pause this sound in menus
#define CHAN_AREA 128 // Sound plays from all around. Only valid with sector sounds.
#define CHAN_LOOP 256
// Channel alias for sector sounds. These define how listener height is
// used when calculating 3D sound volume.
#define CHAN_FLOOR 1 // Sound comes from the floor.
#define CHAN_CEILING 2 // Sound comes from the ceiling.
#define CHAN_FULLHEIGHT 3 // Sound comes entire height of the sector.
#define CHAN_INTERIOR 4 // Sound comes height between floor and ceiling.
#define CHAN_IS3D (1<<24) // internal flag
// modifier flags
#define CHAN_LISTENERZ 8
#define CHAN_IMMOBILE 16
#define CHAN_MAYBE_LOCAL 32
#define CHAN_NOPAUSE 64 // Do not pause this sound in menus.
#define CHAN_AREA 128 // Sound plays from all around. Only valid with sector sounds.
#define CHAN_LOOP 256
#define CHAN_PICKUP (CHAN_ITEM|CHAN_MAYBE_LOCAL)
#define CHAN_IS3D 1 // internal: Sound is 3D.
#define CHAN_EVICTED 2 // internal: Looping sound was evicted.
#define CHAN_FORGETTABLE 4 // internal: Forget sound data when sound stops.
#define CHAN_JUSTSTARTED 512 // internal: Sound has not been updated yet.
// sound attenuation values
#define ATTN_NONE 0 // full volume the entire level
#define ATTN_NORM 1
#define ATTN_IDLE 2
#define ATTN_STATIC 3 // diminish very rapidly with distance
#define ATTN_NONE 0.f // full volume the entire level
#define ATTN_NORM 1.f
#define ATTN_IDLE 1.001f
#define ATTN_STATIC 3.f // diminish very rapidly with distance
int S_PickReplacement (int refid);
void S_CacheRandomSound (sfxinfo_t *sfx);
@ -279,6 +289,9 @@ bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id);
// Moves all sounds from one mobj to another
void S_RelinkSound (AActor *from, AActor *to);
// Stores/retrieves playing channel information in an archive.
void S_SerializeSounds(FArchive &arc);
// Start music using <music_name>
bool S_StartMusic (const char *music_name);
@ -304,6 +317,8 @@ void S_ResumeSound ();
//
void S_UpdateSounds (void *listener);
void S_RestoreEvictedChannels();
// [RH] S_sfx "maintenance" routines
void S_ParseSndInfo ();
void S_ParseReverbDef ();

View file

@ -92,11 +92,6 @@ FMOD_RESULT SPC_CreateCodec(FMOD::System *sys);
static int Enum_NumForName(const FEnumList *list, const char *name);
static const char *Enum_NameForNum(const FEnumList *list, int num);
static FMOD_RESULT F_CALLBACK Memory_Open(const char *name, int unicode, unsigned int *filesize, void **handle, void **userdata);
static FMOD_RESULT F_CALLBACK Memory_Close(void *handle, void *userdata);
static FMOD_RESULT F_CALLBACK Memory_Read(void *handle, void *buffer, unsigned int sizebytes, unsigned int *bytesread, void *userdata);
static FMOD_RESULT F_CALLBACK Memory_Seek(void *handle, unsigned int pos, void *userdata);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
EXTERN_CVAR (String, snd_output)
@ -613,6 +608,7 @@ bool FMODSoundRenderer::Init()
int eval;
SFXPaused = false;
DSPLocked = false;
MusicGroup = NULL;
SfxGroup = NULL;
PausableSfx = NULL;
@ -620,8 +616,7 @@ bool FMODSoundRenderer::Init()
WaterLP = NULL;
WaterReverb = NULL;
PrevEnvironment = DefaultEnvironments[0];
DSPClockLo = 0;
DSPClockHi = 0;
DSPClock.AsOne = 0;
ChannelGroupTargetUnit = NULL;
Printf("I_InitSound: Initializing FMOD\n");
@ -991,7 +986,7 @@ void FMODSoundRenderer::Shutdown()
{
unsigned int i;
S_StopAllChannels();
//S_StopAllChannels();
if (MusicGroup != NULL)
{
@ -1179,36 +1174,14 @@ FString FMODSoundRenderer::GatherStats()
Sys->getChannelsPlaying(&channels);
Sys->getCPUUsage(&dsp, &stream, &update, &total);
out.Format ("%d channels,%5.2f%% CPU (DSP:%2.2f%% Stream:%2.2f%% Update:%2.2f%%)",
out.Format ("%d channels,"TEXTCOLOR_YELLOW"%5.2f"TEXTCOLOR_NORMAL"%% CPU "
"(DSP:"TEXTCOLOR_YELLOW"%2.2f"TEXTCOLOR_NORMAL"%% "
"Stream:"TEXTCOLOR_YELLOW"%2.2f"TEXTCOLOR_NORMAL"%% "
"Update:"TEXTCOLOR_YELLOW"%2.2f"TEXTCOLOR_NORMAL"%%)",
channels, total, dsp, stream, update);
return out;
}
//==========================================================================
//
// FMODSoundRenderer :: MovieDisableSound
//
//==========================================================================
void FMODSoundRenderer::MovieDisableSound()
{
I_ShutdownMusic();
Shutdown();
}
//==========================================================================
//
// FMODSoundRenderer :: MovieResumeSound
//
//==========================================================================
void FMODSoundRenderer::MovieResumeSound()
{
Init();
S_Init();
S_RestartMusic();
}
//==========================================================================
//
// FMODSoundRenderer :: SetSfxVolume
@ -1377,7 +1350,7 @@ SoundStream *FMODSoundRenderer::OpenStream(const char *filename_or_data, int fla
//
//==========================================================================
FSoundChan *FMODSoundRenderer::StartSound(sfxinfo_t *sfx, float vol, int pitch, int chanflags)
FSoundChan *FMODSoundRenderer::StartSound(sfxinfo_t *sfx, float vol, int pitch, int chanflags, FSoundChan *reuse_chan)
{
int id = int(sfx - &S_sfx[0]);
FMOD_RESULT result;
@ -1417,8 +1390,9 @@ FSoundChan *FMODSoundRenderer::StartSound(sfxinfo_t *sfx, float vol, int pitch,
chan->setFrequency(freq);
}
chan->setVolume(vol);
HandleChannelDelay(chan, reuse_chan, freq);
chan->setPaused(false);
return CommonChannelSetup(chan);
return CommonChannelSetup(chan, reuse_chan);
}
DPrintf ("Sound %s failed to play: %d\n", sfx->name.GetChars(), result);
@ -1434,7 +1408,8 @@ FSoundChan *FMODSoundRenderer::StartSound(sfxinfo_t *sfx, float vol, int pitch,
CVAR(Float, snd_3dspread, 180, 0)
FSoundChan *FMODSoundRenderer::StartSound3D(sfxinfo_t *sfx, float vol, float distscale,
int pitch, int priority, float pos[3], float vel[3], sector_t *sector, int channum, int chanflags)
int pitch, int priority, float pos[3], float vel[3], sector_t *sector, int channum, int chanflags,
FSoundChan *reuse_chan)
{
int id = int(sfx - &S_sfx[0]);
FMOD_RESULT result;
@ -1460,6 +1435,11 @@ FSoundChan *FMODSoundRenderer::StartSound3D(sfxinfo_t *sfx, float vol, float dis
// Play it.
GSfxInfo = sfx;
GDistScale = distscale;
// Experiments indicate that playSound will ignore priorities and always succeed
// as long as the paremeters are set properly. It will first try to kick out sounds
// with the same priority level but has no problem with kicking out sounds at
// higher priority levels if it needs to.
result = Sys->playSound(FMOD_CHANNEL_FREE, (FMOD::Sound *)sfx->data, true, &chan);
// Then set the priority back.
@ -1503,9 +1483,9 @@ FSoundChan *FMODSoundRenderer::StartSound3D(sfxinfo_t *sfx, float vol, float dis
chan->set3DAttributes((FMOD_VECTOR *)pos, (FMOD_VECTOR *)vel);
chan->set3DSpread(snd_3dspread);
}
chan->setDelay(FMOD_DELAYTYPE_DSPCLOCK_START, DSPClockHi, DSPClockLo);
HandleChannelDelay(chan, reuse_chan, freq);
chan->setPaused(false);
FSoundChan *schan = CommonChannelSetup(chan);
FSoundChan *schan = CommonChannelSetup(chan, reuse_chan);
schan->DistanceScale = distscale;
return schan;
}
@ -1516,7 +1496,50 @@ FSoundChan *FMODSoundRenderer::StartSound3D(sfxinfo_t *sfx, float vol, float dis
//==========================================================================
//
// FMODSound :: SetChanHeadSettings
// FMODSoundRenderer :: HandleChannelDelay
//
// If the sound is restarting, seek it to its proper place.
// Otherwise, record its starting time.
//
//==========================================================================
void FMODSoundRenderer::HandleChannelDelay(FMOD::Channel *chan, FSoundChan *reuse_chan, float freq) const
{
if (reuse_chan != NULL)
{ // Sound is being restarted, so seek it to the position
// it would be in now if it had never been evicted.
QWORD_UNION nowtime;
chan->getDelay(FMOD_DELAYTYPE_DSPCLOCK_START, &nowtime.Hi, &nowtime.Lo);
// If the DSP is locked, the sounds are being restored, and
// the channel's start time is actually its seek position.
if (DSPLocked)
{
unsigned int seekpos = reuse_chan->StartTime.Lo;
if (seekpos > 0)
{
chan->setPosition(seekpos, FMOD_TIMEUNIT_PCM);
}
reuse_chan->StartTime.AsOne = QWORD(nowtime.AsOne - seekpos * OutputRate / freq);
}
else
{
QWORD difftime = nowtime.AsOne - reuse_chan->StartTime.AsOne;
if (difftime > 0)
{
chan->setPosition((unsigned int)(difftime / OutputRate), FMOD_TIMEUNIT_MS);
}
}
}
else
{
chan->setDelay(FMOD_DELAYTYPE_DSPCLOCK_START, DSPClock.Hi, DSPClock.Lo);
}
}
//==========================================================================
//
// FMODSoundRenderer :: SetChanHeadSettings
//
// If this sound is played at the same coordinates as the listener, make
// it head relative. Also, area sounds should use no 3D panning if close
@ -1567,6 +1590,11 @@ FMOD_MODE FMODSoundRenderer::SetChanHeadSettings(FMOD::Channel *chan, sfxinfo_t
{
cz = MAX(sec->ceilingplane.ZatPoint(cx, cy), players[consoleplayer].camera->z);
}
else if (channum == CHAN_INTERIOR)
{
cz = clamp(players[consoleplayer].camera->z, sec->floorplane.ZatPoint(cx, cy),
sec->ceilingplane.ZatPoint(cx, cy));
}
else
{
cz = players[consoleplayer].camera->z;
@ -1620,9 +1648,21 @@ FMOD_MODE FMODSoundRenderer::SetChanHeadSettings(FMOD::Channel *chan, sfxinfo_t
//
//==========================================================================
FSoundChan *FMODSoundRenderer::CommonChannelSetup(FMOD::Channel *chan) const
FSoundChan *FMODSoundRenderer::CommonChannelSetup(FMOD::Channel *chan, FSoundChan *reuse_chan) const
{
FSoundChan *schan = S_GetChannel(chan);
FSoundChan *schan;
if (reuse_chan != NULL)
{
schan = reuse_chan;
schan->ChanFlags &= ~CHAN_EVICTED;
schan->SysChannel = chan;
}
else
{
schan = S_GetChannel(chan);
chan->getDelay(FMOD_DELAYTYPE_DSPCLOCK_START, &schan->StartTime.Hi, &schan->StartTime.Lo);
}
chan->setUserData(schan);
chan->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, ChannelEndCallback, 0);
GSfxInfo = NULL;
@ -1642,8 +1682,38 @@ void FMODSoundRenderer::StopSound(FSoundChan *chan)
if (chan->SysChannel != NULL)
{
// S_EvictAllChannels() will set the CHAN_EVICTED flag to indicate
// that it wants to keep all the channel information around.
if (!(chan->ChanFlags & CHAN_EVICTED))
{
chan->ChanFlags |= CHAN_FORGETTABLE;
}
((FMOD::Channel *)chan->SysChannel)->stop();
}
else
{
S_ReturnChannel(chan);
}
}
//==========================================================================
//
// FMODSoundRenderer :: GetPosition
//
// Returns position of sound on this channel, in samples.
//
//==========================================================================
unsigned int FMODSoundRenderer::GetPosition(FSoundChan *chan)
{
unsigned int pos;
if (chan == NULL || chan->SysChannel == NULL)
{
return 0;
}
((FMOD::Channel *)chan->SysChannel)->getPosition(&pos, FMOD_TIMEUNIT_PCM);
return pos;
}
//==========================================================================
@ -1816,6 +1886,29 @@ void FMODSoundRenderer::UpdateListener()
}
}
//==========================================================================
//
// FMODSoundRenderer :: Sync
//
// Used by the save/load code to restart sounds at the same position they
// were in at the time of saving. Must not be nested.
//
//==========================================================================
void FMODSoundRenderer::Sync(bool sync)
{
DSPLocked = sync;
if (sync)
{
Sys->lockDSP();
Sys->getDSPClock(&DSPClock.Hi, &DSPClock.Lo);
}
else
{
Sys->unlockDSP();
}
}
//==========================================================================
//
// FMODSoundRenderer :: UpdateSounds
@ -1826,9 +1919,8 @@ void FMODSoundRenderer::UpdateSounds()
{
// Any sounds played between now and the next call to this function
// will start exactly one tic from now.
Sys->getDSPClock(&DSPClockHi, &DSPClockLo);
FMOD_64BIT_ADD(DSPClockHi, DSPClockLo, 0, OutputRate / TICRATE);
Sys->getDSPClock(&DSPClock.Hi, &DSPClock.Lo);
DSPClock.AsOne += OutputRate / TICRATE;
Sys->update();
}
@ -2064,7 +2156,58 @@ FMOD_RESULT F_CALLBACK FMODSoundRenderer::ChannelEndCallback
if (chan->getUserData((void **)&schan) == FMOD_OK && schan != NULL)
{
S_ReturnChannel(schan);
bool evicted;
// If the sound was stopped with GSnd->StopSound(), then we know
// it wasn't evicted. Otherwise, if it's looping, it must have
// been evicted. If it's not looping, then it was evicted if it
// didn't reach the end of its playback.
if (schan->ChanFlags & CHAN_FORGETTABLE)
{
evicted = false;
}
else if (schan->ChanFlags & (CHAN_LOOP | CHAN_EVICTED))
{
evicted = true;
}
else
{
FMOD::Sound *sound;
unsigned int len, pos;
evicted = false; // Assume not evicted
if (FMOD_OK == chan->getPosition(&pos, FMOD_TIMEUNIT_PCM))
{
// If position is 0, then this sound either didn't have
// a chance to play at all, or it stopped normally.
if (pos == 0)
{
if (schan->ChanFlags & CHAN_JUSTSTARTED)
{
evicted = true;
}
}
else if (FMOD_OK == chan->getCurrentSound(&sound))
{
if (FMOD_OK == sound->getLength(&len, FMOD_TIMEUNIT_PCM))
{
if (pos < len)
{
evicted = true;
}
}
}
}
}
if (!evicted)
{
S_ReturnChannel(schan);
}
else
{
schan->ChanFlags |= CHAN_EVICTED;
schan->SysChannel = NULL;
}
}
return FMOD_OK;
}

View file

@ -25,24 +25,27 @@ public:
void StopStream (SoundStream *stream);
// Starts a sound.
FSoundChan *StartSound (sfxinfo_t *sfx, float vol, int pitch, int chanflags);
FSoundChan *StartSound3D (sfxinfo_t *sfx, float vol, float distscale, int pitch, int priority, float pos[3], float vel[3], sector_t *sector, int channum, int chanflags);
FSoundChan *StartSound (sfxinfo_t *sfx, float vol, int pitch, int chanflags, FSoundChan *reuse_chan);
FSoundChan *StartSound3D (sfxinfo_t *sfx, float vol, float distscale, int pitch, int priority, float pos[3], float vel[3], sector_t *sector, int channum, int chanflags, FSoundChan *reuse_chan);
// Stops a sound channel.
void StopSound (FSoundChan *chan);
// Returns position of sound on this channel, in samples.
unsigned int GetPosition(FSoundChan *chan);
// Synchronizes following sound startups.
void Sync (bool sync);
// Pauses or resumes all sound effect channels.
void SetSfxPaused (bool paused);
// Pauses or resumes *every* channel, including environmental reverb.
void SetInactive (bool inactive);
// Updates the position of a sound channel.
void UpdateSoundParams3D (FSoundChan *chan, float pos[3], float vel[3]);
// For use by I_PlayMovie
void MovieDisableSound ();
void MovieResumeSound ();
void UpdateListener ();
void UpdateSounds ();
@ -56,15 +59,16 @@ public:
private:
bool SFXPaused;
bool InitSuccess;
unsigned int DSPClockLo;
unsigned int DSPClockHi;
bool DSPLocked;
QWORD_UNION DSPClock;
int OutputRate;
static FMOD_RESULT F_CALLBACK ChannelEndCallback
(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type, int cmd, unsigned int data1, unsigned int data2);
static float F_CALLBACK RolloffCallback(FMOD_CHANNEL *channel, float distance);
FSoundChan *CommonChannelSetup(FMOD::Channel *chan) const;
void HandleChannelDelay(FMOD::Channel *chan, FSoundChan *reuse_chan, float freq) const;
FSoundChan *CommonChannelSetup(FMOD::Channel *chan, FSoundChan *reuse_chan) const;
FMOD_MODE SetChanHeadSettings(FMOD::Channel *chan, sfxinfo_t *sfx, float pos[3], int channum, int chanflags, sector_t *sec, FMOD_MODE oldmode) const;
void DoLoad (void **slot, sfxinfo_t *sfx);
void getsfx (sfxinfo_t *sfx);

View file

@ -155,16 +155,16 @@ CCMD (snd_status)
CCMD (snd_reset)
{
SoundRenderer *snd = GSnd;
if (snd != NULL)
I_ShutdownMusic();
S_EvictAllChannels();
if (GSnd != NULL)
{
snd->MovieDisableSound ();
delete GSnd;
GSnd = NULL;
}
I_InitSound ();
S_Init ();
S_RestartMusic ();
if (snd != NULL) delete snd;
I_InitSound();
S_RestartMusic();
S_RestoreEvictedChannels();
}
CCMD (snd_listdrivers)

View file

@ -89,12 +89,18 @@ public:
virtual SoundStream *OpenStream (const char *filename, int flags, int offset, int length) = 0;
// Starts a sound.
virtual FSoundChan *StartSound (sfxinfo_t *sfx, float vol, int pitch, int chanflags) = 0;
virtual FSoundChan *StartSound3D (sfxinfo_t *sfx, float vol, float distscale, int pitch, int priority, float pos[3], float vel[3], sector_t *sector, int channum, int chanflags) = 0;
virtual FSoundChan *StartSound (sfxinfo_t *sfx, float vol, int pitch, int chanflags, FSoundChan *reuse_chan) = 0;
virtual FSoundChan *StartSound3D (sfxinfo_t *sfx, float vol, float distscale, int pitch, int priority, float pos[3], float vel[3], sector_t *sector, int channum, int chanflags, FSoundChan *reuse_chan) = 0;
// Stops a sound channel.
virtual void StopSound (FSoundChan *chan) = 0;
// Returns position of sound on this channel, in samples.
virtual unsigned int GetPosition(FSoundChan *chan) = 0;
// Synchronizes following sound startups.
virtual void Sync (bool sync) = 0;
// Pauses or resumes all sound effect channels.
virtual void SetSfxPaused (bool paused) = 0;
@ -104,10 +110,6 @@ public:
// Updates the volume, separation, and pitch of a sound channel.
virtual void UpdateSoundParams3D (FSoundChan *chan, float pos[3], float vel[3]) = 0;
// For use by I_PlayMovie
virtual void MovieDisableSound () = 0;
virtual void MovieResumeSound () = 0;
virtual void UpdateListener () = 0;
virtual void UpdateSounds () = 0;

View file

@ -75,7 +75,7 @@
// SAVESIG should match SAVEVER.
// MINSAVEVER is the minimum level snapshot version that can be loaded.
#define MINSAVEVER 1044
#define MINSAVEVER 1055
#if SVN_REVISION_NUMBER < MINSAVEVER
// Never write a savegame with a version lower than what we need

View file

@ -811,16 +811,19 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
}
if(GSnd != NULL)
if (GSnd != NULL)
{
#if 0
// Do we actually need this here?
if (!oldstate && SessionState)
{
GSnd->MovieDisableSound ();
GSnd->SuspendSound ();
}
else if (oldstate && !SessionState)
{
GSnd->MovieResumeSound ();
}
#endif
}
#ifdef _DEBUG
char foo[256];

View file

@ -37,6 +37,10 @@
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
#ifndef I_DO_NOT_LIKE_BIG_DOWNLOADS
#define I_DO_NOT_LIKE_BIG_DOWNLOADS
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define USE_WINDOWS_DWORD