- sound engine update.

Notable changes:
* IsSourcePlayingSomething had undefined behavior when checking unattached and unpositioned sounds.
* loading Blood RAW sounds with different sample rates but the same backing lump may not use the same hardware sound buffer.
* when playing an unpositioned sound the attenuation is irrelevant and must be ignored. This resulted in a 3D sound being started which was mostly inaudible due to lack of valid origin.
This commit is contained in:
Christoph Oelckers 2019-12-19 11:57:58 +01:00
parent 59f09d4893
commit 318da33e39
4 changed files with 37 additions and 10 deletions

View File

@ -22,6 +22,7 @@ enum EChanFlag
CHANF_PICKUP = CHANF_MAYBE_LOCAL, CHANF_PICKUP = CHANF_MAYBE_LOCAL,
CHANF_NONE = 0,
CHANF_IS3D = 1, // internal: Sound is 3D. CHANF_IS3D = 1, // internal: Sound is 3D.
CHANF_EVICTED = 2, // internal: Sound was evicted. CHANF_EVICTED = 2, // internal: Sound was evicted.
CHANF_FORGETTABLE = 4, // internal: Forget channel data when sound stops. CHANF_FORGETTABLE = 4, // internal: Forget channel data when sound stops.

View File

@ -85,7 +85,7 @@ class DoomSoundEngine : public SoundEngine
{ {
// client specific parts of the sound engine go in this class. // client specific parts of the sound engine go in this class.
void CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID soundid, FVector3* pos, FVector3* vel) override; void CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID soundid, FVector3* pos, FVector3* vel, FSoundChan *) override;
bool ValidatePosVel(int sourcetype, const void* source, const FVector3& pos, const FVector3& vel); bool ValidatePosVel(int sourcetype, const void* source, const FVector3& pos, const FVector3& vel);
TArray<uint8_t> ReadSound(int lumpnum); TArray<uint8_t> ReadSound(int lumpnum);
int PickReplacement(int refid); int PickReplacement(int refid);
@ -892,7 +892,7 @@ static void CalcPolyobjSoundOrg(const DVector3& listenpos, const FPolyObj* poly,
// //
//========================================================================= //=========================================================================
void DoomSoundEngine::CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID soundid, FVector3* pos, FVector3* vel) void DoomSoundEngine::CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID soundid, FVector3* pos, FVector3* vel, FSoundChan *)
{ {
if (pos != nullptr) if (pos != nullptr)
{ {

View File

@ -335,7 +335,7 @@ FString SoundEngine::ListSoundChannels()
void SoundEngine::CalcPosVel(FSoundChan *chan, FVector3 *pos, FVector3 *vel) void SoundEngine::CalcPosVel(FSoundChan *chan, FVector3 *pos, FVector3 *vel)
{ {
CalcPosVel(chan->SourceType, chan->Source, chan->Point, chan->EntChannel, chan->ChanFlags, chan->OrgID, pos, vel); CalcPosVel(chan->SourceType, chan->Source, chan->Point, chan->EntChannel, chan->ChanFlags, chan->OrgID, pos, vel, chan);
} }
bool SoundEngine::ValidatePosVel(const FSoundChan* const chan, const FVector3& pos, const FVector3& vel) bool SoundEngine::ValidatePosVel(const FSoundChan* const chan, const FVector3& pos, const FVector3& vel)
@ -397,7 +397,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
org_id = sound_id; org_id = sound_id;
CalcPosVel(type, source, &pt->X, channel, chanflags, sound_id, &pos, &vel); CalcPosVel(type, source, &pt->X, channel, chanflags, sound_id, &pos, &vel, nullptr);
if (!ValidatePosVel(type, source, pos, vel)) if (!ValidatePosVel(type, source, pos, vel))
{ {
@ -577,7 +577,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
if (chanflags & (CHANF_UI|CHANF_NOPAUSE)) startflags |= SNDF_NOPAUSE; if (chanflags & (CHANF_UI|CHANF_NOPAUSE)) startflags |= SNDF_NOPAUSE;
if (chanflags & CHANF_UI) startflags |= SNDF_NOREVERB; if (chanflags & CHANF_UI) startflags |= SNDF_NOREVERB;
if (attenuation > 0) if (attenuation > 0 && type != SOURCE_None)
{ {
LoadSound3D(sfx, &SoundBuffer); LoadSound3D(sfx, &SoundBuffer);
chan = (FSoundChan*)GSnd->StartSound3D (sfx->data3d, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL); chan = (FSoundChan*)GSnd->StartSound3D (sfx->data3d, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL);
@ -727,7 +727,8 @@ sfxinfo_t *SoundEngine::LoadSound(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer)
// then set this one up as a link, and don't load the sound again. // then set this one up as a link, and don't load the sound again.
for (i = 0; i < S_sfx.Size(); i++) for (i = 0; i < S_sfx.Size(); i++)
{ {
if (S_sfx[i].data.isValid() && S_sfx[i].link == sfxinfo_t::NO_LINK && S_sfx[i].lumpnum == sfx->lumpnum) if (S_sfx[i].data.isValid() && S_sfx[i].link == sfxinfo_t::NO_LINK && S_sfx[i].lumpnum == sfx->lumpnum &&
(!sfx->bLoadRAW || (sfx->RawRate == S_sfx[i].RawRate))) // Raw sounds with different sample rates may not share buffers, even if they use the same source data.
{ {
//DPrintf (DMSG_NOTIFY, "Linked %s to %s (%d)\n", sfx->name.GetChars(), S_sfx[i].name.GetChars(), i); //DPrintf (DMSG_NOTIFY, "Linked %s to %s (%d)\n", sfx->name.GetChars(), S_sfx[i].name.GetChars(), i);
sfx->link = i; sfx->link = i;
@ -1060,6 +1061,16 @@ void SoundEngine::ChangeSoundVolume(int sourcetype, const void *source, int chan
return; return;
} }
void SoundEngine::SetVolume(FSoundChan* chan, float volume)
{
if (volume < 0.0) volume = 0.0;
else if (volume > 1.0) volume = 1.0;
assert(chan != nullptr);
GSnd->ChannelVolume(chan, volume);
chan->Volume = volume;
}
//========================================================================== //==========================================================================
// //
// S_ChangeSoundPitch // S_ChangeSoundPitch
@ -1153,7 +1164,7 @@ bool SoundEngine::IsSourcePlayingSomething (int sourcetype, const void *actor, i
{ {
for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan)
{ {
if (chan->SourceType == sourcetype && chan->Source == actor) if (chan->SourceType == sourcetype && (sourcetype == SOURCE_None || sourcetype == SOURCE_Unattached || chan->Source == actor))
{ {
if ((channel == 0 || chan->EntChannel == channel) && (sound_id <= 0 || chan->OrgID == sound_id)) if ((channel == 0 || chan->EntChannel == channel) && (sound_id <= 0 || chan->OrgID == sound_id))
{ {
@ -1558,6 +1569,14 @@ int SoundEngine::AddSoundLump(const char* logicalname, int lump, int CurrentPitc
return (int)S_sfx.Size()-1; return (int)S_sfx.Size()-1;
} }
int SoundEngine::AddSfx(sfxinfo_t &sfx)
{
S_sfx.Push(sfx);
if (sfx.ResourceId >= 0) ResIdMap[sfx.ResourceId] = S_sfx.Size() - 1;
return (int)S_sfx.Size() - 1;
}
//========================================================================== //==========================================================================
// //
// S_FindSoundTentative // S_FindSoundTentative

View File

@ -262,7 +262,7 @@ private:
bool IsChannelUsed(int sourcetype, const void* actor, int channel, int* seen); bool IsChannelUsed(int sourcetype, const void* actor, int channel, int* seen);
// This is the actual sound positioning logic which needs to be provided by the client. // This is the actual sound positioning logic which needs to be provided by the client.
virtual void CalcPosVel(int type, const void* source, const float pt[3], int channel, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel) = 0; virtual void CalcPosVel(int type, const void* source, const float pt[3], int channel, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan *chan) = 0;
// This can be overridden by the clent to provide some diagnostics. The default lets everything pass. // This can be overridden by the clent to provide some diagnostics. The default lets everything pass.
virtual bool ValidatePosVel(int sourcetype, const void* source, const FVector3& pos, const FVector3& vel) { return true; } virtual bool ValidatePosVel(int sourcetype, const void* source, const FVector3& pos, const FVector3& vel) { return true; }
@ -293,6 +293,7 @@ public:
void StopAllChannels(void); void StopAllChannels(void);
void SetPitch(FSoundChan* chan, float dpitch); void SetPitch(FSoundChan* chan, float dpitch);
void SetVolume(FSoundChan* chan, float vol);
FSoundChan* GetChannel(void* syschan); FSoundChan* GetChannel(void* syschan);
void RestoreEvictedChannels(); void RestoreEvictedChannels();
@ -316,7 +317,7 @@ public:
void RelinkSound(int sourcetype, const void* from, const void* to, const FVector3* optpos); void RelinkSound(int sourcetype, const void* from, const void* to, const FVector3* optpos);
void ChangeSoundVolume(int sourcetype, const void* source, int channel, double dvolume); void ChangeSoundVolume(int sourcetype, const void* source, int channel, double dvolume);
void ChangeSoundPitch(int sourcetype, const void* source, int channel, double pitch, int sound_id = -1); void ChangeSoundPitch(int sourcetype, const void* source, int channel, double pitch, int sound_id = -1);
bool IsSourcePlayingSomething(int sourcetype, const void* actor, int channel, int sound_id); bool IsSourcePlayingSomething(int sourcetype, const void* actor, int channel, int sound_id = -1);
// Stop and resume music, during game PAUSE. // Stop and resume music, during game PAUSE.
int GetSoundPlayingInfo(int sourcetype, const void* source, int sound_id); int GetSoundPlayingInfo(int sourcetype, const void* source, int sound_id);
@ -375,12 +376,17 @@ public:
{ {
S_rnd.Clear(); S_rnd.Clear();
} }
bool isValidSoundId(int id)
{
return id > 0 && id < (int)S_sfx.Size() && !S_sfx[id].bTentative && S_sfx[id].lumpnum != sfx_empty;
}
template<class func> bool EnumerateChannels(func callback) template<class func> bool EnumerateChannels(func callback)
{ {
for (FSoundChan* chan = Channels; chan; chan = chan->NextChan) for (FSoundChan* chan = Channels; chan; chan = chan->NextChan)
{ {
if (callback(chan)) return true; int res = callback(chan);
if (res) return res > 0;
} }
return false; return false;
} }
@ -403,6 +409,7 @@ public:
int FindSoundNoHash(const char* logicalname); int FindSoundNoHash(const char* logicalname);
int FindSoundByLump(int lump); int FindSoundByLump(int lump);
int AddSoundLump(const char* logicalname, int lump, int CurrentPitchMask, int resid = -1, int nearlimit = 2); int AddSoundLump(const char* logicalname, int lump, int CurrentPitchMask, int resid = -1, int nearlimit = 2);
int AddSfx(sfxinfo_t &sfx);
int FindSoundTentative(const char* name); int FindSoundTentative(const char* name);
void CacheRandomSound(sfxinfo_t* sfx); void CacheRandomSound(sfxinfo_t* sfx);
unsigned int GetMSLength(FSoundID sound); unsigned int GetMSLength(FSoundID sound);