mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-11-13 07:58:04 +00:00
- added serialization of playing sounds.
For ambient sounds that can be cleanly restarted a new 'transient' flag was added so that these do not get written out. Tested on SW so far, other games yet to do.
This commit is contained in:
parent
da6c7ddab5
commit
69e018d0c4
6 changed files with 141 additions and 10 deletions
|
@ -50,6 +50,7 @@
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "z_music.h"
|
#include "z_music.h"
|
||||||
|
#include "s_soundinternal.h"
|
||||||
|
|
||||||
static CompositeSavegameWriter savewriter;
|
static CompositeSavegameWriter savewriter;
|
||||||
static FResourceFile *savereader;
|
static FResourceFile *savereader;
|
||||||
|
@ -70,6 +71,7 @@ static void SerializeSession(FSerializer& arc)
|
||||||
SECRET_Serialize(arc);
|
SECRET_Serialize(arc);
|
||||||
Mus_Serialize(arc);
|
Mus_Serialize(arc);
|
||||||
quoteMgr.Serialize(arc);
|
quoteMgr.Serialize(arc);
|
||||||
|
S_SerializeSounds(arc);
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
|
@ -44,6 +44,8 @@
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "gamecontrol.h"
|
#include "gamecontrol.h"
|
||||||
|
#include "serializer.h"
|
||||||
|
#include "build.h"
|
||||||
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -280,7 +282,7 @@ TArray<FSoundChan*> SoundEngine::AllActiveChannels()
|
||||||
// If the sound is forgettable, this is as good a time as
|
// If the sound is forgettable, this is as good a time as
|
||||||
// any to forget about it. And if it's a UI sound, it shouldn't
|
// any to forget about it. And if it's a UI sound, it shouldn't
|
||||||
// be stored in the savegame.
|
// be stored in the savegame.
|
||||||
if (!(chan->ChanFlags & (CHANF_FORGETTABLE | CHANF_UI)))
|
if (!(chan->ChanFlags & (CHANF_FORGETTABLE | CHANF_UI | CHANF_TRANSIENT)))
|
||||||
{
|
{
|
||||||
chans.Push(chan);
|
chans.Push(chan);
|
||||||
}
|
}
|
||||||
|
@ -1764,3 +1766,105 @@ int S_LookupSound(const char* fn)
|
||||||
}
|
}
|
||||||
return fileSystem.FindFile(fn);
|
return fileSystem.FindFile(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Although saving the sound system's state is supposed to be an engine
|
||||||
|
// feature, the specifics cannot be set up there, this needs to be on the client side.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static FSerializer& Serialize(FSerializer& arc, const char* key, FSoundChan& chan, FSoundChan* def)
|
||||||
|
{
|
||||||
|
if (arc.BeginObject(key))
|
||||||
|
{
|
||||||
|
arc("sourcetype", chan.SourceType)
|
||||||
|
("soundid", chan.SoundID)
|
||||||
|
("orgid", chan.OrgID)
|
||||||
|
("volume", chan.Volume)
|
||||||
|
("distancescale", chan.DistanceScale)
|
||||||
|
("pitch", chan.Pitch)
|
||||||
|
("chanflags", chan.ChanFlags)
|
||||||
|
("entchannel", chan.EntChannel)
|
||||||
|
("priority", chan.Priority)
|
||||||
|
("nearlimit", chan.NearLimit)
|
||||||
|
("starttime", chan.StartTime)
|
||||||
|
("rolloftype", chan.Rolloff.RolloffType)
|
||||||
|
("rolloffmin", chan.Rolloff.MinDistance)
|
||||||
|
("rolloffmax", chan.Rolloff.MaxDistance)
|
||||||
|
("limitrange", chan.LimitRange)
|
||||||
|
.Array("point", chan.Point, 3);
|
||||||
|
|
||||||
|
int SourceIndex = 0;
|
||||||
|
if (arc.isWriting())
|
||||||
|
{
|
||||||
|
if (chan.SourceType == SOURCE_Actor) SourceIndex = int((spritetype*)(chan.Source) - sprite);
|
||||||
|
else SourceIndex = soundEngine->SoundSourceIndex(&chan);
|
||||||
|
}
|
||||||
|
arc("Source", SourceIndex);
|
||||||
|
if (arc.isReading())
|
||||||
|
{
|
||||||
|
if (chan.SourceType == SOURCE_Actor) chan.Source = &sprite[SourceIndex];
|
||||||
|
else soundEngine->SetSource(&chan, SourceIndex);
|
||||||
|
}
|
||||||
|
arc.EndObject();
|
||||||
|
}
|
||||||
|
return arc;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// S_SerializeSounds
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void S_SerializeSounds(FSerializer& arc)
|
||||||
|
{
|
||||||
|
FSoundChan* chan;
|
||||||
|
|
||||||
|
GSnd->Sync(true);
|
||||||
|
|
||||||
|
if (arc.isWriting())
|
||||||
|
{
|
||||||
|
// 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.
|
||||||
|
TArray<FSoundChan*> chans = soundEngine->AllActiveChannels();
|
||||||
|
|
||||||
|
if (chans.Size() > 0 && arc.BeginArray("sounds"))
|
||||||
|
{
|
||||||
|
for (unsigned int i = chans.Size(); i-- != 0; )
|
||||||
|
{
|
||||||
|
// Replace start time with sample position.
|
||||||
|
uint64_t start = chans[i]->StartTime;
|
||||||
|
chans[i]->StartTime = GSnd ? GSnd->GetPosition(chans[i]) : 0;
|
||||||
|
arc(nullptr, *chans[i]);
|
||||||
|
chans[i]->StartTime = start;
|
||||||
|
}
|
||||||
|
arc.EndArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int count;
|
||||||
|
|
||||||
|
soundEngine->StopAllChannels();
|
||||||
|
if (arc.BeginArray("sounds"))
|
||||||
|
{
|
||||||
|
count = arc.ArraySize();
|
||||||
|
for (unsigned int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
chan = (FSoundChan*)soundEngine->GetChannel(nullptr);
|
||||||
|
arc(nullptr, *chan);
|
||||||
|
// Sounds always start out evicted when restored from a save.
|
||||||
|
chan->ChanFlags |= CHANF_EVICTED | CHANF_ABSTIME;
|
||||||
|
}
|
||||||
|
arc.EndArray();
|
||||||
|
}
|
||||||
|
// totalclock runs on 120 fps, we need to allow a small delay here.
|
||||||
|
soundEngine->SetRestartTime((int)totalclock + 6);
|
||||||
|
}
|
||||||
|
GSnd->Sync(false);
|
||||||
|
GSnd->UpdateSounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -275,6 +275,10 @@ public:
|
||||||
}
|
}
|
||||||
void EvictAllChannels();
|
void EvictAllChannels();
|
||||||
|
|
||||||
|
// For handling special sound types. Source types None, Unattached and Actor never get here.
|
||||||
|
virtual int SoundSourceIndex(FSoundChan* chan) { return 0; }
|
||||||
|
virtual void SetSource(FSoundChan* chan, int index) {}
|
||||||
|
|
||||||
void StopChannel(FSoundChan* chan);
|
void StopChannel(FSoundChan* chan);
|
||||||
sfxinfo_t* LoadSound(sfxinfo_t* sfx);
|
sfxinfo_t* LoadSound(sfxinfo_t* sfx);
|
||||||
|
|
||||||
|
@ -451,3 +455,5 @@ inline int S_FindSound(const char* name)
|
||||||
}
|
}
|
||||||
|
|
||||||
int S_LookupSound(const char* fn);
|
int S_LookupSound(const char* fn);
|
||||||
|
class FSerializer;
|
||||||
|
void S_SerializeSounds(FSerializer& arc);
|
||||||
|
|
|
@ -258,7 +258,7 @@ void BendAmbientSound(void)
|
||||||
{
|
{
|
||||||
soundEngine->EnumerateChannels([](FSoundChan* chan)
|
soundEngine->EnumerateChannels([](FSoundChan* chan)
|
||||||
{
|
{
|
||||||
if (chan->SourceType == SOURCE_Ambient)
|
if (chan->SourceType == SOURCE_Ambient && chan->Source == &amb)
|
||||||
{
|
{
|
||||||
soundEngine->SetPitch(chan, (nDronePitch + 11800) / 11025.f);
|
soundEngine->SetPitch(chan, (nDronePitch + 11800) / 11025.f);
|
||||||
}
|
}
|
||||||
|
@ -346,7 +346,7 @@ void StartSwirly(int nActiveSound)
|
||||||
nVolume = 220;
|
nVolume = 220;
|
||||||
|
|
||||||
soundEngine->StopSound(SOURCE_Swirly, &swirly, -1);
|
soundEngine->StopSound(SOURCE_Swirly, &swirly, -1);
|
||||||
soundEngine->StartSound(SOURCE_Swirly, &swirly, nullptr, CHAN_BODY, 0, StaticSound[kSoundMana1]+1, nVolume / 255.f, ATTN_NONE, nullptr, nPitch / 11025.f);
|
soundEngine->StartSound(SOURCE_Swirly, &swirly, nullptr, CHAN_BODY, CHANF_TRANSIENT, StaticSound[kSoundMana1]+1, nVolume / 255.f, ATTN_NONE, nullptr, nPitch / 11025.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -396,7 +396,7 @@ void SoundBigEntrance(void)
|
||||||
short nPitch = i * 512 - 1200;
|
short nPitch = i * 512 - 1200;
|
||||||
//pASound->snd_pitch = nPitch;
|
//pASound->snd_pitch = nPitch;
|
||||||
soundEngine->StopSound(SOURCE_EXBoss, &fakesources[i], -1);
|
soundEngine->StopSound(SOURCE_EXBoss, &fakesources[i], -1);
|
||||||
soundEngine->StartSound(SOURCE_EXBoss, &fakesources[i], nullptr, CHAN_BODY, 0, StaticSound[kSoundTorchOn]+1, 200 / 255.f, ATTN_NONE, nullptr, nPitch / 11025.f);
|
soundEngine->StartSound(SOURCE_EXBoss, &fakesources[i], nullptr, CHAN_BODY, CHANF_TRANSIENT, StaticSound[kSoundTorchOn]+1, 200 / 255.f, ATTN_NONE, nullptr, nPitch / 11025.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,7 +611,7 @@ void CheckAmbience(short nSector)
|
||||||
{
|
{
|
||||||
vec3_t v = { pWall->x, pWall->y, sector[nSector2].floorz };
|
vec3_t v = { pWall->x, pWall->y, sector[nSector2].floorz };
|
||||||
amb = GetSoundPos(&v);
|
amb = GetSoundPos(&v);
|
||||||
soundEngine->StartSound(SOURCE_Ambient, &amb, nullptr, CHAN_BODY, CHANF_NONE, SectSound[nSector] + 1, 1.f, ATTN_NORM);
|
soundEngine->StartSound(SOURCE_Ambient, &amb, nullptr, CHAN_BODY, CHANF_TRANSIENT, SectSound[nSector] + 1, 1.f, ATTN_NORM);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
soundEngine->EnumerateChannels([=](FSoundChan* chan)
|
soundEngine->EnumerateChannels([=](FSoundChan* chan)
|
||||||
|
@ -685,7 +685,7 @@ void UpdateCreepySounds()
|
||||||
|
|
||||||
GetSpriteSoundPitch(&nVolume, &nPitch);
|
GetSpriteSoundPitch(&nVolume, &nPitch);
|
||||||
soundEngine->StopSound(SOURCE_Ambient, &creepy, CHAN_BODY);
|
soundEngine->StopSound(SOURCE_Ambient, &creepy, CHAN_BODY);
|
||||||
soundEngine->StartSound(SOURCE_Ambient, &creepy, nullptr, CHAN_BODY, CHANF_NONE, vsi + 1, nVolume / 255.f, ATTN_NONE, nullptr, (11025 + nPitch) / 11025.f);
|
soundEngine->StartSound(SOURCE_Ambient, &creepy, nullptr, CHAN_BODY, CHANF_TRANSIENT, vsi + 1, nVolume / 255.f, ATTN_NONE, nullptr, (11025 + nPitch) / 11025.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nCreepyTimer = kCreepyCount;
|
nCreepyTimer = kCreepyCount;
|
||||||
|
|
|
@ -1009,16 +1009,18 @@ void InitLevelGlobals2(void)
|
||||||
void
|
void
|
||||||
InitLevel(void)
|
InitLevel(void)
|
||||||
{
|
{
|
||||||
|
if (LoadGameOutsideMoveLoop)
|
||||||
|
{
|
||||||
|
InitLevelGlobals();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static int DemoNumber = 0;
|
static int DemoNumber = 0;
|
||||||
|
|
||||||
Terminate3DSounds();
|
Terminate3DSounds();
|
||||||
|
|
||||||
// A few IMPORTANT GLOBAL RESETS
|
// A few IMPORTANT GLOBAL RESETS
|
||||||
InitLevelGlobals();
|
InitLevelGlobals();
|
||||||
if (LoadGameOutsideMoveLoop)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DemoMode)
|
if (!DemoMode)
|
||||||
Mus_Stop();
|
Mus_Stop();
|
||||||
|
|
|
@ -431,6 +431,23 @@ public:
|
||||||
S_Rolloff.MinDistance = 0; // These are the default values, SW uses a few different rolloff settings.
|
S_Rolloff.MinDistance = 0; // These are the default values, SW uses a few different rolloff settings.
|
||||||
S_Rolloff.MaxDistance = 1187;
|
S_Rolloff.MaxDistance = 1187;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SoundSourceIndex(FSoundChan* chan) override
|
||||||
|
{
|
||||||
|
if (chan->SourceType == SOURCE_Player) return int(PLAYERp(chan->Source) - Player);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSource(FSoundChan* chan, int index) override
|
||||||
|
{
|
||||||
|
if (chan->SourceType == SOURCE_Player)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= MAX_SW_PLAYERS_REG) index = 0;
|
||||||
|
chan->Source = &Player[index];
|
||||||
|
}
|
||||||
|
else chan->Source = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
Loading…
Reference in a new issue