- 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_NONE = 0,
CHANF_IS3D = 1, // internal: Sound is 3D.
CHANF_EVICTED = 2, // internal: Sound was evicted.
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.
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);
TArray<uint8_t> ReadSound(int lumpnum);
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)
{

View file

@ -335,7 +335,7 @@ FString SoundEngine::ListSoundChannels()
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)
@ -397,7 +397,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
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))
{
@ -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) startflags |= SNDF_NOREVERB;
if (attenuation > 0)
if (attenuation > 0 && type != SOURCE_None)
{
LoadSound3D(sfx, &SoundBuffer);
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.
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);
sfx->link = i;
@ -1060,6 +1061,16 @@ void SoundEngine::ChangeSoundVolume(int sourcetype, const void *source, int chan
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
@ -1153,7 +1164,7 @@ bool SoundEngine::IsSourcePlayingSomething (int sourcetype, const void *actor, i
{
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))
{
@ -1558,6 +1569,14 @@ int SoundEngine::AddSoundLump(const char* logicalname, int lump, int CurrentPitc
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

View file

@ -262,7 +262,7 @@ private:
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.
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.
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 SetPitch(FSoundChan* chan, float dpitch);
void SetVolume(FSoundChan* chan, float vol);
FSoundChan* GetChannel(void* syschan);
void RestoreEvictedChannels();
@ -316,7 +317,7 @@ public:
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 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.
int GetSoundPlayingInfo(int sourcetype, const void* source, int sound_id);
@ -375,12 +376,17 @@ public:
{
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)
{
for (FSoundChan* chan = Channels; chan; chan = chan->NextChan)
{
if (callback(chan)) return true;
int res = callback(chan);
if (res) return res > 0;
}
return false;
}
@ -403,6 +409,7 @@ public:
int FindSoundNoHash(const char* logicalname);
int FindSoundByLump(int lump);
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);
void CacheRandomSound(sfxinfo_t* sfx);
unsigned int GetMSLength(FSoundID sound);