- continued refactoring on sound code.

The game independent part of the code has been mostly isolated.
This commit is contained in:
Christoph Oelckers 2019-12-08 21:22:53 +01:00
parent fd181f469d
commit b9582cc98e
22 changed files with 1545 additions and 1331 deletions

View file

@ -208,9 +208,7 @@ extern bool ParsingKeyConf, UnsafeExecutionContext;
void ResetButtonTriggers (); // Call ResetTriggers for all buttons void ResetButtonTriggers (); // Call ResetTriggers for all buttons
void ResetButtonStates (); // Same as above, but also clear bDown void ResetButtonStates (); // Same as above, but also clear bDown
extern unsigned int MakeKey (const char *s); #include "superfasthash.h"
extern unsigned int MakeKey (const char *s, size_t len);
extern unsigned int SuperFastHash (const char *data, size_t len);
void execLogfile(const char *fn, bool append = false); void execLogfile(const char *fn, bool append = false);

View file

@ -364,7 +364,7 @@ static FSoundID T_FindSound(const char * name)
} }
int id = S_AddSound(name, buffer); int id = S_AddSound(name, buffer);
S_HashSounds(); soundEngine->HashSounds();
return FSoundID(id); return FSoundID(id);
} }

View file

@ -4387,11 +4387,11 @@ int DLevelScript::GetActorProperty (int tid, int property)
return 0; return 0;
} }
case APROP_SeeSound: return GlobalACSStrings.AddString(actor->SeeSound); case APROP_SeeSound: return GlobalACSStrings.AddString(S_GetSoundName(actor->SeeSound));
case APROP_AttackSound: return GlobalACSStrings.AddString(actor->AttackSound); case APROP_AttackSound: return GlobalACSStrings.AddString(S_GetSoundName(actor->AttackSound));
case APROP_PainSound: return GlobalACSStrings.AddString(actor->PainSound); case APROP_PainSound: return GlobalACSStrings.AddString(S_GetSoundName(actor->PainSound));
case APROP_DeathSound: return GlobalACSStrings.AddString(actor->DeathSound); case APROP_DeathSound: return GlobalACSStrings.AddString(S_GetSoundName(actor->DeathSound));
case APROP_ActiveSound: return GlobalACSStrings.AddString(actor->ActiveSound); case APROP_ActiveSound: return GlobalACSStrings.AddString(S_GetSoundName(actor->ActiveSound));
case APROP_Species: return GlobalACSStrings.AddString(actor->GetSpecies()); case APROP_Species: return GlobalACSStrings.AddString(actor->GetSpecies());
case APROP_NameTag: return GlobalACSStrings.AddString(actor->GetTag()); case APROP_NameTag: return GlobalACSStrings.AddString(actor->GetTag());
case APROP_StencilColor:return actor->fillcolor; case APROP_StencilColor:return actor->fillcolor;
@ -4464,11 +4464,11 @@ int DLevelScript::CheckActorProperty (int tid, int property, int value)
// Strings are covered by GetActorProperty, but they're fairly // Strings are covered by GetActorProperty, but they're fairly
// heavy-duty, so make the check here. // heavy-duty, so make the check here.
case APROP_SeeSound: string = actor->SeeSound; break; case APROP_SeeSound: string = S_GetSoundName(actor->SeeSound); break;
case APROP_AttackSound: string = actor->AttackSound; break; case APROP_AttackSound: string = S_GetSoundName(actor->AttackSound); break;
case APROP_PainSound: string = actor->PainSound; break; case APROP_PainSound: string = S_GetSoundName(actor->PainSound); break;
case APROP_DeathSound: string = actor->DeathSound; break; case APROP_DeathSound: string = S_GetSoundName(actor->DeathSound); break;
case APROP_ActiveSound: string = actor->ActiveSound; break; case APROP_ActiveSound: string = S_GetSoundName(actor->ActiveSound); break;
case APROP_Species: string = actor->GetSpecies(); break; case APROP_Species: string = actor->GetSpecies(); break;
case APROP_NameTag: string = actor->GetTag(); break; case APROP_NameTag: string = actor->GetTag(); break;
case APROP_DamageType: string = actor->DamageType; break; case APROP_DamageType: string = actor->DamageType; break;
@ -5265,7 +5265,7 @@ int DLevelScript::SwapActorTeleFog(AActor *activator, int tid)
} }
else if (rettype == TypeSound) else if (rettype == TypeSound)
{ {
retval = GlobalACSStrings.AddString(FSoundID(retval)); retval = GlobalACSStrings.AddString(S_GetSoundName(FSoundID(retval)));
} }
} }
else if (rettype == TypeFloat64) else if (rettype == TypeFloat64)

View file

@ -731,7 +731,7 @@ void R_InitSkins (void)
} }
else else
{ {
int sndref = S_FindSoundNoHash (key); int sndref = soundEngine->FindSoundNoHash (key);
if (sndref != 0) if (sndref != 0)
{ {
S_AddPlayerSound (Skins[i].Name, Skins[i].gender, sndref, lump, true); S_AddPlayerSound (Skins[i].Name, Skins[i].gender, sndref, lump, true);
@ -911,7 +911,7 @@ void R_InitSkins (void)
if (Skins.Size() > PlayerClasses.Size ()) if (Skins.Size() > PlayerClasses.Size ())
{ // The sound table may have changed, so rehash it. { // The sound table may have changed, so rehash it.
S_HashSounds (); soundEngine->HashSounds ();
S_ShrinkPlayerSoundLists (); S_ShrinkPlayerSoundLists ();
} }
} }

View file

@ -1243,7 +1243,7 @@ FxExpression *FxStringCast::Resolve(FCompileContext &ctx)
if (basex->isConstant()) if (basex->isConstant())
{ {
ExpVal constval = static_cast<FxConstant *>(basex)->GetValue(); ExpVal constval = static_cast<FxConstant *>(basex)->GetValue();
FxExpression *x = new FxConstant(S_sfx[constval.GetInt()].name, ScriptPosition); FxExpression *x = new FxConstant(S_GetSoundName(constval.GetInt()), ScriptPosition);
delete this; delete this;
return x; return x;
} }

View file

@ -1184,7 +1184,7 @@ PSound::PSound()
void PSound::WriteValue(FSerializer &ar, const char *key,const void *addr) const void PSound::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{ {
const char *cptr = *(const FSoundID *)addr; const char *cptr = S_GetSoundName(*(const FSoundID *)addr);
ar.StringPtr(key, cptr); ar.StringPtr(key, cptr);
} }

View file

@ -51,7 +51,7 @@ static void CastN2S(FString *a, int b) { FName name = FName(ENamedName(b)); *a =
static int CastS2Co(FString *b) { return V_GetColor(nullptr, *b); } static int CastS2Co(FString *b) { return V_GetColor(nullptr, *b); }
static void CastCo2S(FString *a, int b) { PalEntry c(b); a->Format("%02x %02x %02x", c.r, c.g, c.b); } static void CastCo2S(FString *a, int b) { PalEntry c(b); a->Format("%02x %02x %02x", c.r, c.g, c.b); }
static int CastS2So(FString *b) { return FSoundID(*b); } static int CastS2So(FString *b) { return FSoundID(*b); }
static void CastSo2S(FString *a, int b) { *a = S_sfx[b].name; } static void CastSo2S(FString* a, int b) { *a = S_GetSoundName(b); }
static void CastSID2S(FString *a, unsigned int b) { *a = (b >= sprites.Size()) ? "TNT1" : sprites[b].name; } static void CastSID2S(FString *a, unsigned int b) { *a = (b >= sprites.Size()) ? "TNT1" : sprites[b].name; }
static void CastTID2S(FString *a, int b) { auto tex = TexMan.GetTexture(*(FTextureID*)&b); *a = (tex == nullptr) ? "(null)" : tex->GetName().GetChars(); } static void CastTID2S(FString *a, int b) { auto tex = TexMan.GetTexture(*(FTextureID*)&b); *a = (tex == nullptr) ? "(null)" : tex->GetName().GetChars(); }

View file

@ -1837,7 +1837,7 @@ static void DoCast(const VMRegisters &reg, const VMFrame *f, int a, int b, int c
case CAST_So2S: case CAST_So2S:
ASSERTS(a); ASSERTD(b); ASSERTS(a); ASSERTD(b);
reg.s[a] = S_sfx[reg.d[b]].name; reg.s[a] = S_GetSoundName(reg.d[b]);
break; break;
case CAST_SID2S: case CAST_SID2S:

View file

@ -1663,7 +1663,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundI
if (!arc.w->inObject() || def == nullptr || sid != *def) if (!arc.w->inObject() || def == nullptr || sid != *def)
{ {
arc.WriteKey(key); arc.WriteKey(key);
const char *sn = (const char*)sid; const char *sn = S_GetSoundName(sid);
if (sn != nullptr) arc.w->String(sn); if (sn != nullptr) arc.w->String(sn);
else arc.w->Null(); else arc.w->Null();
} }

View file

@ -35,8 +35,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "doomtype.h"
#include "oalsound.h" #include "oalsound.h"
#include "i_module.h" #include "i_module.h"
@ -52,6 +50,7 @@
#include "s_music.h" #include "s_music.h"
#include "zmusic/zmusic.h" #include "zmusic/zmusic.h"
EXTERN_CVAR (Float, snd_sfxvolume) EXTERN_CVAR (Float, snd_sfxvolume)
EXTERN_CVAR (Float, snd_musicvolume) EXTERN_CVAR (Float, snd_musicvolume)
CVAR (Int, snd_samplerate, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Int, snd_samplerate, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
@ -300,8 +299,8 @@ void I_InitSound ()
void I_CloseSound () void I_CloseSound ()
{ {
// Free all loaded samples // Free all loaded samples. Beware that the sound engine may already have been deleted.
S_UnloadAllSounds(); if (soundEngine) soundEngine->UnloadAllSounds();
delete GSnd; delete GSnd;
GSnd = NULL; GSnd = NULL;

View file

@ -174,11 +174,7 @@ extern bool nosfx;
extern bool nosound; extern bool nosound;
void I_InitSound (); void I_InitSound ();
void I_CloseSound();
void S_ChannelEnded(FISoundChannel *schan);
void S_ChannelVirtualChanged(FISoundChannel *schan, bool is_virtual);
float S_GetRolloff(FRolloffInfo *rolloff, float distance, bool logarithmic);
FISoundChannel *S_GetChannel(void *syschan);
extern ReverbContainer *DefaultEnvironments[26]; extern ReverbContainer *DefaultEnvironments[26];

View file

@ -122,4 +122,5 @@ class SoundStream;
#endif #endif

View file

@ -544,22 +544,7 @@ static size_t GetChannelCount(ChannelConfig chans)
static float GetRolloff(const FRolloffInfo *rolloff, float distance) static float GetRolloff(const FRolloffInfo *rolloff, float distance)
{ {
if(distance <= rolloff->MinDistance) return soundEngine->GetRolloff(rolloff, distance);
return 1.f;
// Logarithmic rolloff has no max distance where it goes silent.
if(rolloff->RolloffType == ROLLOFF_Log)
return rolloff->MinDistance /
(rolloff->MinDistance + rolloff->RolloffFactor*(distance-rolloff->MinDistance));
if(distance >= rolloff->MaxDistance)
return 0.f;
float volume = (rolloff->MaxDistance - distance) / (rolloff->MaxDistance - rolloff->MinDistance);
if(rolloff->RolloffType == ROLLOFF_Linear)
return volume;
if(rolloff->RolloffType == ROLLOFF_Custom && S_SoundCurve.Size() > 0)
return S_SoundCurve[int(S_SoundCurve.Size() * (1.f - volume))] / 127.f;
return (powf(10.f, volume) - 1.f) / 9.f;
} }
ALCdevice *OpenALSoundRenderer::InitDevice() ALCdevice *OpenALSoundRenderer::InitDevice()
@ -983,7 +968,7 @@ void OpenALSoundRenderer::SetSfxVolume(float volume)
{ {
SfxVolume = volume; SfxVolume = volume;
FSoundChan *schan = Channels; FSoundChan *schan = soundEngine->GetChannels();
while(schan) while(schan)
{ {
if(schan->SysChannel != NULL) if(schan->SysChannel != NULL)
@ -1359,7 +1344,7 @@ void OpenALSoundRenderer::UnloadSound(SoundHandle sfx)
return; return;
ALuint buffer = GET_PTRID(sfx.data); ALuint buffer = GET_PTRID(sfx.data);
FSoundChan *schan = Channels; FSoundChan *schan = soundEngine->GetChannels();
while(schan) while(schan)
{ {
if(schan->SysChannel) if(schan->SysChannel)
@ -1495,7 +1480,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
FreeSfx.Pop(); FreeSfx.Pop();
FISoundChannel *chan = reuse_chan; FISoundChannel *chan = reuse_chan;
if(!chan) chan = S_GetChannel(MAKE_PTRID(source)); if(!chan) chan = soundEngine->GetChannel(MAKE_PTRID(source));
else chan->SysChannel = MAKE_PTRID(source); else chan->SysChannel = MAKE_PTRID(source);
chan->Rolloff.RolloffType = ROLLOFF_Log; chan->Rolloff.RolloffType = ROLLOFF_Log;
@ -1706,7 +1691,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
FreeSfx.Pop(); FreeSfx.Pop();
FISoundChannel *chan = reuse_chan; FISoundChannel *chan = reuse_chan;
if(!chan) chan = S_GetChannel(MAKE_PTRID(source)); if(!chan) chan = soundEngine->GetChannel(MAKE_PTRID(source));
else chan->SysChannel = MAKE_PTRID(source); else chan->SysChannel = MAKE_PTRID(source);
chan->Rolloff = *rolloff; chan->Rolloff = *rolloff;
@ -1765,7 +1750,7 @@ void OpenALSoundRenderer::StopChannel(FISoundChannel *chan)
ALuint source = GET_PTRID(chan->SysChannel); ALuint source = GET_PTRID(chan->SysChannel);
// Release first, so it can be properly marked as evicted if it's being killed // Release first, so it can be properly marked as evicted if it's being killed
S_ChannelEnded(chan); soundEngine->ChannelEnded(chan);
ALint state = AL_INITIAL; ALint state = AL_INITIAL;
alGetSourcei(source, AL_SOURCE_STATE, &state); alGetSourcei(source, AL_SOURCE_STATE, &state);
@ -1789,7 +1774,7 @@ void OpenALSoundRenderer::ForceStopChannel(FISoundChannel *chan)
ALuint source = GET_PTRID(chan->SysChannel); ALuint source = GET_PTRID(chan->SysChannel);
if(!source) return; if(!source) return;
S_ChannelEnded(chan); soundEngine->ChannelEnded(chan);
FreeSource(source); FreeSource(source);
} }
@ -2009,7 +1994,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener)
alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f); alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f);
// Apply the updated filters on the sources // Apply the updated filters on the sources
FSoundChan *schan = Channels; FSoundChan *schan = soundEngine->GetChannels();
while (schan) while (schan)
{ {
ALuint source = GET_PTRID(schan->SysChannel); ALuint source = GET_PTRID(schan->SysChannel);
@ -2022,7 +2007,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener)
} }
} }
FSoundChan *schan = Channels; FSoundChan *schan = soundEngine->GetChannels();
while (schan) while (schan)
{ {
ALuint source = GET_PTRID(schan->SysChannel); ALuint source = GET_PTRID(schan->SysChannel);
@ -2047,7 +2032,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener)
alFilterf(EnvFilters[1], AL_LOWPASS_GAIN, 1.f); alFilterf(EnvFilters[1], AL_LOWPASS_GAIN, 1.f);
alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f); alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f);
FSoundChan *schan = Channels; FSoundChan *schan = soundEngine->GetChannels();
while (schan) while (schan)
{ {
ALuint source = GET_PTRID(schan->SysChannel); ALuint source = GET_PTRID(schan->SysChannel);
@ -2060,7 +2045,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener)
} }
} }
FSoundChan *schan = Channels; FSoundChan *schan = soundEngine->GetChannels();
while (schan) while (schan)
{ {
ALuint source = GET_PTRID(schan->SysChannel); ALuint source = GET_PTRID(schan->SysChannel);
@ -2236,7 +2221,7 @@ void OpenALSoundRenderer::PurgeStoppedSources()
if(state == AL_INITIAL || state == AL_PLAYING || state == AL_PAUSED) if(state == AL_INITIAL || state == AL_PLAYING || state == AL_PAUSED)
continue; continue;
FSoundChan *schan = Channels; FSoundChan *schan = soundEngine->GetChannels();
while(schan) while(schan)
{ {
if(schan->SysChannel != NULL && src == GET_PTRID(schan->SysChannel)) if(schan->SysChannel != NULL && src == GET_PTRID(schan->SysChannel))
@ -2358,7 +2343,7 @@ void OpenALSoundRenderer::LoadReverb(const ReverbContainer *env)
FSoundChan *OpenALSoundRenderer::FindLowestChannel() FSoundChan *OpenALSoundRenderer::FindLowestChannel()
{ {
FSoundChan *schan = Channels; FSoundChan *schan = soundEngine->GetChannels();
FSoundChan *lowest = NULL; FSoundChan *lowest = NULL;
while(schan) while(schan)
{ {

View file

@ -61,12 +61,6 @@
// TYPES ------------------------------------------------------------------- // TYPES -------------------------------------------------------------------
struct FRandomSoundList
{
TArray<uint32_t> Choices;
uint32_t Owner = 0;
};
struct FPlayerClassLookup struct FPlayerClassLookup
{ {
FString Name; FString Name;
@ -200,11 +194,9 @@ static int S_AddSound (const char *logicalname, int lumpnum, FScanner *sc=NULL);
// EXTERNAL DATA DECLARATIONS ---------------------------------------------- // EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern int sfx_empty;
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------
TArray<sfxinfo_t> S_sfx (128); //TArray<sfxinfo_t> S_sfx (128);
TMap<int, FString> HexenMusic; TMap<int, FString> HexenMusic;
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
@ -239,7 +231,6 @@ static const char *SICommandStrings[] =
NULL NULL
}; };
static TArray<FRandomSoundList> S_rnd;
static FMusicVolume *MusicVolumes; static FMusicVolume *MusicVolumes;
static TArray<FSavedPlayerSoundInfo> SavedPlayerSounds; static TArray<FSavedPlayerSoundInfo> SavedPlayerSounds;
@ -255,8 +246,6 @@ static int DefPlayerClass;
static uint8_t CurrentPitchMask; static uint8_t CurrentPitchMask;
static FRandom pr_randsound ("RandSound");
// CODE -------------------------------------------------------------------- // CODE --------------------------------------------------------------------
//========================================================================== //==========================================================================
@ -281,36 +270,6 @@ float S_GetMusicVolume (const char *music)
return 1.f; return 1.f;
} }
//==========================================================================
//
// S_HashSounds
//
// Fills in the next and index fields of S_sfx to form a working hash table.
//==========================================================================
void S_HashSounds ()
{
unsigned int i;
unsigned int j;
unsigned int size;
S_sfx.ShrinkToFit ();
size = S_sfx.Size ();
// Mark all buckets as empty
for (i = 0; i < size; i++)
S_sfx[i].index = 0;
// Now set up the chains
for (i = 1; i < size; i++)
{
j = MakeKey (S_sfx[i].name) % size;
S_sfx[i].next = S_sfx[j].index;
S_sfx[j].index = i;
}
}
//========================================================================== //==========================================================================
// //
// S_CheckIntegrity // S_CheckIntegrity
@ -320,6 +279,7 @@ void S_HashSounds ()
static bool S_CheckSound(sfxinfo_t *startsfx, sfxinfo_t *sfx, TArray<sfxinfo_t *> &chain) static bool S_CheckSound(sfxinfo_t *startsfx, sfxinfo_t *sfx, TArray<sfxinfo_t *> &chain)
{ {
auto &S_sfx = soundEngine->GetSounds();
sfxinfo_t *me = sfx; sfxinfo_t *me = sfx;
bool success = true; bool success = true;
unsigned siz = chain.Size(); unsigned siz = chain.Size();
@ -339,7 +299,7 @@ static bool S_CheckSound(sfxinfo_t *startsfx, sfxinfo_t *sfx, TArray<sfxinfo_t *
if (me->bRandomHeader) if (me->bRandomHeader)
{ {
const FRandomSoundList *list = &S_rnd[me->link]; const FRandomSoundList* list = soundEngine->ResolveRandomSound(me);
for (unsigned i = 0; i < list->Choices.Size(); ++i) for (unsigned i = 0; i < list->Choices.Size(); ++i)
{ {
auto rsfx = &S_sfx[list->Choices[i]]; auto rsfx = &S_sfx[list->Choices[i]];
@ -385,6 +345,7 @@ void S_CheckIntegrity()
TArray<sfxinfo_t *> chain; TArray<sfxinfo_t *> chain;
TArray<bool> broken; TArray<bool> broken;
auto &S_sfx = soundEngine->GetSounds();
broken.Resize(S_sfx.Size()); broken.Resize(S_sfx.Size());
memset(&broken[0], 0, sizeof(bool)*S_sfx.Size()); memset(&broken[0], 0, sizeof(bool)*S_sfx.Size());
for (unsigned i = 0; i < S_sfx.Size(); i++) for (unsigned i = 0; i < S_sfx.Size(); i++)
@ -404,34 +365,18 @@ void S_CheckIntegrity()
} }
} }
//==========================================================================
//
// S_PickReplacement
//
// Picks a replacement sound from the associated random list. If this sound
// is not the head of a random list, then the sound passed is returned.
//==========================================================================
int S_PickReplacement(int refid)
{
while (S_sfx[refid].bRandomHeader)
{
const FRandomSoundList *list = &S_rnd[S_sfx[refid].link];
refid = list->Choices[pr_randsound(list->Choices.Size())];
}
return refid;
}
//========================================================================== //==========================================================================
// //
// S_GetSoundMSLength // S_GetSoundMSLength
// //
// Returns duration of sound // Returns duration of sound
// This cannot be made a sound engine function due to the player sounds.
// //
//========================================================================== //==========================================================================
unsigned int S_GetMSLength(FSoundID sound) unsigned int S_GetMSLength(FSoundID sound)
{ {
auto &S_sfx = soundEngine->GetSounds();
if ((unsigned int)sound >= S_sfx.Size()) if ((unsigned int)sound >= S_sfx.Size())
{ {
return 0; return 0;
@ -453,7 +398,7 @@ unsigned int S_GetMSLength(FSoundID sound)
// I think the longest one makes more sense. // I think the longest one makes more sense.
int length = 0; int length = 0;
const FRandomSoundList *list = &S_rnd[sfx->link]; const FRandomSoundList* list = soundEngine->ResolveRandomSound(sfx);
for (auto &me : list->Choices) for (auto &me : list->Choices)
{ {
@ -469,7 +414,7 @@ unsigned int S_GetMSLength(FSoundID sound)
} }
} }
sfx = S_LoadSound(sfx); sfx = soundEngine->LoadSound(sfx, nullptr);
if (sfx != NULL) return GSnd->GetMSLength(sfx->data); if (sfx != NULL) return GSnd->GetMSLength(sfx->data);
else return 0; else return 0;
} }
@ -481,157 +426,6 @@ DEFINE_ACTION_FUNCTION(DObject,S_GetLength)
ACTION_RETURN_FLOAT(S_GetMSLength(sound_id)/1000.0); ACTION_RETURN_FLOAT(S_GetMSLength(sound_id)/1000.0);
} }
//==========================================================================
//
// S_CacheRandomSound
//
// Loads all sounds a random sound might play.
//
//==========================================================================
void S_CacheRandomSound (sfxinfo_t *sfx)
{
if (sfx->bRandomHeader)
{
const FRandomSoundList *list = &S_rnd[sfx->link];
for (unsigned i = 0; i < list->Choices.Size(); ++i)
{
sfx = &S_sfx[list->Choices[i]];
sfx->bUsed = true;
S_CacheSound (&S_sfx[list->Choices[i]]);
}
}
}
//==========================================================================
//
// S_FindSound
//
// Given a logical name, find the sound's index in S_sfx.
//==========================================================================
int S_FindSound (const char *logicalname)
{
int i;
if (logicalname != NULL)
{
i = S_sfx[MakeKey (logicalname) % S_sfx.Size ()].index;
while ((i != 0) && stricmp (S_sfx[i].name, logicalname))
i = S_sfx[i].next;
return i;
}
else
{
return 0;
}
}
//==========================================================================
//
// S_FindSoundNoHash
//
// Given a logical name, find the sound's index in S_sfx without
// using the hash table.
//==========================================================================
int S_FindSoundNoHash (const char *logicalname)
{
unsigned int i;
for (i = 1; i < S_sfx.Size (); i++)
{
if (stricmp (S_sfx[i].name, logicalname) == 0)
{
return i;
}
}
return 0;
}
//==========================================================================
//
// S_FindSoundByLump
//
// Given a sound lump, find the sound's index in S_sfx.
//==========================================================================
int S_FindSoundByLump (int lump)
{
if (lump != -1)
{
unsigned int i;
for (i = 1; i < S_sfx.Size (); i++)
if (S_sfx[i].lumpnum == lump)
return i;
}
return 0;
}
//==========================================================================
//
// S_AddSoundLump
//
// Adds a new sound mapping to S_sfx.
//==========================================================================
int S_AddSoundLump (const char *logicalname, int lump)
{
sfxinfo_t newsfx;
newsfx.data.Clear();
newsfx.data3d.Clear();
newsfx.name = logicalname;
newsfx.lumpnum = lump;
newsfx.next = 0;
newsfx.index = 0;
newsfx.Volume = 1;
newsfx.Attenuation = 1;
newsfx.PitchMask = CurrentPitchMask;
newsfx.NearLimit = 2;
newsfx.LimitRange = 256*256;
newsfx.bRandomHeader = false;
newsfx.bPlayerReserve = false;
newsfx.bLoadRAW = false;
newsfx.bPlayerCompat = false;
newsfx.b16bit = false;
newsfx.bUsed = false;
newsfx.bSingular = false;
newsfx.bTentative = false;
newsfx.bPlayerSilent = false;
newsfx.RawRate = 0;
newsfx.link = sfxinfo_t::NO_LINK;
newsfx.Rolloff.RolloffType = ROLLOFF_Doom;
newsfx.Rolloff.MinDistance = 0;
newsfx.Rolloff.MaxDistance = 0;
newsfx.LoopStart = -1;
return (int)S_sfx.Push (newsfx);
}
//==========================================================================
//
// S_FindSoundTentative
//
// Given a logical name, find the sound's index in S_sfx without
// using the hash table. If it does not exist, a new sound without
// an associated lump is created.
//==========================================================================
int S_FindSoundTentative (const char *name)
{
int id = S_FindSoundNoHash (name);
if (id == 0)
{
id = S_AddSoundLump (name, -1);
S_sfx[id].bTentative = true;
}
return id;
}
//========================================================================== //==========================================================================
// //
// S_AddSound // S_AddSound
@ -648,9 +442,10 @@ int S_AddSound (const char *logicalname, const char *lumpname, FScanner *sc)
static int S_AddSound (const char *logicalname, int lumpnum, FScanner *sc) static int S_AddSound (const char *logicalname, int lumpnum, FScanner *sc)
{ {
auto &S_sfx = soundEngine->GetSounds();
int sfxid; int sfxid;
sfxid = S_FindSoundNoHash (logicalname); sfxid = soundEngine->FindSoundNoHash (logicalname);
if (sfxid > 0) if (sfxid > 0)
{ // If the sound has already been defined, change the old definition { // If the sound has already been defined, change the old definition
@ -674,7 +469,7 @@ static int S_AddSound (const char *logicalname, int lumpnum, FScanner *sc)
} }
if (sfx->bRandomHeader) if (sfx->bRandomHeader)
{ {
FRandomSoundList *rnd = &S_rnd[sfx->link]; FRandomSoundList* rnd = soundEngine->ResolveRandomSound(sfx);
rnd->Choices.Reset(); rnd->Choices.Reset();
rnd->Owner = 0; rnd->Owner = 0;
} }
@ -691,7 +486,7 @@ static int S_AddSound (const char *logicalname, int lumpnum, FScanner *sc)
} }
else else
{ // Otherwise, create a new definition. { // Otherwise, create a new definition.
sfxid = S_AddSoundLump (logicalname, lumpnum); sfxid = soundEngine->AddSoundLump (logicalname, lumpnum, CurrentPitchMask);
} }
return sfxid; return sfxid;
@ -719,6 +514,7 @@ int S_AddPlayerSound (const char *pclass, int gender, int refid,
int S_AddPlayerSound (const char *pclass, int gender, int refid, int lumpnum, bool fromskin) int S_AddPlayerSound (const char *pclass, int gender, int refid, int lumpnum, bool fromskin)
{ {
auto &S_sfx = soundEngine->GetSounds();
FString fakename; FString fakename;
int id; int id;
@ -728,7 +524,7 @@ int S_AddPlayerSound (const char *pclass, int gender, int refid, int lumpnum, bo
fakename += '"'; fakename += '"';
fakename += S_sfx[refid].name; fakename += S_sfx[refid].name;
id = S_AddSoundLump (fakename, lumpnum); id = soundEngine->AddSoundLump (fakename, lumpnum, CurrentPitchMask);
int classnum = S_AddPlayerClass (pclass); int classnum = S_AddPlayerClass (pclass);
int soundlist = S_AddPlayerGender (classnum, gender); int soundlist = S_AddPlayerGender (classnum, gender);
@ -752,6 +548,7 @@ int S_AddPlayerSoundExisting (const char *pclass, int gender, int refid,
int classnum = S_AddPlayerClass (pclass); int classnum = S_AddPlayerClass (pclass);
int soundlist = S_AddPlayerGender (classnum, gender); int soundlist = S_AddPlayerGender (classnum, gender);
auto &S_sfx = soundEngine->GetSounds();
PlayerSounds[soundlist].AddSound (S_sfx[refid].link, aliasto); PlayerSounds[soundlist].AddSound (S_sfx[refid].link, aliasto);
if (fromskin) S_SavePlayerSound(pclass, gender, refid, aliasto, true); if (fromskin) S_SavePlayerSound(pclass, gender, refid, aliasto, true);
@ -928,7 +725,7 @@ void FPlayerSoundHashTable::MarkUsed()
{ {
for (Entry *probe = Buckets[i]; probe != NULL; probe = probe->Next) for (Entry *probe = Buckets[i]; probe != NULL; probe = probe->Next)
{ {
S_sfx[probe->SfxID].bUsed = true; soundEngine->MarkUsed(probe->SfxID);
} }
} }
} }
@ -944,8 +741,9 @@ void FPlayerSoundHashTable::MarkUsed()
void S_ClearSoundData() void S_ClearSoundData()
{ {
S_StopAllChannels(); soundEngine->StopAllChannels();
S_UnloadAllSounds(); soundEngine->UnloadAllSounds();
auto &S_sfx = soundEngine->GetSounds();
S_sfx.Clear(); S_sfx.Clear();
Ambients.Clear(); Ambients.Clear();
while (MusicVolumes != NULL) while (MusicVolumes != NULL)
@ -954,7 +752,7 @@ void S_ClearSoundData()
MusicVolumes = me->Next; MusicVolumes = me->Next;
M_Free(me); M_Free(me);
} }
S_rnd.Clear(); soundEngine->ClearRandoms();
NumPlayerReserves = 0; NumPlayerReserves = 0;
PlayerClassesIsSorted = false; PlayerClassesIsSorted = false;
@ -977,6 +775,7 @@ void S_ClearSoundData()
void S_ParseSndInfo (bool redefine) void S_ParseSndInfo (bool redefine)
{ {
auto &S_sfx = soundEngine->GetSounds();
int lump; int lump;
if (!redefine) SavedPlayerSounds.Clear(); // clear skin sounds only for initial parsing. if (!redefine) SavedPlayerSounds.Clear(); // clear skin sounds only for initial parsing.
@ -1005,13 +804,7 @@ void S_ParseSndInfo (bool redefine)
} }
} }
S_RestorePlayerSounds(); S_RestorePlayerSounds();
S_HashSounds (); soundEngine->HashSounds ();
S_sfx.ShrinkToFit ();
if (S_rnd.Size() > 0)
{
S_rnd.ShrinkToFit ();
}
S_ShrinkPlayerSoundLists (); S_ShrinkPlayerSoundLists ();
@ -1028,13 +821,7 @@ void S_ParseSndInfo (bool redefine)
void S_AddLocalSndInfo(int lump) void S_AddLocalSndInfo(int lump)
{ {
S_AddSNDINFO(lump); S_AddSNDINFO(lump);
S_HashSounds (); soundEngine->HashSounds ();
S_sfx.ShrinkToFit ();
if (S_rnd.Size() > 0)
{
S_rnd.ShrinkToFit ();
}
S_ShrinkPlayerSoundLists (); S_ShrinkPlayerSoundLists ();
S_CheckIntegrity(); S_CheckIntegrity();
@ -1050,6 +837,7 @@ void S_AddLocalSndInfo(int lump)
static void S_AddSNDINFO (int lump) static void S_AddSNDINFO (int lump)
{ {
auto &S_sfx = soundEngine->GetSounds();
bool skipToEndIf; bool skipToEndIf;
TArray<uint32_t> list; TArray<uint32_t> list;
@ -1087,7 +875,7 @@ static void S_AddSNDINFO (int lump)
ambient->sound = 0; ambient->sound = 0;
sc.MustGetString (); sc.MustGetString ();
ambient->sound = FSoundID(S_FindSoundTentative(sc.String)); ambient->sound = FSoundID(soundEngine->FindSoundTentative(sc.String));
ambient->attenuation = 0; ambient->attenuation = 0;
sc.MustGetString (); sc.MustGetString ();
@ -1205,7 +993,7 @@ static void S_AddSNDINFO (int lump)
int gender, refid, targid; int gender, refid, targid;
S_ParsePlayerSoundCommon (sc, pclass, gender, refid); S_ParsePlayerSoundCommon (sc, pclass, gender, refid);
targid = S_FindSoundNoHash (sc.String); targid = soundEngine->FindSoundNoHash (sc.String);
if (!S_sfx[targid].bPlayerReserve) if (!S_sfx[targid].bPlayerReserve)
{ {
sc.ScriptError ("%s is not a player sound", sc.String); sc.ScriptError ("%s is not a player sound", sc.String);
@ -1235,7 +1023,7 @@ static void S_AddSNDINFO (int lump)
int soundnum; int soundnum;
S_ParsePlayerSoundCommon (sc, pclass, gender, refid); S_ParsePlayerSoundCommon (sc, pclass, gender, refid);
soundnum = S_FindSoundTentative (sc.String); soundnum = soundEngine->FindSoundTentative (sc.String);
S_AddPlayerSoundExisting (pclass, gender, refid, soundnum); S_AddPlayerSoundExisting (pclass, gender, refid, soundnum);
} }
break; break;
@ -1251,7 +1039,7 @@ static void S_AddSNDINFO (int lump)
{ {
sfxfrom = S_sfx[sfxfrom].link; sfxfrom = S_sfx[sfxfrom].link;
} }
S_sfx[sfxfrom].link = S_FindSoundTentative (sc.String); S_sfx[sfxfrom].link = soundEngine->FindSoundTentative (sc.String);
S_sfx[sfxfrom].NearLimit = -1; // Aliases must use the original sound's limit. S_sfx[sfxfrom].NearLimit = -1; // Aliases must use the original sound's limit.
} }
break; break;
@ -1261,7 +1049,7 @@ static void S_AddSNDINFO (int lump)
int sfx; int sfx;
sc.MustGetString (); sc.MustGetString ();
sfx = S_FindSoundTentative (sc.String); sfx = soundEngine->FindSoundTentative (sc.String);
sc.MustGetNumber (); sc.MustGetNumber ();
S_sfx[sfx].NearLimit = MIN(MAX(sc.Number, 0), 255); S_sfx[sfx].NearLimit = MIN(MAX(sc.Number, 0), 255);
if (sc.CheckFloat()) if (sc.CheckFloat())
@ -1276,7 +1064,7 @@ static void S_AddSNDINFO (int lump)
int sfx; int sfx;
sc.MustGetString (); sc.MustGetString ();
sfx = S_FindSoundTentative (sc.String); sfx = soundEngine->FindSoundTentative (sc.String);
S_sfx[sfx].bSingular = true; S_sfx[sfx].bSingular = true;
} }
break; break;
@ -1286,7 +1074,7 @@ static void S_AddSNDINFO (int lump)
int sfx; int sfx;
sc.MustGetString (); sc.MustGetString ();
sfx = S_FindSoundTentative (sc.String); sfx = soundEngine->FindSoundTentative (sc.String);
sc.MustGetNumber (); sc.MustGetNumber ();
S_sfx[sfx].PitchMask = (1 << clamp (sc.Number, 0, 7)) - 1; S_sfx[sfx].PitchMask = (1 << clamp (sc.Number, 0, 7)) - 1;
} }
@ -1303,7 +1091,7 @@ static void S_AddSNDINFO (int lump)
int sfx; int sfx;
sc.MustGetString(); sc.MustGetString();
sfx = S_FindSoundTentative(sc.String); sfx = soundEngine->FindSoundTentative(sc.String);
sc.MustGetFloat(); sc.MustGetFloat();
S_sfx[sfx].Volume = (float)sc.Float; S_sfx[sfx].Volume = (float)sc.Float;
} }
@ -1314,7 +1102,7 @@ static void S_AddSNDINFO (int lump)
int sfx; int sfx;
sc.MustGetString(); sc.MustGetString();
sfx = S_FindSoundTentative(sc.String); sfx = soundEngine->FindSoundTentative(sc.String);
sc.MustGetFloat(); sc.MustGetFloat();
S_sfx[sfx].Attenuation = (float)sc.Float; S_sfx[sfx].Attenuation = (float)sc.Float;
} }
@ -1331,11 +1119,11 @@ static void S_AddSNDINFO (int lump)
if (sc.Compare("*")) if (sc.Compare("*"))
{ {
sfx = -1; sfx = -1;
rolloff = &S_Rolloff; rolloff = &soundEngine->GlobalRolloff();
} }
else else
{ {
sfx = S_FindSoundTentative(sc.String); sfx = soundEngine->FindSoundTentative(sc.String);
rolloff = &S_sfx[sfx].Rolloff; rolloff = &S_sfx[sfx].Rolloff;
} }
type = ROLLOFF_Doom; type = ROLLOFF_Doom;
@ -1376,7 +1164,7 @@ static void S_AddSNDINFO (int lump)
sc.MustGetStringName ("{"); sc.MustGetStringName ("{");
while (sc.GetString () && !sc.Compare ("}")) while (sc.GetString () && !sc.Compare ("}"))
{ {
uint32_t sfxto = S_FindSoundTentative (sc.String); uint32_t sfxto = soundEngine->FindSoundTentative (sc.String);
if (sfxto == random.Owner) if (sfxto == random.Owner)
{ {
Printf("Definition of random sound '%s' refers to itself recursively.\n", sc.String); Printf("Definition of random sound '%s' refers to itself recursively.\n", sc.String);
@ -1391,13 +1179,7 @@ static void S_AddSNDINFO (int lump)
} }
else if (list.Size() > 1) else if (list.Size() > 1)
{ // Only add non-empty random lists { // Only add non-empty random lists
auto index = S_rnd.Reserve(1); soundEngine->AddRandomSound(Owner, list);
auto &random = S_rnd.Last();
random.Choices = std::move(list);
random.Owner = Owner;
S_sfx[Owner].link = index;
S_sfx[Owner].bRandomHeader = true;
S_sfx[Owner].NearLimit = -1;
} }
} }
break; break;
@ -1513,6 +1295,7 @@ static void S_AddBloodSFX (int lumpnum)
if (rawlump != -1) if (rawlump != -1)
{ {
auto &S_sfx = soundEngine->GetSounds();
const char *name = Wads.GetLumpFullName(lumpnum); const char *name = Wads.GetLumpFullName(lumpnum);
sfxnum = S_AddSound(name, rawlump); sfxnum = S_AddSound(name, rawlump);
if (sfx->Format < 5 || sfx->Format > 12) if (sfx->Format < 5 || sfx->Format > 12)
@ -1572,7 +1355,8 @@ static void S_ParsePlayerSoundCommon (FScanner &sc, FString &pclass, int &gender
sc.MustGetString (); sc.MustGetString ();
gender = D_GenderToInt (sc.String); gender = D_GenderToInt (sc.String);
sc.MustGetString (); sc.MustGetString ();
refid = S_FindSoundNoHash (sc.String); refid = soundEngine->FindSoundNoHash (sc.String);
auto &S_sfx = soundEngine->GetSounds();
if (refid != 0 && !S_sfx[refid].bPlayerReserve && !S_sfx[refid].bTentative) if (refid != 0 && !S_sfx[refid].bPlayerReserve && !S_sfx[refid].bTentative)
{ {
sc.ScriptError ("%s has already been used for a non-player sound.", sc.String); sc.ScriptError ("%s has already been used for a non-player sound.", sc.String);
@ -1734,6 +1518,7 @@ int S_LookupPlayerSound (const char *pclass, int gender, const char *name)
int S_LookupPlayerSound (const char *pclass, int gender, FSoundID refid) int S_LookupPlayerSound (const char *pclass, int gender, FSoundID refid)
{ {
auto &S_sfx = soundEngine->GetSounds();
if (!S_sfx[refid].bPlayerReserve) if (!S_sfx[refid].bPlayerReserve)
{ // Not a player sound, so just return this sound { // Not a player sound, so just return this sound
return refid; return refid;
@ -1744,6 +1529,7 @@ int S_LookupPlayerSound (const char *pclass, int gender, FSoundID refid)
static int S_LookupPlayerSound (int classidx, int gender, FSoundID refid) static int S_LookupPlayerSound (int classidx, int gender, FSoundID refid)
{ {
auto &S_sfx = soundEngine->GetSounds();
int ingender = gender; int ingender = gender;
if (classidx == -1) if (classidx == -1)
@ -1847,6 +1633,7 @@ bool S_AreSoundsEquivalent (AActor *actor, int id1, int id2)
{ {
sfxinfo_t *sfx; sfxinfo_t *sfx;
auto &S_sfx = soundEngine->GetSounds();
if (id1 == id2) if (id1 == id2)
{ {
return true; return true;
@ -1998,52 +1785,6 @@ void S_MarkPlayerSounds (AActor *player)
} }
} }
//==========================================================================
//
// CCMD soundlist
//
//==========================================================================
CCMD (soundlist)
{
char lumpname[9];
unsigned int i;
lumpname[8] = 0;
for (i = 0; i < S_sfx.Size (); i++)
{
const sfxinfo_t *sfx = &S_sfx[i];
if (sfx->bRandomHeader)
{
Printf ("%3d. %s -> #%d {", i, sfx->name.GetChars(), sfx->link);
const FRandomSoundList *list = &S_rnd[sfx->link];
for (auto &me : list->Choices)
{
Printf (" %s ", S_sfx[me].name.GetChars());
}
Printf ("}\n");
}
else if (sfx->bPlayerReserve)
{
Printf ("%3d. %s <<player sound %d>>\n", i, sfx->name.GetChars(), sfx->link);
}
else if (S_sfx[i].lumpnum != -1)
{
Wads.GetLumpName (lumpname, sfx->lumpnum);
Printf ("%3d. %s (%s)\n", i, sfx->name.GetChars(), lumpname);
}
else if (S_sfx[i].link != sfxinfo_t::NO_LINK)
{
Printf ("%3d. %s -> %s\n", i, sfx->name.GetChars(), S_sfx[sfx->link].name.GetChars());
}
else
{
Printf ("%3d. %s **not present**\n", i, sfx->name.GetChars());
}
Printf(" PitchMask = %d\n", sfx->PitchMask);
}
}
//========================================================================== //==========================================================================
// //
// CCMD soundlinks // CCMD soundlinks
@ -2052,6 +1793,7 @@ CCMD (soundlist)
CCMD (soundlinks) CCMD (soundlinks)
{ {
auto &S_sfx = soundEngine->GetSounds();
unsigned int i; unsigned int i;
for (i = 0; i < S_sfx.Size (); i++) for (i = 0; i < S_sfx.Size (); i++)
@ -2075,6 +1817,7 @@ CCMD (soundlinks)
CCMD (playersounds) CCMD (playersounds)
{ {
auto &S_sfx = soundEngine->GetSounds();
const char *reserveNames[256]; const char *reserveNames[256];
unsigned int i; unsigned int i;
int j, k, l; int j, k, l;
@ -2119,7 +1862,7 @@ DEFINE_ACTION_FUNCTION(AAmbientSound, MarkAmbientSounds)
FAmbientSound *ambient = Ambients.CheckKey(self->args[0]); FAmbientSound *ambient = Ambients.CheckKey(self->args[0]);
if (ambient != NULL) if (ambient != NULL)
{ {
ambient->sound.MarkUsed(); soundEngine->MarkUsed(ambient->sound);
} }
return 0; return 0;
} }
@ -2251,13 +1994,12 @@ DEFINE_ACTION_FUNCTION(AAmbientSound, Activate)
{ {
if ((amb->type & 3) == 0 && amb->periodmin == 0) if ((amb->type & 3) == 0 && amb->periodmin == 0)
{ {
int sndnum = S_FindSound(amb->sound); if (amb->sound == 0)
if (sndnum == 0)
{ {
self->Destroy (); self->Destroy ();
return 0; return 0;
} }
amb->periodmin = ::Scale(S_GetMSLength(sndnum), TICRATE, 1000); amb->periodmin = ::Scale(S_GetMSLength(amb->sound), TICRATE, 1000);
} }
self->special1 = 0; self->special1 = 0;
@ -2343,7 +2085,7 @@ DEFINE_ACTION_FUNCTION(DObject, MarkSound)
{ {
PARAM_PROLOGUE; PARAM_PROLOGUE;
PARAM_SOUND(sound_id); PARAM_SOUND(sound_id);
sound_id.MarkUsed(); soundEngine->MarkUsed(sound_id);
return 0; return 0;
} }

File diff suppressed because it is too large Load diff

View file

@ -3,8 +3,22 @@
// Information about one playing sound. // Information about one playing sound.
struct sector_t; struct sector_t;
struct FPolyObj; struct FPolyObj;
struct FLevelLocals;
void S_Init();
void S_InitData();
void S_Start();
void S_Shutdown();
void S_UpdateSounds(AActor* listenactor); void S_UpdateSounds(AActor* listenactor);
void S_SetSoundPaused(int state);
void S_PrecacheLevel(FLevelLocals* l);
// Start sound for thing at <ent>
void S_Sound(int channel, FSoundID sfxid, float volume, float attenuation);
void S_SoundPitch(int channel, FSoundID sfxid, float volume, float attenuation, float pitch);
void S_Sound (AActor *ent, int channel, FSoundID sfxid, float volume, float attenuation); void S_Sound (AActor *ent, int channel, FSoundID sfxid, float volume, float attenuation);
void S_SoundMinMaxDist (AActor *ent, int channel, FSoundID sfxid, float volume, float mindist, float maxdist); void S_SoundMinMaxDist (AActor *ent, int channel, FSoundID sfxid, float volume, float mindist, float maxdist);
@ -45,3 +59,31 @@ void S_SerializeSounds(FSerializer &arc);
void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch); void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch);
static void S_SetListener(AActor *listenactor); static void S_SetListener(AActor *listenactor);
void S_SoundReset(); void S_SoundReset();
void S_ResumeSound(bool state);
void S_PauseSound(bool state1, bool state);
void S_NoiseDebug();
inline void S_StopSound(int chan)
{
soundEngine->StopSound(chan);
}
inline void S_StopAllChannels()
{
soundEngine->StopAllChannels();
}
inline const char* S_GetSoundName(FSoundID id)
{
return soundEngine->GetSoundName(id);
}
inline int S_FindSound(const char* logicalname)
{
return soundEngine->FindSound(logicalname);
}
inline int S_FindSoundByResID(int rid)
{
return soundEngine->FindSoundByResID(rid);
}

View file

@ -1433,13 +1433,13 @@ void SN_MarkPrecacheSounds(int sequence, seqtype_t type)
{ {
FSoundSequence *seq = Sequences[sequence]; FSoundSequence *seq = Sequences[sequence];
seq->StopSound.MarkUsed(); soundEngine->MarkUsed(seq->StopSound);
for (int i = 0; GetCommand(seq->Script[i]) != SS_CMD_END; ++i) for (int i = 0; GetCommand(seq->Script[i]) != SS_CMD_END; ++i)
{ {
int cmd = GetCommand(seq->Script[i]); int cmd = GetCommand(seq->Script[i]);
if (cmd == SS_CMD_PLAY || cmd == SS_CMD_PLAYREPEAT || cmd == SS_CMD_PLAYLOOP) if (cmd == SS_CMD_PLAY || cmd == SS_CMD_PLAYREPEAT || cmd == SS_CMD_PLAYLOOP)
{ {
FSoundID(GetData(seq->Script[i])).MarkUsed(); soundEngine->MarkUsed(GetData(seq->Script[i]));
} }
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -28,7 +28,6 @@
#ifndef __S_SOUND__ #ifndef __S_SOUND__
#define __S_SOUND__ #define __S_SOUND__
#include "doomtype.h"
#include "i_soundinternal.h" #include "i_soundinternal.h"
class AActor; class AActor;
@ -37,58 +36,36 @@ class FSerializer;
struct FLevelLocals; struct FLevelLocals;
#include "s_soundinternal.h" #include "s_soundinternal.h"
#include "s_doomsound.h"
// Per level startup code. // Per level startup code.
// Kills playing sounds at start of level and starts new music. // Kills playing sounds at start of level and starts new music.
// //
void S_Start ();
// Called after a level is loaded. Ensures that most sounds are loaded. // Called after a level is loaded. Ensures that most sounds are loaded.
void S_PrecacheLevel (FLevelLocals *l);
// Start sound for thing at <ent>
void S_Sound (int channel, FSoundID sfxid, float volume, float attenuation);
void S_SoundPitch (int channel, FSoundID sfxid, float volume, float attenuation, float pitch);
struct FSoundLoadBuffer; struct FSoundLoadBuffer;
int S_PickReplacement (int refid);
void S_CacheRandomSound (sfxinfo_t *sfx);
// Stop sound for all channels
void S_StopAllChannels (void);
void S_SetPitch(FSoundChan *chan, float dpitch);
void S_RestoreEvictedChannels();
// [RH] S_sfx "maintenance" routines // [RH] S_sfx "maintenance" routines
void S_ClearSoundData(); void S_ClearSoundData();
void S_ParseSndInfo (bool redefine); void S_ParseSndInfo (bool redefine);
void S_HashSounds ();
int S_FindSoundNoHash (const char *logicalname);
bool S_AreSoundsEquivalent (AActor *actor, int id1, int id2); bool S_AreSoundsEquivalent (AActor *actor, int id1, int id2);
bool S_AreSoundsEquivalent (AActor *actor, const char *name1, const char *name2); bool S_AreSoundsEquivalent (AActor *actor, const char *name1, const char *name2);
int S_LookupPlayerSound (const char *playerclass, int gender, const char *logicalname); int S_LookupPlayerSound (const char *playerclass, int gender, const char *logicalname);
int S_LookupPlayerSound (const char *playerclass, int gender, FSoundID refid); int S_LookupPlayerSound (const char *playerclass, int gender, FSoundID refid);
int S_FindSkinnedSound (AActor *actor, FSoundID refid); int S_FindSkinnedSound (AActor *actor, FSoundID refid);
int S_FindSkinnedSoundEx (AActor *actor, const char *logicalname, const char *extendedname); int S_FindSkinnedSoundEx (AActor *actor, const char *logicalname, const char *extendedname);
int S_FindSoundByLump (int lump);
int S_AddSound (const char *logicalname, const char *lumpname, FScanner *sc=NULL); // Add sound by lumpname int S_AddSound (const char *logicalname, const char *lumpname, FScanner *sc=NULL); // Add sound by lumpname
int S_AddSoundLump (const char *logicalname, int lump); // Add sound by lump index
int S_AddPlayerSound (const char *playerclass, const int gender, int refid, const char *lumpname); int S_AddPlayerSound (const char *playerclass, const int gender, int refid, const char *lumpname);
int S_AddPlayerSound (const char *playerclass, const int gender, int refid, int lumpnum, bool fromskin=false); int S_AddPlayerSound (const char *playerclass, const int gender, int refid, int lumpnum, bool fromskin=false);
int S_AddPlayerSoundExisting (const char *playerclass, const int gender, int refid, int aliasto, bool fromskin=false); int S_AddPlayerSoundExisting (const char *playerclass, const int gender, int refid, int aliasto, bool fromskin=false);
void S_MarkPlayerSounds (AActor *player); void S_MarkPlayerSounds (AActor *player);
void S_ShrinkPlayerSoundLists (); void S_ShrinkPlayerSoundLists ();
void S_UnloadSound (sfxinfo_t *sfx);
sfxinfo_t *S_LoadSound(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer = nullptr);
unsigned int S_GetMSLength(FSoundID sound); unsigned int S_GetMSLength(FSoundID sound);
// [RH] Prints sound debug info to the screen. // [RH] Prints sound debug info to the screen.
// Modelled after Hexen's noise cheat. // Modelled after Hexen's noise cheat.
void S_NoiseDebug ();
#include "s_doomsound.h"
#endif #endif

View file

@ -1,7 +1,14 @@
#pragma once #pragma once
#include "i_soundinternal.h" #include "i_sound.h"
struct FRandomSoundList
{
TArray<uint32_t> Choices;
uint32_t Owner = 0;
};
extern int sfx_empty;
// //
// SoundFX struct. // SoundFX struct.
@ -21,19 +28,20 @@ struct sfxinfo_t
unsigned int next, index; // [RH] For hashing unsigned int next, index; // [RH] For hashing
float Volume; float Volume;
uint8_t ResourceId; // Resource ID as implemented by Blood. Not used by Doom but added for completeness. int ResourceId; // Resource ID as implemented by Blood. Not used by Doom but added for completeness.
uint8_t PitchMask; uint8_t PitchMask;
int16_t NearLimit; // 0 means unlimited int16_t NearLimit; // 0 means unlimited
float LimitRange; // Range for sound limiting (squared for faster computations) float LimitRange; // Range for sound limiting (squared for faster computations)
unsigned bRandomHeader:1; unsigned bRandomHeader:1;
unsigned bPlayerReserve:1;
unsigned bLoadRAW:1; unsigned bLoadRAW:1;
unsigned bPlayerCompat:1;
unsigned b16bit:1; unsigned b16bit:1;
unsigned bUsed:1; unsigned bUsed:1;
unsigned bSingular:1; unsigned bSingular:1;
unsigned bTentative:1; unsigned bTentative:1;
unsigned bPlayerReserve : 1;
unsigned bPlayerCompat : 1;
unsigned bPlayerSilent:1; // This player sound is intentionally silent. unsigned bPlayerSilent:1; // This player sound is intentionally silent.
int RawRate; // Sample rate to use when bLoadRAW is true int RawRate; // Sample rate to use when bLoadRAW is true
@ -61,9 +69,6 @@ enum
int S_FindSound(const char *logicalname); int S_FindSound(const char *logicalname);
int S_FindSoundByResID(int snd_id); int S_FindSoundByResID(int snd_id);
// the complete set of sound effects
extern TArray<sfxinfo_t> S_sfx;
// An index into the S_sfx[] array. // An index into the S_sfx[] array.
class FSoundID class FSoundID
{ {
@ -110,18 +115,6 @@ public:
{ {
return ID; return ID;
} }
operator FString() const
{
return ID ? S_sfx[ID].name : "";
}
operator const char *() const
{
return ID ? S_sfx[ID].name.GetChars() : NULL;
}
void MarkUsed() const
{
S_sfx[ID].MarkUsed();
}
private: private:
int ID; int ID;
protected: protected:
@ -136,13 +129,8 @@ public:
using FSoundID::operator=; using FSoundID::operator=;
}; };
extern FRolloffInfo S_Rolloff;
extern TArray<uint8_t> S_SoundCurve;
class AActor;
struct sector_t;
struct FPolyObj;
struct FSoundChan : public FISoundChannel struct FSoundChan : public FISoundChannel
{ {
FSoundChan *NextChan; // Next channel in this list. FSoundChan *NextChan; // Next channel in this list.
@ -163,25 +151,6 @@ struct FSoundChan : public FISoundChannel
}; };
}; };
extern FSoundChan *Channels;
void S_ReturnChannel(FSoundChan *chan);
void S_EvictAllChannels();
void S_StopChannel(FSoundChan *chan);
void S_LinkChannel(FSoundChan *chan, FSoundChan **head);
void S_UnlinkChannel(FSoundChan *chan);
// Initializes sound stuff, including volume
// Sets channels, SFX and music volume,
// allocates channel buffer, sets S_sfx lookup.
//
void S_Init ();
void S_InitData ();
void S_Shutdown ();
// Loads a sound, including any random sounds it might reference.
void S_CacheSound (sfxinfo_t *sfx);
// sound channels // sound channels
// channel 0 never willingly overrides // channel 0 never willingly overrides
@ -237,9 +206,6 @@ enum
#define ATTN_IDLE 1.001f #define ATTN_IDLE 1.001f
#define ATTN_STATIC 3.f // diminish very rapidly with distance #define ATTN_STATIC 3.f // diminish very rapidly with distance
// Checks if a copy of this sound is already playing.
bool S_CheckSingular (int sound_id);
enum // This cannot be remain as this, but for now it has to suffice. enum // This cannot be remain as this, but for now it has to suffice.
{ {
SOURCE_None, // Sound is always on top of the listener. SOURCE_None, // Sound is always on top of the listener.
@ -250,31 +216,6 @@ enum // This cannot be remain as this, but for now it has to suffice.
}; };
//
// Updates music & sounds
//
void S_UpdateSounds (int time);
FSoundChan* S_StartSound(int sourcetype, const void* source,
const FVector3* pt, int channel, FSoundID sound_id, float volume, float attenuation, FRolloffInfo* rolloff = nullptr, float spitch = 0.0f);
// Stops an origin-less sound from playing from this channel.
void S_StopSound(int channel);
void S_StopSound(int sourcetype, const void* actor, int channel);
void S_RelinkSound(int sourcetype, const void* from, const void* to, const FVector3* optpos);
void S_ChangeSoundVolume(int sourcetype, const void *source, int channel, double dvolume);
void S_ChangeSoundPitch(int sourcetype, const void *source, int channel, double pitch);
bool S_IsSourcePlayingSomething (int sourcetype, const void *actor, int channel, int sound_id);
// Stop and resume music, during game PAUSE.
void S_PauseSound (bool notmusic, bool notsfx);
void S_ResumeSound (bool notsfx);
void S_SetSoundPaused (int state);
bool S_GetSoundPlayingInfo(int sourcetype, const void* source, int sound_id);
void S_UnloadAllSounds();
void S_Reset();
extern ReverbContainer *Environments; extern ReverbContainer *Environments;
extern ReverbContainer *DefaultEnvironments[26]; extern ReverbContainer *DefaultEnvironments[26];
@ -285,3 +226,163 @@ ReverbContainer *S_FindEnvironment (const char *name);
ReverbContainer *S_FindEnvironment (int id); ReverbContainer *S_FindEnvironment (int id);
void S_AddEnvironment (ReverbContainer *settings); void S_AddEnvironment (ReverbContainer *settings);
class SoundEngine
{
protected:
bool SoundPaused = false; // whether sound is paused
int RestartEvictionsAt = 0; // do not restart evicted channels before this time
SoundListener listener{};
FSoundChan* Channels = nullptr;
FSoundChan* FreeChannels = nullptr;
// the complete set of sound effects
TArray<sfxinfo_t> S_sfx;
FRolloffInfo S_Rolloff;
TArray<uint8_t> S_SoundCurve;
TMap<int, int> ResIdMap;
TArray<FRandomSoundList> S_rnd;
private:
void LoadSound3D(sfxinfo_t* sfx, FSoundLoadBuffer* pBuffer);
void LinkChannel(FSoundChan* chan, FSoundChan** head);
void UnlinkChannel(FSoundChan* chan);
void ReturnChannel(FSoundChan* chan);
void RestartChannel(FSoundChan* chan);
void RestoreEvictedChannel(FSoundChan* chan);
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, FVector3* pos, FVector3* vel) = 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; }
bool ValidatePosVel(const FSoundChan* const chan, const FVector3& pos, const FVector3& vel);
// Checks if a copy of this sound is already playing.
bool CheckSingular(int sound_id);
bool CheckSoundLimit(sfxinfo_t* sfx, const FVector3& pos, int near_limit, float limit_range, int sourcetype, const void* actor, int channel);
virtual TArray<uint8_t> ReadSound(int lumpnum) = 0;
public:
virtual ~SoundEngine() = default;
void EvictAllChannels();
void StopChannel(FSoundChan* chan);
sfxinfo_t* LoadSound(sfxinfo_t* sfx, FSoundLoadBuffer* pBuffer);
// Initializes sound stuff, including volume
// Sets channels, SFX and music volume,
// allocates channel buffer, sets S_sfx lookup.
//
void Init(TArray<uint8_t> &sndcurve);
void InitData();
void Shutdown();
void StopAllChannels(void);
void SetPitch(FSoundChan* chan, float dpitch);
FSoundChan* GetChannel(void* syschan);
void RestoreEvictedChannels();
void CalcPosVel(FSoundChan* chan, FVector3* pos, FVector3* vel);
// Loads a sound, including any random sounds it might reference.
void CacheSound(sfxinfo_t* sfx);
void CacheSound(int sfx) { CacheSound(&S_sfx[sfx]); }
void UnloadSound(sfxinfo_t* sfx);
void UpdateSounds(int time);
FSoundChan* StartSound(int sourcetype, const void* source,
const FVector3* pt, int channel, FSoundID sound_id, float volume, float attenuation, FRolloffInfo* rolloff = nullptr, float spitch = 0.0f);
// Stops an origin-less sound from playing from this channel.
void StopSound(int channel);
void StopSound(int sourcetype, const void* actor, int channel);
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);
bool IsSourcePlayingSomething(int sourcetype, const void* actor, int channel, int sound_id);
// Stop and resume music, during game PAUSE.
bool GetSoundPlayingInfo(int sourcetype, const void* source, int sound_id);
void UnloadAllSounds();
void Reset();
void MarkUsed(int num);
void CacheMarkedSounds();
TArray<FSoundChan*> AllActiveChannels();
void MarkAllUnused()
{
for (auto & s: S_sfx) s.bUsed = false;
}
bool isListener(const void* object) const
{
return object && listener.ListenerObject == object;
}
bool isPlayerReserve(int snd_id)
{
return S_sfx[snd_id].bPlayerReserve; // Later this needs to be abstracted out of the engine itself. Right now that cannot be done.
}
void SetListener(SoundListener& l)
{
listener = l;
}
void SetRestartTime(int time)
{
RestartEvictionsAt = time;
}
void SetPaused(bool on)
{
SoundPaused = on;
}
FSoundChan* GetChannels()
{
return Channels;
}
const char *GetSoundName(FSoundID id)
{
return id == 0 ? "" : S_sfx[id].name;
}
TArray<sfxinfo_t> &GetSounds() //Thio should only be used for constructing the sound list or for diagnostics code prinring information about the sound list.
{
return S_sfx;
}
FRolloffInfo& GlobalRolloff() // like GetSounds this is meant for sound list generators, not for gaining cheap access to the sound engine's innards.
{
return S_Rolloff;
}
FRandomSoundList *ResolveRandomSound(sfxinfo_t* sfx)
{
return &S_rnd[sfx->link];
}
void ClearRandoms()
{
S_rnd.Clear();
}
void ChannelVirtualChanged(FISoundChannel* ichan, bool is_virtual);
FString ListSoundChannels();
// Allow this to be overridden for special needs.
virtual float GetRolloff(const FRolloffInfo* rolloff, float distance);
virtual void ChannelEnded(FISoundChannel* ichan); // allows the client to do bookkeeping on the sound.
// Lookup utilities.
int FindSound(const char* logicalname);
int FindSoundByResID(int rid);
int FindSoundNoHash(const char* logicalname);
int FindSoundByLump(int lump);
int AddSoundLump(const char* logicalname, int lump, int CurrentPitchMask, int resid = -1);
int FindSoundTentative(const char* name);
void CacheRandomSound(sfxinfo_t* sfx);
unsigned int GetMSLength(FSoundID sound);
int PickReplacement(int refid);
void HashSounds();
void AddRandomSound(int Owner, TArray<uint32_t> list);
};
extern SoundEngine* soundEngine;

View file

@ -0,0 +1,5 @@
#pragma once
extern unsigned int MakeKey (const char *s);
extern unsigned int MakeKey (const char *s, size_t len);
extern unsigned int SuperFastHash (const char *data, size_t len);

View file

@ -436,6 +436,8 @@ class Actor : Thinker native
MarkSound(BounceSound); MarkSound(BounceSound);
MarkSound(WallBounceSound); MarkSound(WallBounceSound);
MarkSound(CrushPainSound); MarkSound(CrushPainSound);
MarkSound(HowlSound);
MarkSound(MeleeSound);
} }
bool IsPointerEqual(int ptr_select1, int ptr_select2) bool IsPointerEqual(int ptr_select1, int ptr_select2)