diff --git a/docs/rh-log.txt b/docs/rh-log.txt index b3b3fbe569..62e28cfb1f 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,6 @@ January 24, 2009 +- Removed the SoundChans bitfield from AActor, since it seems there are race + conditions I don't fully understand where it simply doesn't work. - Removed BaseTime initialization from sdl/i_system.cpp as per Chris's recommendation. diff --git a/src/actor.h b/src/actor.h index d023be81cb..b4054c3730 100644 --- a/src/actor.h +++ b/src/actor.h @@ -679,7 +679,6 @@ public: TObjPtr LastLookActor; // Actor last looked for (if TIDtoHate != 0) fixed_t SpawnPoint[3]; // For nightmare respawn WORD SpawnAngle; - BYTE SoundChans; // Bitfield indicating which sound channels are playing. int skillrespawncount; TObjPtr tracer; // Thing being chased/attacked for tracers TObjPtr master; // Thing which spawned this one (prevents mutual attacks) diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 63c92fa532..d5d9465fb9 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -135,7 +135,7 @@ public: int Amount; // Amount of item this instance has int MaxAmount; // Max amount of item this instance can have int RespawnTics; // Tics from pickup time to respawn time - FTextureID Icon; // Icon to show on status bar or HUD + FTextureID Icon; // Icon to show on status bar or HUD int DropTime; // Countdown after dropping const PClass *SpawnPointClass; // For respawning like Heretic's mace diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index d0bce101f3..8a13b15a0a 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -196,7 +196,8 @@ AInventory *AWeapon::CreateCopy (AActor *other) // // A weapon that's tossed out should contain no ammo, so you can't cheat // by dropping it and then picking it back up. -//======================= +// +//=========================================================================== AInventory *AWeapon::CreateTossable () { diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 1e923485ee..07b1cb8c83 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -100,6 +100,7 @@ extern float S_GetMusicVolume (const char *music); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static bool S_CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_limit); +static bool S_IsChannelUsed(AActor *actor, int channel, int *seen); static void S_ActivatePlayList(bool goBack); static void CalcPosVel(FSoundChan *chan, FVector3 *pos, FVector3 *vel); static void CalcPosVel(int type, const AActor *actor, const sector_t *sector, const FPolyObj *poly, @@ -572,10 +573,6 @@ FISoundChannel *S_GetChannel(void *syschan) void S_ReturnChannel(FSoundChan *chan) { - if (chan->SourceType == SOURCE_Actor && chan->Actor != NULL) - { - chan->Actor->SoundChans &= ~(1 << chan->EntChannel); - } S_UnlinkChannel(chan); memset(chan, 0, sizeof(*chan)); S_LinkChannel(chan, &FreeChannels); @@ -950,20 +947,20 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO basepriority = 0; } + int seen = 0; if (actor != NULL && channel == CHAN_AUTO) - { // Select a channel that isn't already playing something. - BYTE mask = actor->SoundChans; - + { + // Select a channel that isn't already playing something. // Try channel 0 first, then travel from channel 7 down. - if ((mask & 1) == 0) + if (!S_IsChannelUsed(actor, 0, &seen)) { channel = 0; } else { - for (channel = 7; channel > 0; --channel, mask <<= 1) + for (channel = 7; channel > 0; --channel) { - if ((mask & 0x80) == 0) + if (!S_IsChannelUsed(actor, channel, &seen)) { break; } @@ -976,7 +973,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO } // If this actor is already playing something on the selected channel, stop it. - if (type != SOURCE_None && ((actor == NULL && channel != CHAN_AUTO) || (actor != NULL && actor->SoundChans & (1 << channel)))) + if (type != SOURCE_None && ((actor == NULL && channel != CHAN_AUTO) || (actor != NULL && S_IsChannelUsed(actor, channel, &seen)))) { for (chan = Channels; chan != NULL; chan = chan->NextChan) { @@ -1068,7 +1065,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO chan->SourceType = type; switch (type) { - case SOURCE_Actor: chan->Actor = actor; actor->SoundChans |= 1 << channel; break; + case SOURCE_Actor: chan->Actor = actor; break; case SOURCE_Sector: chan->Sector = sec; break; case SOURCE_Polyobj: chan->Poly = poly; break; case SOURCE_Unattached: chan->Point[0] = pt->X; chan->Point[1] = pt->Y; chan->Point[2] = pt->Z; break; @@ -1139,17 +1136,10 @@ void S_RestartSound(FSoundChan *chan) ochan = (FSoundChan*)GSnd->StartSound(sfx->data, chan->Volume, chan->Pitch, startflags, chan); } assert(ochan == NULL || ochan == chan); - if (ochan != NULL) + if (ochan == NULL) { - // When called from the savegame loader, the actor's SoundChans - // flags will be cleared. During normal gameplay, they should still - // be set. - if (ochan->SourceType == SOURCE_Actor) - { - if (ochan->Actor != NULL) ochan->Actor->SoundChans |= 1 << ochan->EntChannel; - } + chan->ChanFlags = oldflags; } - else chan->ChanFlags = oldflags; } //========================================================================== @@ -1390,17 +1380,13 @@ void S_StopSound (int channel) void S_StopSound (AActor *actor, int channel) { - // No need to search every channel if we know it's not playing anything. - if (actor != NULL && actor->SoundChans & (1 << channel)) + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { - for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + if (chan->SourceType == SOURCE_Actor && + chan->Actor == actor && + (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) { - if (chan->SourceType == SOURCE_Actor && - chan->Actor == actor && - (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) - { - S_StopChannel(chan); - } + S_StopChannel(chan); } } } @@ -1502,11 +1488,6 @@ void S_RelinkSound (AActor *from, AActor *to) } } } - if (to != NULL) - { - to->SoundChans = from->SoundChans; - } - from->SoundChans = 0; } //========================================================================== @@ -1567,6 +1548,36 @@ bool S_GetSoundPlayingInfo (const FPolyObj *poly, int sound_id) return false; } +//========================================================================== +// +// S_IsChannelUsed +// +// Returns true if the channel is in use. Also fills in a bitmask of +// channels seen while scanning for this one, to make searching for unused +// channels faster. Initialize seen to 0 for the first call. +// +//========================================================================== + +bool S_IsChannelUsed(AActor *actor, int channel, int *seen) +{ + if (*seen & (1 << channel)) + { + return true; + } + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + { + if (chan->SourceType == SOURCE_Actor && chan->Actor == actor) + { + *seen |= 1 << chan->EntChannel; + if (chan->EntChannel == channel) + { + return true; + } + } + } + return false; +} + //========================================================================== // // S_IsActorPlayingSomething @@ -1575,11 +1586,6 @@ bool S_GetSoundPlayingInfo (const FPolyObj *poly, int sound_id) bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id) { - if (actor->SoundChans == 0) - { - return false; - } - if (i_compatflags & COMPATF_MAGICSILENCE) { channel = 0; @@ -1933,9 +1939,8 @@ void S_StopChannel(FSoundChan *chan) chan->ChanFlags |= CHAN_FORGETTABLE; } - if (chan->SourceType == SOURCE_Actor && chan->Actor != NULL) + if (chan->SourceType == SOURCE_Actor) { - chan->Actor->SoundChans &= ~(1 << chan->EntChannel); chan->Actor = NULL; }