- matching sound backend code with GZDoom.

# Conflicts:
#	source/core/sound/s_soundinternal.h
This commit is contained in:
Christoph Oelckers 2020-04-12 08:09:38 +02:00
parent c81e79e635
commit 8bd5f12b42
41 changed files with 522 additions and 365 deletions

View file

@ -701,6 +701,7 @@ set (PCH_SOURCES
core/screenshot.cpp core/screenshot.cpp
core/serializer.cpp core/serializer.cpp
core/raze_music.cpp core/raze_music.cpp
core/raze_sound.cpp
core/2d/v_2ddrawer.cpp core/2d/v_2ddrawer.cpp
core/2d/v_draw.cpp core/2d/v_draw.cpp

View file

@ -51,7 +51,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "endgame.h" #include "endgame.h"
#include "view.h" #include "view.h"
#include "tile.h" #include "tile.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
#include "gib.h" #include "gib.h"
#include "aiburn.h" #include "aiburn.h"

View file

@ -33,7 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "resource.h" #include "resource.h"
#include "sound.h" #include "sound.h"
#include "loadsave.h" #include "loadsave.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
BEGIN_BLD_NS BEGIN_BLD_NS

View file

@ -71,7 +71,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "m_argv.h" #include "m_argv.h"
#include "statistics.h" #include "statistics.h"
#include "menu/menu.h" #include "menu/menu.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
#include "nnexts.h" #include "nnexts.h"
#include"secrets.h" #include"secrets.h"

View file

@ -37,7 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "view.h" #include "view.h"
#include "animtexture.h" #include "animtexture.h"
#include "../glbackend/glbackend.h" #include "../glbackend/glbackend.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
BEGIN_BLD_NS BEGIN_BLD_NS

View file

@ -41,7 +41,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "statistics.h" #include "statistics.h"
#include "gamemenu.h" #include "gamemenu.h"
#include "gstrings.h" #include "gstrings.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
BEGIN_BLD_NS BEGIN_BLD_NS

View file

@ -39,7 +39,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "actor.h" #include "actor.h"
#include "tile.h" #include "tile.h"
#include "view.h" #include "view.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
BEGIN_BLD_NS BEGIN_BLD_NS

View file

@ -34,7 +34,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "sfx.h" #include "sfx.h"
#include "sound.h" #include "sound.h"
#include "trig.h" #include "trig.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
BEGIN_BLD_NS BEGIN_BLD_NS
@ -51,6 +51,19 @@ public:
S_Rolloff.MinDistance = 170; // these are the numbers I got when uncrunching the original sound code. S_Rolloff.MinDistance = 170; // these are the numbers I got when uncrunching the original sound code.
S_Rolloff.MaxDistance = 850; S_Rolloff.MaxDistance = 850;
} }
void StopChannel(FSoundChan* chan) override
{
if (chan && chan->SysChannel != NULL && !(chan->ChanFlags & CHANF_EVICTED) && chan->SourceType == SOURCE_Actor)
{
chan->Source = NULL;
chan->SourceType = SOURCE_Unattached;
}
SoundEngine::StopChannel(chan);
}
}; };
void sfxInit(void) void sfxInit(void)

View file

@ -32,7 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "baselayer.h" #include "baselayer.h"
#include "raze_music.h" #include "raze_music.h"
#include "sfx.h" #include "sfx.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
BEGIN_BLD_NS BEGIN_BLD_NS

View file

@ -59,6 +59,7 @@
#include "i_system.h" #include "i_system.h"
#include "s_soundinternal.h" #include "s_soundinternal.h"
#include "engineerrors.h" #include "engineerrors.h"
#include "gamecontrol.h"
#define LEFTMARGIN 8 #define LEFTMARGIN 8
#define RIGHTMARGIN 8 #define RIGHTMARGIN 8

View file

@ -45,7 +45,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "gstrings.h" #include "gstrings.h"
#include "quotemgr.h" #include "quotemgr.h"
#include "mapinfo.h" #include "mapinfo.h"
#include "s_soundinternal.h" #include "raze_sound.h"
#include "i_system.h" #include "i_system.h"
#include "inputstate.h" #include "inputstate.h"
#include "v_video.h" #include "v_video.h"

View file

@ -78,6 +78,7 @@ struct UserConfig
extern UserConfig userConfig; extern UserConfig userConfig;
extern int nomusic; extern int nomusic;
extern bool nosound;
inline bool MusicEnabled() inline bool MusicEnabled()
{ {
return !nomusic; return !nomusic;
@ -85,7 +86,7 @@ inline bool MusicEnabled()
inline bool SoundEnabled() inline bool SoundEnabled()
{ {
return snd_enabled && !userConfig.nosound; return snd_enabled && !nosound;
} }
@ -173,4 +174,11 @@ struct FStartupInfo
//int LoadBrightmaps = -1; //int LoadBrightmaps = -1;
}; };
extern FStartupInfo RazeStartupInfo; extern FStartupInfo RazeStartupInfo;
enum
{
PAUSESFX_MENU = 1,
PAUSESFX_CONSOLE = 2
};

View file

@ -53,7 +53,7 @@
#include "baselayer.h" #include "baselayer.h"
#include "statistics.h" #include "statistics.h"
#include "input/m_joy.h" #include "input/m_joy.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
void RegisterDukeMenus(); void RegisterDukeMenus();
void RegisterRedneckMenus(); void RegisterRedneckMenus();

250
source/core/raze_sound.cpp Normal file
View file

@ -0,0 +1,250 @@
/*
** s_sound.cpp
** Main sound engine
**
**---------------------------------------------------------------------------
** Copyright 1998-2016 Randy Heit
** Copyright 2002-2019 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "raze_sound.h"
#include "c_cvars.h"
#include "basics.h"
#include "stats.h"
#include "v_text.h"
#include "filesystem.h"
#include "serializer.h"
#include "name.h"
#include "cmdlib.h"
#include "gamecontrol.h"
#include "build.h"
extern ReverbContainer* ForcedEnvironment;
static int LastReverb;
CUSTOM_CVAR(Bool, snd_reverb, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
FX_SetReverb(-1);
}
// This is for testing reverb settings.
CUSTOM_CVAR(Int, snd_reverbtype, -1, 0)
{
FX_SetReverb(-1);
}
void FX_SetReverb(int strength)
{
if (strength == -1) strength = LastReverb;
if (snd_reverbtype > -1)
{
strength = snd_reverbtype;
ForcedEnvironment = S_FindEnvironment(strength);
}
else if (snd_reverb && strength > 0)
{
// todo: optimize environments. The original "reverb" was garbage and not usable as reference.
if (strength < 64) strength = 0x1400;
else if (strength < 192) strength = 0x1503;
else strength = 0x1900;
LastReverb = strength;
ForcedEnvironment = S_FindEnvironment(strength);
}
else ForcedEnvironment = nullptr;
}
//==========================================================================
//
// S_NoiseDebug
//
// [RH] Print sound debug info. Called by status bar.
//==========================================================================
FString NoiseDebug(SoundEngine *engine)
{
FVector3 listener;
FVector3 origin;
listener = engine->GetListener().position;
int ch = 0;
FString out;
out.Format("*** SOUND DEBUG INFO ***\nListener: %3.2f %2.3f %2.3f\n"
"x y z vol dist chan pri flags aud pos name\n", listener.X, listener.Y, listener.Z);
for (auto chan = engine->GetChannels(); chan; chan = chan->NextChan)
{
if (!(chan->ChanFlags & CHANF_IS3D))
{
out += "--- --- --- --- ";
}
else
{
engine->CalcPosVel(chan, &origin, nullptr);
out.AppendFormat(TEXTCOLOR_GOLD "%5.0f | %5.0f | %5.0f | %5.0f ", origin.X, origin.Z, origin.Y, (origin - listener).Length());
}
out.AppendFormat("%-.2g %-4d %-4d %sF%s3%sZ%sU%sM%sN%sA%sL%sE%sV" TEXTCOLOR_GOLD " %-5.4f %-4u %d: %s %p\n", chan->Volume, chan->EntChannel, chan->Priority,
(chan->ChanFlags & CHANF_FORGETTABLE) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_IS3D) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_LISTENERZ) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_UI) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_MAYBE_LOCAL) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_NOPAUSE) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_AREA) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_LOOP) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_EVICTED) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_VIRTUAL) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
GSnd->GetAudibility(chan), GSnd->GetPosition(chan), ((int)chan->OrgID)-1, engine->GetSounds()[chan->SoundID].name.GetChars(), chan->Source);
ch++;
}
out.AppendFormat("%d channels\n", ch);
return out;
}
ADD_STAT(sounddebug)
{
return NoiseDebug(soundEngine);
}
CVAR(Bool, snd_extendedlookup, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
int S_LookupSound(const char* fn)
{
static const char * const sndformats[] = { "OGG", "FLAC", "WAV" };
if (snd_extendedlookup)
{
int lump = fileSystem.FindFileWithExtensions(StripExtension(fn), sndformats, countof(sndformats));
if (lump >= 0) return lump;
}
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();
}

37
source/core/raze_sound.h Normal file
View file

@ -0,0 +1,37 @@
#pragma once
#include "s_soundinternal.h"
enum
{
SOURCE_Actor = SOURCE_None+1, // Sound is coming from an actor.
SOURCE_Ambient, // Sound is coming from a blood ambient definition.
SOURCE_Player, // SW player sound (player in SW maintains its own position separately from the sprite so needs to be special.)
SOURCE_Swirly, // Special stuff for Exhumed. (local sound with custom panning)
SOURCE_EXBoss, // Another special case for Exhumed.
};
inline void FX_StopAllSounds(void)
{
soundEngine->StopAllChannels();
}
void FX_SetReverb(int strength);
inline void FX_SetReverbDelay(int delay)
{
}
inline int S_FindSoundByResID(int ndx)
{
return soundEngine->FindSoundByResID(ndx);
}
inline int S_FindSound(const char* name)
{
return soundEngine->FindSound(name);
}
int S_LookupSound(const char* fn);
class FSerializer;
void S_SerializeSounds(FSerializer& arc);

View file

@ -38,7 +38,7 @@
#include "filesystem.h" #include "filesystem.h"
#include "rts.h" #include "rts.h"
#include "m_swap.h" #include "m_swap.h"
#include "s_soundinternal.h" #include "raze_sound.h"
struct WadInfo struct WadInfo

View file

@ -50,7 +50,7 @@
#include "serializer.h" #include "serializer.h"
#include "version.h" #include "version.h"
#include "raze_music.h" #include "raze_music.h"
#include "s_soundinternal.h" #include "raze_sound.h"
static CompositeSavegameWriter savewriter; static CompositeSavegameWriter savewriter;
static FResourceFile *savereader; static FResourceFile *savereader;

View file

@ -49,7 +49,7 @@
#include "cmdlib.h" #include "cmdlib.h"
#include "utf8.h" #include "utf8.h"
#include "printf.h" #include "printf.h"
#include "s_soundinternal.h" #include "raze_sound.h"
bool save_full = false; bool save_full = false;

View file

@ -36,10 +36,9 @@
#include <stdlib.h> #include <stdlib.h>
#include "oalsound.h" #include "oalsound.h"
#include "printf.h"
#include "i_module.h" #include "i_module.h"
#include "cmdlib.h" #include "cmdlib.h"
#include <zmusic.h>
#include "c_dispatch.h" #include "c_dispatch.h"
#include "i_music.h" #include "i_music.h"
@ -47,12 +46,9 @@
#include "v_text.h" #include "v_text.h"
#include "c_cvars.h" #include "c_cvars.h"
#include "stats.h" #include "stats.h"
#include "s_music.h"
#include "raze_music.h"
#include "gamecvars.h"
#include "gamecontrol.h"
#include <zmusic.h> #include <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)
@ -71,6 +67,8 @@ CVAR(String, snd_backend, DEF_BACKEND, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR (Bool, snd_pitched, false, CVAR_ARCHIVE) CVAR (Bool, snd_pitched, false, CVAR_ARCHIVE)
SoundRenderer *GSnd; SoundRenderer *GSnd;
bool nosound;
bool nosfx;
void I_CloseSound (); void I_CloseSound ();
@ -173,17 +171,17 @@ public:
} }
// Starts a sound. // Starts a sound.
FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime)
{ {
return NULL; return NULL;
} }
FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan) FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime)
{ {
return NULL; return NULL;
} }
// Marks a channel's start time without actually playing it. // Marks a channel's start time without actually playing it.
void MarkStartTime (FISoundChannel *chan) void MarkStartTime (FISoundChannel *chan, float startTime)
{ {
} }
@ -247,21 +245,31 @@ public:
void I_InitSound () void I_InitSound ()
{ {
FModule_SetProgDir(progdir); FModule_SetProgDir(progdir);
/* Get command line options: */
nosound = !!Args->CheckParm ("-nosound");
nosfx = !!Args->CheckParm ("-nosfx");
GSnd = NULL; GSnd = NULL;
if (userConfig.nosound) if (nosound)
{ {
GSnd = new NullSoundRenderer; GSnd = new NullSoundRenderer;
return; return;
} }
#ifndef NO_OPENAL // Keep it simple: let everything except "null" init the sound.
if (IsOpenALPresent()) if (stricmp(snd_backend, "null") == 0)
{ {
GSnd = new OpenALSoundRenderer; GSnd = new NullSoundRenderer;
}
else
{
#ifndef NO_OPENAL
if (IsOpenALPresent())
{
GSnd = new OpenALSoundRenderer;
}
#endif
} }
#endif // !NO_OPENAL
if (!GSnd || !GSnd->IsValid ()) if (!GSnd || !GSnd->IsValid ())
{ {
I_CloseSound(); I_CloseSound();

View file

@ -35,6 +35,7 @@
#ifndef __I_SOUND__ #ifndef __I_SOUND__
#define __I_SOUND__ #define __I_SOUND__
#include <vector>
#include "i_soundinternal.h" #include "i_soundinternal.h"
#include "zstring.h" #include "zstring.h"
#include <zmusic.h> #include <zmusic.h>
@ -108,8 +109,8 @@ public:
virtual SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) = 0; virtual SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) = 0;
// Starts a sound. // Starts a sound.
virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) = 0; virtual FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime = 0.f) = 0;
virtual FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan) = 0; virtual FISoundChannel *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime = 0.f) = 0;
// Stops a sound channel. // Stops a sound channel.
virtual void StopChannel (FISoundChannel *chan) = 0; virtual void StopChannel (FISoundChannel *chan) = 0;
@ -121,7 +122,7 @@ public:
virtual void ChannelPitch(FISoundChannel *chan, float volume) = 0; virtual void ChannelPitch(FISoundChannel *chan, float volume) = 0;
// Marks a channel's start time without actually playing it. // Marks a channel's start time without actually playing it.
virtual void MarkStartTime (FISoundChannel *chan) = 0; virtual void MarkStartTime (FISoundChannel *chan, float startTime = 0.f) = 0;
// Returns position of sound on this channel, in samples. // Returns position of sound on this channel, in samples.
virtual unsigned int GetPosition(FISoundChannel *chan) = 0; virtual unsigned int GetPosition(FISoundChannel *chan) = 0;
@ -159,6 +160,8 @@ public:
}; };
extern SoundRenderer *GSnd; extern SoundRenderer *GSnd;
extern bool nosfx;
extern bool nosound;
void I_InitSound (); void I_InitSound ();
void I_CloseSound(); void I_CloseSound();
@ -166,11 +169,6 @@ void I_CloseSound();
extern ReverbContainer *DefaultEnvironments[26]; extern ReverbContainer *DefaultEnvironments[26];
bool IsOpenALPresent(); bool IsOpenALPresent();
void S_SoundReset();
enum
{
PAUSESFX_MENU = 1,
PAUSESFX_CONSOLE = 2
};
#endif #endif

View file

@ -6,7 +6,6 @@
#include "vectors.h" #include "vectors.h"
#include "tarray.h" #include "tarray.h"
#include <zmusic.h>
#include "tflags.h" #include "tflags.h"
enum EChanFlag enum EChanFlag
@ -30,7 +29,7 @@ enum EChanFlag
CHANF_VIRTUAL = 2048, // internal: Channel is currently virtual CHANF_VIRTUAL = 2048, // internal: Channel is currently virtual
CHANF_NOSTOP = 4096, // only for A_PlaySound. Does not start if channel is playing something. CHANF_NOSTOP = 4096, // only for A_PlaySound. Does not start if channel is playing something.
CHANF_OVERLAP = 8192, // [MK] Does not stop any sounds in the channel and instead plays over them. CHANF_OVERLAP = 8192, // [MK] Does not stop any sounds in the channel and instead plays over them.
CHANF_ENDED = 16384, // Helper to detect broken ChannelEnded implementations. CHANF_LOCAL = 16384, // only plays locally for the calling actor
CHANF_TRANSIENT = 32768, // Do not record in savegames - used for sounds that get restarted outside the sound system (e.g. ambients in SW and Blood) CHANF_TRANSIENT = 32768, // Do not record in savegames - used for sounds that get restarted outside the sound system (e.g. ambients in SW and Blood)
}; };

View file

@ -35,16 +35,15 @@
#include <functional> #include <functional>
#include <chrono> #include <chrono>
#include "c_cvars.h"
#include "templates.h" #include "templates.h"
#include "oalsound.h" #include "oalsound.h"
#include "c_dispatch.h" #include "c_dispatch.h"
#include "v_text.h" #include "v_text.h"
#include "i_module.h" #include "i_module.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "c_cvars.h" #include "m_fixed.h"
#include "printf.h"
#include <zmusic.h>
#include "filereadermusicinterface.h"
const char *GetSampleTypeName(SampleType type); const char *GetSampleTypeName(SampleType type);
const char *GetChannelConfigName(ChannelConfig chan); const char *GetChannelConfigName(ChannelConfig chan);
@ -108,7 +107,9 @@ ReverbContainer *ForcedEnvironment;
#ifndef NO_OPENAL #ifndef NO_OPENAL
EXTERN_CVAR (Int, snd_channels)
EXTERN_CVAR (Int, snd_samplerate) EXTERN_CVAR (Int, snd_samplerate)
EXTERN_CVAR (Bool, snd_waterreverb)
EXTERN_CVAR (Bool, snd_pitched) EXTERN_CVAR (Bool, snd_pitched)
EXTERN_CVAR (Int, snd_hrtf) EXTERN_CVAR (Int, snd_hrtf)
@ -1171,7 +1172,7 @@ SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int
return stream; return stream;
} }
FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime)
{ {
if(FreeSfx.Size() == 0) if(FreeSfx.Size() == 0)
{ {
@ -1222,7 +1223,10 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
alSourcef(source, AL_PITCH, PITCH(pitch)); alSourcef(source, AL_PITCH, PITCH(pitch));
if(!reuse_chan || reuse_chan->StartTime == 0) if(!reuse_chan || reuse_chan->StartTime == 0)
alSourcef(source, AL_SEC_OFFSET, 0.f); {
float st = (chanflags&SNDF_LOOP) ? fmod(startTime, (float)GetMSLength(sfx) / 1000.f) : clamp<float>(startTime, 0.f, (float)GetMSLength(sfx) / 1000.f);
alSourcef(source, AL_SEC_OFFSET, st);
}
else else
{ {
if((chanflags&SNDF_ABSTIME)) if((chanflags&SNDF_ABSTIME))
@ -1271,7 +1275,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int
FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener *listener, float vol,
FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel,
int channum, int chanflags, FISoundChannel *reuse_chan) int channum, int chanflags, FISoundChannel *reuse_chan, float startTime)
{ {
float dist_sqr = (float)(pos - listener->position).LengthSquared(); float dist_sqr = (float)(pos - listener->position).LengthSquared();
@ -1415,7 +1419,10 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener
alSourcef(source, AL_PITCH, PITCH(pitch)); alSourcef(source, AL_PITCH, PITCH(pitch));
if(!reuse_chan || reuse_chan->StartTime == 0) if(!reuse_chan || reuse_chan->StartTime == 0)
alSourcef(source, AL_SEC_OFFSET, 0.f); {
float st = (chanflags & SNDF_LOOP) ? fmod(startTime, (float)GetMSLength(sfx) / 1000.f) : clamp<float>(startTime, 0.f, (float)GetMSLength(sfx) / 1000.f);
alSourcef(source, AL_SEC_OFFSET, st);
}
else else
{ {
if((chanflags&SNDF_ABSTIME)) if((chanflags&SNDF_ABSTIME))
@ -1782,7 +1789,7 @@ void OpenALSoundRenderer::UpdateSounds()
if(connected == ALC_FALSE) if(connected == ALC_FALSE)
{ {
Printf("Sound device disconnected; restarting...\n"); Printf("Sound device disconnected; restarting...\n");
soundEngine->Reset(); S_SoundReset();
return; return;
} }
} }
@ -1795,11 +1802,14 @@ bool OpenALSoundRenderer::IsValid()
return Device != NULL; return Device != NULL;
} }
void OpenALSoundRenderer::MarkStartTime(FISoundChannel *chan) void OpenALSoundRenderer::MarkStartTime(FISoundChannel *chan, float startTime)
{ {
// FIXME: Get current time (preferably from the audio clock, but the system // FIXME: Get current time (preferably from the audio clock, but the system
// time will have to do) // time will have to do)
chan->StartTime = std::chrono::steady_clock::now().time_since_epoch().count(); using namespace std::chrono;
auto startTimeDuration = duration<double>(startTime);
auto diff = steady_clock::now().time_since_epoch() - startTimeDuration;
chan->StartTime = static_cast<uint64_t>(duration_cast<nanoseconds>(diff).count());
} }
float OpenALSoundRenderer::GetAudibility(FISoundChannel *chan) float OpenALSoundRenderer::GetAudibility(FISoundChannel *chan)

View file

@ -136,8 +136,8 @@ public:
virtual SoundStream *CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata); virtual SoundStream *CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata);
// Starts a sound. // Starts a sound.
virtual FISoundChannel *StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan); virtual FISoundChannel *StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan, float startTime);
virtual FISoundChannel *StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan); virtual FISoundChannel *StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan, float startTime);
// Changes a channel's volume. // Changes a channel's volume.
virtual void ChannelVolume(FISoundChannel *chan, float volume); virtual void ChannelVolume(FISoundChannel *chan, float volume);
@ -166,7 +166,7 @@ public:
virtual void UpdateListener(SoundListener *); virtual void UpdateListener(SoundListener *);
virtual void UpdateSounds(); virtual void UpdateSounds();
virtual void MarkStartTime(FISoundChannel*); virtual void MarkStartTime(FISoundChannel*, float startTime);
virtual float GetAudibility(FISoundChannel*); virtual float GetAudibility(FISoundChannel*);

View file

@ -36,16 +36,11 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "templates.h"
#include "s_soundinternal.h" #include "s_soundinternal.h"
#include "m_swap.h" #include "m_swap.h"
#include "superfasthash.h" #include "superfasthash.h"
#include "c_cvars.h" #include "s_music.h"
#include "name.h"
#include "filesystem.h"
#include "cmdlib.h"
#include "gamecontrol.h"
#include "serializer.h"
#include "build.h"
enum enum
@ -62,7 +57,7 @@ int sfx_empty = -1;
// //
//========================================================================== //==========================================================================
void SoundEngine::Init(TArray<uint8_t> &curve, int factor) void SoundEngine::Init(TArray<uint8_t> &curve)
{ {
StopAllChannels(); StopAllChannels();
// Free all channels for use. // Free all channels for use.
@ -71,7 +66,6 @@ void SoundEngine::Init(TArray<uint8_t> &curve, int factor)
ReturnChannel(Channels); ReturnChannel(Channels);
} }
S_SoundCurve = std::move(curve); S_SoundCurve = std::move(curve);
SndCurveFactor = (uint8_t)factor;
} }
//========================================================================== //==========================================================================
@ -173,7 +167,6 @@ void SoundEngine::CacheSound (sfxinfo_t *sfx)
} }
else else
{ {
// Since we do not know in what format the sound will be used, we have to cache both.
LoadSound(sfx); LoadSound(sfx);
sfx->bUsed = true; sfx->bUsed = true;
} }
@ -374,7 +367,7 @@ FSoundID SoundEngine::ResolveSound(const void *, int, FSoundID soundid, float &a
FSoundChan *SoundEngine::StartSound(int type, const void *source, FSoundChan *SoundEngine::StartSound(int type, const void *source,
const FVector3 *pt, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, const FVector3 *pt, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation,
FRolloffInfo *forcedrolloff, float spitch) FRolloffInfo *forcedrolloff, float spitch, float startTime)
{ {
sfxinfo_t *sfx; sfxinfo_t *sfx;
EChanFlags chanflags = flags; EChanFlags chanflags = flags;
@ -385,7 +378,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
FVector3 pos, vel; FVector3 pos, vel;
FRolloffInfo *rolloff; FRolloffInfo *rolloff;
if (sound_id <= 0 || volume <= 0 || userConfig.nosound ) if (sound_id <= 0 || volume <= 0 || nosfx || nosound )
return NULL; return NULL;
// prevent crashes. // prevent crashes.
@ -465,9 +458,8 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
near_limit = 0; near_limit = 0;
} }
// If this sound doesn't like playing near itself, don't play it if // If this sound doesn't like playing near itself, don't play it if that's what would happen.
// that's what would happen. (Does this really need the SOURCE_Actor restriction?) if (near_limit > 0 && CheckSoundLimit(sfx, pos, near_limit, limit_range, type, source, channel))
if (near_limit > 0 && CheckSoundLimit(sfx, pos, near_limit, limit_range, type, type == SOURCE_Actor? source : nullptr, channel))
{ {
chanflags |= CHANF_EVICTED; chanflags |= CHANF_EVICTED;
} }
@ -555,13 +547,17 @@ 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;
startTime = (startflags & SNDF_LOOP)
? fmod(startTime, (float)GSnd->GetMSLength(sfx->data) / 1000.f)
: clamp<float>(startTime, 0.f, (float)GSnd->GetMSLength(sfx->data) / 1000.f);
if (attenuation > 0 && type != SOURCE_None) if (attenuation > 0 && type != SOURCE_None)
{ {
chan = (FSoundChan*)GSnd->StartSound3D (sfx->data, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL); chan = (FSoundChan*)GSnd->StartSound3D (sfx->data, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL, startTime);
} }
else else
{ {
chan = (FSoundChan*)GSnd->StartSound (sfx->data, float(volume), pitch, startflags, NULL); chan = (FSoundChan*)GSnd->StartSound (sfx->data, float(volume), pitch, startflags, NULL, startTime);
} }
} }
if (chan == NULL && (chanflags & CHANF_LOOP)) if (chan == NULL && (chanflags & CHANF_LOOP))
@ -893,6 +889,38 @@ void SoundEngine::StopSound(int sourcetype, const void* actor, int channel, int
} }
} }
//==========================================================================
//
// S_StopAllActorSounds
//
// Stops all sounds on an actor.
//
//==========================================================================
void SoundEngine::StopActorSounds(int sourcetype, const void* actor, int chanmin, int chanmax)
{
const bool all = (chanmin == 0 && chanmax == 0);
if (!all && chanmax > chanmin)
{
const int temp = chanmax;
chanmax = chanmin;
chanmin = temp;
}
FSoundChan* chan = Channels;
while (chan != nullptr)
{
FSoundChan* next = chan->NextChan;
if (chan->SourceType == sourcetype &&
chan->Source == actor &&
(all || (chan->EntChannel >= chanmin && chan->EntChannel <= chanmax)))
{
StopChannel(chan);
}
chan = next;
}
}
//========================================================================== //==========================================================================
// //
// S_StopAllChannels // S_StopAllChannels
@ -1249,7 +1277,7 @@ float SoundEngine::GetRolloff(const FRolloffInfo* rolloff, float distance)
if (rolloff->RolloffType == ROLLOFF_Custom && S_SoundCurve.Size() > 0) if (rolloff->RolloffType == ROLLOFF_Custom && S_SoundCurve.Size() > 0)
{ {
return S_SoundCurve[int(S_SoundCurve.Size() * (1.f - volume))] / (float)SndCurveFactor; return S_SoundCurve[int(S_SoundCurve.Size() * (1.f - volume))] / 127.f;
} }
return (powf(10.f, volume) - 1.f) / 9.f; return (powf(10.f, volume) - 1.f) / 9.f;
} }
@ -1264,7 +1292,7 @@ void SoundEngine::ChannelEnded(FISoundChannel *ichan)
{ {
FSoundChan *schan = static_cast<FSoundChan*>(ichan); FSoundChan *schan = static_cast<FSoundChan*>(ichan);
bool evicted; bool evicted;
schan->ChanFlags &= ~CHANF_ENDED;
if (schan != NULL) if (schan != NULL)
{ {
// If the sound was stopped with GSnd->StopSound(), then we know // If the sound was stopped with GSnd->StopSound(), then we know
@ -1341,11 +1369,6 @@ void SoundEngine::StopChannel(FSoundChan *chan)
if (!(chan->ChanFlags & CHANF_EVICTED)) if (!(chan->ChanFlags & CHANF_EVICTED))
{ {
chan->ChanFlags |= CHANF_FORGETTABLE; chan->ChanFlags |= CHANF_FORGETTABLE;
if (chan->SourceType == SOURCE_Actor)
{
chan->Source = NULL;
chan->SourceType = SOURCE_Unattached;
}
} }
if (GSnd) GSnd->StopChannel(chan); if (GSnd) GSnd->StopChannel(chan);
} }
@ -1486,13 +1509,6 @@ 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;
}
//========================================================================== //==========================================================================
// //
@ -1645,209 +1661,10 @@ void SoundEngine::AddRandomSound(int Owner, TArray<uint32_t> list)
S_sfx[Owner].NearLimit = -1; S_sfx[Owner].NearLimit = -1;
} }
extern ReverbContainer* ForcedEnvironment; void S_SoundReset()
static int LastReverb;
CUSTOM_CVAR(Bool, snd_reverb, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{ {
FX_SetReverb(-1); S_StopMusic(true);
} soundEngine->Reset();
S_RestartMusic();
// This is for testing reverb settings.
CUSTOM_CVAR(Int, snd_reverbtype, -1, 0)
{
FX_SetReverb(-1);
}
void FX_SetReverb(int strength)
{
if (strength == -1) strength = LastReverb;
if (snd_reverbtype > -1)
{
strength = snd_reverbtype;
ForcedEnvironment = S_FindEnvironment(strength);
}
else if (snd_reverb && strength > 0)
{
// todo: optimize environments. The original "reverb" was garbage and not usable as reference.
if (strength < 64) strength = 0x1400;
else if (strength < 192) strength = 0x1503;
else strength = 0x1900;
LastReverb = strength;
ForcedEnvironment = S_FindEnvironment(strength);
}
else ForcedEnvironment = nullptr;
}
#include "basics.h"
#include "stats.h"
#include "v_text.h"
//==========================================================================
//
// S_NoiseDebug
//
// [RH] Print sound debug info. Called by status bar.
//==========================================================================
FString SoundEngine::NoiseDebug()
{
FVector3 listener;
FVector3 origin;
listener = this->listener.position;
int ch = 0;
FString out;
out.Format("*** SOUND DEBUG INFO ***\nListener: %3.2f %2.3f %2.3f\n"
"x y z vol dist chan pri flags aud pos name\n", listener.X, listener.Y, listener.Z);
for (auto chan = Channels; chan; chan = chan->NextChan)
{
if (!(chan->ChanFlags & CHANF_IS3D))
{
out += "--- --- --- --- ";
}
else
{
CalcPosVel(chan, &origin, nullptr);
out.AppendFormat(TEXTCOLOR_GOLD "%5.0f | %5.0f | %5.0f | %5.0f ", origin.X, origin.Z, origin.Y, (origin - listener).Length());
}
out.AppendFormat("%-.2g %-4d %-4d %sF%s3%sZ%sU%sM%sN%sA%sL%sE%sV" TEXTCOLOR_GOLD " %-5.4f %-4u %d: %s %p\n", chan->Volume, chan->EntChannel, chan->Priority,
(chan->ChanFlags & CHANF_FORGETTABLE) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_IS3D) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_LISTENERZ) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_UI) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_MAYBE_LOCAL) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_NOPAUSE) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_AREA) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_LOOP) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_EVICTED) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
(chan->ChanFlags & CHANF_VIRTUAL) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
GSnd->GetAudibility(chan), GSnd->GetPosition(chan), ((int)chan->OrgID)-1, S_sfx[chan->SoundID].name.GetChars(), chan->Source);
ch++;
}
out.AppendFormat("%d channels\n", ch);
return out;
}
ADD_STAT(sounddebug)
{
return soundEngine->NoiseDebug();
}
CVAR(Bool, snd_extendedlookup, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
int S_LookupSound(const char* fn)
{
static const char * const sndformats[] = { "OGG", "FLAC", "WAV" };
if (snd_extendedlookup)
{
int lump = fileSystem.FindFileWithExtensions(StripExtension(fn), sndformats, countof(sndformats));
if (lump >= 0) return lump;
}
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();
} }

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "backend/i_sound.h" #include "i_sound.h"
struct FRandomSoundList struct FRandomSoundList
{ {
@ -183,7 +183,6 @@ struct FSoundChan : public FISoundChannel
// CHAN_VOICE is for oof, sight, or other voice sounds // CHAN_VOICE is for oof, sight, or other voice sounds
// CHAN_ITEM is for small things and item pickup // CHAN_ITEM is for small things and item pickup
// CHAN_BODY is for generic body sounds // CHAN_BODY is for generic body sounds
// CHAN_PICKUP can optionally be set as a local sound only for "compatibility"
// Channels below 0 are reserved for CHAN_AUTO. // Channels below 0 are reserved for CHAN_AUTO.
enum EChannel enum EChannel
@ -206,16 +205,11 @@ enum EChannel
#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
enum // This cannot be remain as this, but for now it has to suffice. enum // The core source types, implementations may extend this list as they see fit.
{ {
SOURCE_Any = -1, // Input for check functions meaning 'any source' SOURCE_Any = -1, // Input for check functions meaning 'any source'
SOURCE_None, // Sound is always on top of the listener.
SOURCE_Actor, // Sound is coming from an actor.
SOURCE_Ambient, // Sound is coming from a blood ambient definition.
SOURCE_Unattached, // Sound is not attached to any particular emitter. SOURCE_Unattached, // Sound is not attached to any particular emitter.
SOURCE_Player, // SW player sound (player in SW maintains its own position separately from the sprite so needs to be special.) SOURCE_None, // Sound is always on top of the listener.
SOURCE_Swirly, // Special stuff for Exhumed. (local sound with custom panning)
SOURCE_EXBoss, // Another special case for Exhumed.
}; };
@ -233,7 +227,6 @@ class SoundEngine
{ {
protected: protected:
bool SoundPaused = false; // whether sound is paused bool SoundPaused = false; // whether sound is paused
uint8_t SndCurveFactor = 127;
int RestartEvictionsAt = 0; // do not restart evicted channels before this time int RestartEvictionsAt = 0; // do not restart evicted channels before this time
SoundListener listener{}; SoundListener listener{};
@ -264,9 +257,9 @@ private:
// Checks if a copy of this sound is already playing. // Checks if a copy of this sound is already playing.
bool CheckSingular(int sound_id); 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; virtual TArray<uint8_t> ReadSound(int lumpnum) = 0;
protected: protected:
virtual bool CheckSoundLimit(sfxinfo_t* sfx, const FVector3& pos, int near_limit, float limit_range, int sourcetype, const void* actor, int channel);
virtual FSoundID ResolveSound(const void *ent, int srctype, FSoundID soundid, float &attenuation); virtual FSoundID ResolveSound(const void *ent, int srctype, FSoundID soundid, float &attenuation);
public: public:
@ -276,18 +269,17 @@ 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 int SoundSourceIndex(FSoundChan* chan) { return 0; }
virtual void SetSource(FSoundChan* chan, int index) {} virtual void SetSource(FSoundChan* chan, int index) {}
void StopChannel(FSoundChan* chan); virtual void StopChannel(FSoundChan* chan);
sfxinfo_t* LoadSound(sfxinfo_t* sfx); sfxinfo_t* LoadSound(sfxinfo_t* sfx);
// Initializes sound stuff, including volume // Initializes sound stuff, including volume
// Sets channels, SFX and music volume, // Sets channels, SFX and music volume,
// allocates channel buffer, sets S_sfx lookup. // allocates channel buffer, sets S_sfx lookup.
// //
void Init(TArray<uint8_t> &sndcurve, int factor = 127); void Init(TArray<uint8_t> &sndcurve);
void InitData(); void InitData();
void Clear(); void Clear();
void Shutdown(); void Shutdown();
@ -301,19 +293,20 @@ public:
void CalcPosVel(FSoundChan* chan, FVector3* pos, FVector3* vel); void CalcPosVel(FSoundChan* chan, FVector3* pos, FVector3* vel);
// Loads a sound, including any random sounds it might reference. // Loads a sound, including any random sounds it might reference.
void CacheSound(sfxinfo_t* sfx); virtual void CacheSound(sfxinfo_t* sfx);
void CacheSound(int sfx) { CacheSound(&S_sfx[sfx]); } void CacheSound(int sfx) { CacheSound(&S_sfx[sfx]); }
void UnloadSound(sfxinfo_t* sfx); void UnloadSound(sfxinfo_t* sfx);
void UpdateSounds(int time); void UpdateSounds(int time);
FSoundChan* StartSound(int sourcetype, const void* source, FSoundChan* StartSound(int sourcetype, const void* source,
const FVector3* pt, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, FRolloffInfo* rolloff = nullptr, float spitch = 0.0f); const FVector3* pt, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, FRolloffInfo* rolloff = nullptr, float spitch = 0.0f, float startTime = 0.0f);
// Stops an origin-less sound from playing from this channel. // Stops an origin-less sound from playing from this channel.
void StopSoundID(int sound_id); void StopSoundID(int sound_id);
void StopSound(int channel, int sound_id = -1); void StopSound(int channel, int sound_id = -1);
void StopSound(int sourcetype, const void* actor, int channel, int sound_id = -1); void StopSound(int sourcetype, const void* actor, int channel, int sound_id = -1);
void StopActorSounds(int sourcetype, const void* actor, int chanmin, int chanmax);
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);
@ -326,7 +319,6 @@ public:
void Reset(); void Reset();
void MarkUsed(int num); void MarkUsed(int num);
void CacheMarkedSounds(); void CacheMarkedSounds();
FString NoiseDebug();
TArray<FSoundChan*> AllActiveChannels(); TArray<FSoundChan*> AllActiveChannels();
void MarkAllUnused() void MarkAllUnused()
@ -342,6 +334,10 @@ public:
{ {
listener = l; listener = l;
} }
const SoundListener& GetListener() const
{
return listener;
}
void SetRestartTime(int time) void SetRestartTime(int time)
{ {
RestartEvictionsAt = time; RestartEvictionsAt = time;
@ -413,8 +409,7 @@ public:
int FindSoundByResID(int rid); int FindSoundByResID(int rid);
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); virtual 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);
@ -434,27 +429,4 @@ struct FReverbField
unsigned int Flag; unsigned int Flag;
}; };
inline void FX_StopAllSounds(void)
{
soundEngine->StopAllChannels();
}
void FX_SetReverb(int strength);
inline void FX_SetReverbDelay(int delay)
{
}
inline int S_FindSoundByResID(int ndx)
{
return soundEngine->FindSoundByResID(ndx);
}
inline int S_FindSound(const char* name)
{
return soundEngine->FindSound(name);
}
int S_LookupSound(const char* fn);
class FSerializer;
void S_SerializeSounds(FSerializer& arc);

View file

@ -67,8 +67,8 @@ void Demo_PrepareWarp(void)
{ {
if (!g_demo_paused) if (!g_demo_paused)
{ {
g_demo_soundToggle = userConfig.nosound; g_demo_soundToggle = nosound;
userConfig.nosound = true; nosound = true;
} }
FX_StopAllSounds(); FX_StopAllSounds();
@ -384,8 +384,8 @@ static void Demo_SetupProfile(void)
{ {
g_demo_profile *= -1; // now >0: profile for real g_demo_profile *= -1; // now >0: profile for real
g_demo_soundToggle = userConfig.nosound; g_demo_soundToggle = nosound;
userConfig.nosound = true; // restored by Demo_FinishProfile() nosound = true; // restored by Demo_FinishProfile()
Bmemset(&g_prof, 0, sizeof(g_prof)); Bmemset(&g_prof, 0, sizeof(g_prof));
@ -401,7 +401,7 @@ static void Demo_FinishProfile(void)
double gms=g_prof.totalgamems; double gms=g_prof.totalgamems;
double dms1=g_prof.totalroomsdrawms, dms2=g_prof.totalrestdrawms; double dms1=g_prof.totalroomsdrawms, dms2=g_prof.totalrestdrawms;
userConfig.nosound = g_demo_soundToggle; nosound = g_demo_soundToggle;
if (nt > 0) if (nt > 0)
{ {
@ -667,7 +667,7 @@ nextdemo_nomenu:
if (g_demo_goalCnt>0) if (g_demo_goalCnt>0)
{ {
g_demo_goalCnt=0; g_demo_goalCnt=0;
userConfig.nosound = g_demo_soundToggle; nosound = g_demo_soundToggle;
} }
if (Demo_IsProfiling()) // don't reset g_demo_profile if it's < 0 if (Demo_IsProfiling()) // don't reset g_demo_profile if it's < 0
@ -709,10 +709,10 @@ nextdemo_nomenu:
} }
else else
{ {
int32_t k = userConfig.nosound; int32_t k = nosound;
userConfig.nosound = true; nosound = true;
G_DoMoveThings(); G_DoMoveThings();
userConfig.nosound = k; nosound = k;
} }
ototalclock += TICSPERFRAME; ototalclock += TICSPERFRAME;
@ -727,7 +727,7 @@ nextdemo_nomenu:
if (g_demo_cnt>=g_demo_goalCnt) if (g_demo_cnt>=g_demo_goalCnt)
{ {
g_demo_goalCnt = 0; g_demo_goalCnt = 0;
userConfig.nosound = g_demo_soundToggle; nosound = g_demo_soundToggle;
} }
} }
} }

View file

@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "duke3d.h" #include "duke3d.h"
#include "raze_music.h" #include "raze_music.h"
#include "mapinfo.h" #include "mapinfo.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
BEGIN_DUKE_NS BEGIN_DUKE_NS
@ -44,6 +44,17 @@ public:
S_Rolloff.MinDistance = 144; // was originally 576 which looks like a bug and sounds like crap. S_Rolloff.MinDistance = 144; // was originally 576 which looks like a bug and sounds like crap.
S_Rolloff.MaxDistance = 1088; S_Rolloff.MaxDistance = 1088;
} }
void StopChannel(FSoundChan* chan) override
{
if (chan && chan->SysChannel != NULL && !(chan->ChanFlags & CHANF_EVICTED) && chan->SourceType == SOURCE_Actor)
{
chan->Source = NULL;
chan->SourceType = SOURCE_Unattached;
}
SoundEngine::StopChannel(chan);
}
}; };
void S_InitSound() void S_InitSound()

View file

@ -30,7 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define sounds_public_h_ #define sounds_public_h_
#include "sounds_common.h" #include "sounds_common.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
#include "raze_music.h" #include "raze_music.h"
BEGIN_DUKE_NS BEGIN_DUKE_NS

View file

@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "sound.h" #include "sound.h"
#include "names.h" #include "names.h"
#include "version.h" #include "version.h"
#include "s_soundinternal.h" #include "raze_sound.h"
#include "menu/menu.h" #include "menu/menu.h"

View file

@ -74,7 +74,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "gamecvars.h" #include "gamecvars.h"
#include "savegamehelp.h" #include "savegamehelp.h"
#include "c_dispatch.h" #include "c_dispatch.h"
#include "s_soundinternal.h" #include "raze_sound.h"
#include "core/menu/menu.h" #include "core/menu/menu.h"
BEGIN_PS_NS BEGIN_PS_NS

View file

@ -37,7 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "object.h" #include "object.h"
#include "light.h" #include "light.h"
#include "cd.h" #include "cd.h"
#include "s_soundinternal.h" #include "raze_sound.h"
#include "menu/menu.h" #include "menu/menu.h"
#include "v_2ddrawer.h" #include "v_2ddrawer.h"
#include <string> #include <string>

View file

@ -30,7 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "trigdat.h" #include "trigdat.h"
#include "sequence.h" #include "sequence.h"
#include "cd.h" #include "cd.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
BEGIN_PS_NS BEGIN_PS_NS
@ -153,6 +153,17 @@ public:
S_Rolloff.MinDistance = 0; S_Rolloff.MinDistance = 0;
S_Rolloff.MaxDistance = 1536; S_Rolloff.MaxDistance = 1536;
} }
void StopChannel(FSoundChan* chan) override
{
if (chan && chan->SysChannel != NULL && !(chan->ChanFlags & CHANF_EVICTED) && chan->SourceType == SOURCE_Actor)
{
chan->Source = NULL;
chan->SourceType = SOURCE_Unattached;
}
SoundEngine::StopChannel(chan);
}
}; };
//========================================================================== //==========================================================================

View file

@ -19,7 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef __sound_h__ #ifndef __sound_h__
#define __sound_h__ #define __sound_h__
#include "s_soundinternal.h" #include "raze_sound.h"
BEGIN_PS_NS BEGIN_PS_NS

View file

@ -66,8 +66,8 @@ void Demo_PrepareWarp(void)
{ {
if (!g_demo_paused) if (!g_demo_paused)
{ {
g_demo_soundToggle = userConfig.nosound; g_demo_soundToggle = nosound;
userConfig.nosound = true; nosound = true;
} }
FX_StopAllSounds(); FX_StopAllSounds();
@ -387,8 +387,8 @@ static void Demo_SetupProfile(void)
{ {
g_demo_profile *= -1; // now >0: profile for real g_demo_profile *= -1; // now >0: profile for real
g_demo_soundToggle = userConfig.nosound; g_demo_soundToggle = nosound;
userConfig.nosound = true; // restored by Demo_FinishProfile() nosound = true; // restored by Demo_FinishProfile()
Bmemset(&g_prof, 0, sizeof(g_prof)); Bmemset(&g_prof, 0, sizeof(g_prof));
@ -404,7 +404,7 @@ static void Demo_FinishProfile(void)
double gms=g_prof.totalgamems; double gms=g_prof.totalgamems;
double dms1=g_prof.totalroomsdrawms, dms2=g_prof.totalrestdrawms; double dms1=g_prof.totalroomsdrawms, dms2=g_prof.totalrestdrawms;
userConfig.nosound = g_demo_soundToggle; nosound = g_demo_soundToggle;
if (nt > 0) if (nt > 0)
{ {
@ -670,7 +670,7 @@ nextdemo_nomenu:
if (g_demo_goalCnt>0) if (g_demo_goalCnt>0)
{ {
g_demo_goalCnt=0; g_demo_goalCnt=0;
userConfig.nosound = g_demo_soundToggle; nosound = g_demo_soundToggle;
} }
if (Demo_IsProfiling()) // don't reset g_demo_profile if it's < 0 if (Demo_IsProfiling()) // don't reset g_demo_profile if it's < 0
@ -714,10 +714,10 @@ nextdemo_nomenu:
} }
else else
{ {
int32_t k = userConfig.nosound; int32_t k = nosound;
userConfig.nosound = true; nosound = true;
G_DoMoveThings(); G_DoMoveThings();
userConfig.nosound = k; nosound = k;
} }
ototalclock += TICSPERFRAME; ototalclock += TICSPERFRAME;
@ -732,7 +732,7 @@ nextdemo_nomenu:
if (g_demo_cnt>=g_demo_goalCnt) if (g_demo_cnt>=g_demo_goalCnt)
{ {
g_demo_goalCnt = 0; g_demo_goalCnt = 0;
userConfig.nosound = g_demo_soundToggle; nosound = g_demo_soundToggle;
} }
} }
} }

View file

@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "duke3d.h" #include "duke3d.h"
#include "raze_music.h" #include "raze_music.h"
#include "mapinfo.h" #include "mapinfo.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
BEGIN_RR_NS BEGIN_RR_NS
@ -43,6 +43,17 @@ public:
S_Rolloff.MinDistance = 144; // was originally 576 which looks like a bug and sounds like crap. S_Rolloff.MinDistance = 144; // was originally 576 which looks like a bug and sounds like crap.
S_Rolloff.MaxDistance = 1088; S_Rolloff.MaxDistance = 1088;
} }
void StopChannel(FSoundChan* chan) override
{
if (chan && chan->SysChannel != NULL && !(chan->ChanFlags & CHANF_EVICTED) && chan->SourceType == SOURCE_Actor)
{
chan->Source = NULL;
chan->SourceType = SOURCE_Unattached;
}
SoundEngine::StopChannel(chan);
}
}; };
void S_InitSound() void S_InitSound()

View file

@ -30,7 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define sounds_public_h_ #define sounds_public_h_
#include "sounds_common.h" #include "sounds_common.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
#include "raze_music.h" #include "raze_music.h"
BEGIN_RR_NS BEGIN_RR_NS

View file

@ -50,7 +50,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "colormap.h" #include "colormap.h"
#include "config.h" #include "config.h"
#include "menu/menu.h" #include "menu/menu.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
#include "sounds.h" #include "sounds.h"
#include "../../glbackend/glbackend.h" #include "../../glbackend/glbackend.h"

View file

@ -99,7 +99,7 @@ Things required to make savegames work:
#include "gstrings.h" #include "gstrings.h"
#include "mapinfo.h" #include "mapinfo.h"
#include "rendering/v_video.h" #include "rendering/v_video.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
#include "secrets.h" #include "secrets.h"
#include "osdcmds.h" #include "osdcmds.h"

View file

@ -46,7 +46,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
#include "settings.h" #include "settings.h"
#include "pragmas.h" #include "pragmas.h"
#include "gamecvars.h" #include "gamecvars.h"
#include "s_soundinternal.h" #include "raze_sound.h"
BEGIN_SW_NS BEGIN_SW_NS

View file

@ -46,7 +46,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
#include "weapon.h" #include "weapon.h"
#include "menu/menu.h" #include "menu/menu.h"
#include "swcvar.h" #include "swcvar.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
BEGIN_SW_NS BEGIN_SW_NS

View file

@ -50,7 +50,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
#include "config.h" #include "config.h"
#include "menu/menu.h" #include "menu/menu.h"
#include "raze_music.h" #include "raze_music.h"
#include "sound/s_soundinternal.h" #include "raze_sound.h"
#include "filesystem.h" #include "filesystem.h"
#include "serializer.h" #include "serializer.h"
@ -450,6 +450,16 @@ public:
else chan->Source = nullptr; else chan->Source = nullptr;
} }
void StopChannel(FSoundChan* chan) override
{
if (chan && chan->SysChannel != NULL && !(chan->ChanFlags & CHANF_EVICTED) && chan->SourceType == SOURCE_Actor)
{
chan->Source = NULL;
chan->SourceType = SOURCE_Unattached;
}
SoundEngine::StopChannel(chan);
}
}; };
//========================================================================== //==========================================================================