mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-27 22:42:57 +00:00
- Fixed: Actor-less sounds that aren't played on CHAN_AUTO should still be
subject to channel overriding. - Re-added priority selection based on sound usage. - Reduced the number of virtual channels to match the number of real channels. - Added customizable rolloff, including Doom's standard linear gain rolloff. SNDINFO commands are: $rolloff <sound> <min distance> <max distance> -- linear gain (like Doom) $rolloff <sound> linear <min distance> <max distance> -- linear volume $rolloff <sound> log <min distance> <rolloff factor> -- logarithmic $rolloff <sound> custom <min distance> <max distance> -- use SNDCURVE lump Anything closer than min distance is full volume and anything further than max distance is inaudible. Logarithmic rolloff does not have a maximum distance; it has a scalar that controls how quickly the volume drops off instead. SVN r834 (trunk)
This commit is contained in:
parent
cab572c008
commit
84d125cf21
8 changed files with 328 additions and 139 deletions
|
@ -1,3 +1,20 @@
|
|||
March 21, 2008
|
||||
- Fixed: Actor-less sounds that aren't played on CHAN_AUTO should still be
|
||||
subject to channel overriding.
|
||||
- Re-added priority selection based on sound usage.
|
||||
- Reduced the number of virtual channels to match the number of real
|
||||
channels.
|
||||
- Added customizable rolloff, including Doom's standard linear gain rolloff.
|
||||
SNDINFO commands are:
|
||||
$rolloff <sound> <min distance> <max distance> -- linear gain (like Doom)
|
||||
$rolloff <sound> linear <min distance> <max distance> -- linear volume
|
||||
$rolloff <sound> log <min distance> <rolloff factor> -- logarithmic
|
||||
$rolloff <sound> custom <min distance> <max distance> -- use SNDCURVE lump
|
||||
Anything closer than min distance is full volume and anything further than
|
||||
max distance is inaudible. Logarithmic rolloff does not have a maximum
|
||||
distance; it has a scalar that controls how quickly the volume drops off
|
||||
instead.
|
||||
|
||||
March 21, 2008 (Changes by Graf Zahl)
|
||||
- Disabled scrolling of 3DMIDTEX textures. Due to the special needs this
|
||||
cannot work properly.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
** Routines for managing SNDINFO lumps and ambient sounds
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2007 Randy Heit
|
||||
** Copyright 1998-2008 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
|
@ -145,7 +145,8 @@ enum SICommands
|
|||
SI_IfDoom,
|
||||
SI_IfHeretic,
|
||||
SI_IfHexen,
|
||||
SI_IfStrife
|
||||
SI_IfStrife,
|
||||
SI_Rolloff,
|
||||
};
|
||||
|
||||
// Blood was a cool game. If Monolith ever releases the source for it,
|
||||
|
@ -240,6 +241,7 @@ static const char *SICommandStrings[] =
|
|||
"$ifheretic",
|
||||
"$ifhexen",
|
||||
"$ifstrife",
|
||||
"$rolloff",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -450,7 +452,10 @@ int S_AddSoundLump (const char *logicalname, int lump)
|
|||
newsfx.bUsed = false;
|
||||
newsfx.bSingular = false;
|
||||
newsfx.bTentative = false;
|
||||
newsfx.RolloffType = ROLLOFF_Doom;
|
||||
newsfx.link = sfxinfo_t::NO_LINK;
|
||||
newsfx.MinDistance = 0;
|
||||
newsfx.MaxDistance = 0;
|
||||
|
||||
return (int)S_sfx.Push (newsfx);
|
||||
}
|
||||
|
@ -1136,6 +1141,62 @@ static void S_AddSNDINFO (int lump)
|
|||
CurrentPitchMask = (1 << clamp (sc.Number, 0, 7)) - 1;
|
||||
break;
|
||||
|
||||
case SI_Rolloff: {
|
||||
// $rolloff *|<logical name> [linear|log|custom] <min dist> <max dist/rolloff factor>
|
||||
// Using * for the name makes it the default for sounds that don't specify otherwise.
|
||||
float *min, *max;
|
||||
int type;
|
||||
int sfx;
|
||||
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("*"))
|
||||
{
|
||||
sfx = -1;
|
||||
min = &S_MinDistance;
|
||||
max = &S_MaxDistanceOrRolloffFactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
sfx = S_FindSoundTentative(sc.String);
|
||||
min = &S_sfx[sfx].MinDistance;
|
||||
max = &S_sfx[sfx].MaxDistance;
|
||||
}
|
||||
type = ROLLOFF_Doom;
|
||||
if (!sc.CheckFloat())
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("linear"))
|
||||
{
|
||||
type = ROLLOFF_Linear;
|
||||
}
|
||||
else if (sc.Compare("log"))
|
||||
{
|
||||
type = ROLLOFF_Log;
|
||||
}
|
||||
else if (sc.Compare("custom"))
|
||||
{
|
||||
type = ROLLOFF_Custom;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Unknown rolloff type '%s'", sc.String);
|
||||
}
|
||||
sc.MustGetFloat();
|
||||
}
|
||||
if (sfx < 0)
|
||||
{
|
||||
S_RolloffType = type;
|
||||
}
|
||||
else
|
||||
{
|
||||
S_sfx[sfx].RolloffType = type;
|
||||
}
|
||||
*min = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
*max = sc.Float;
|
||||
break;
|
||||
}
|
||||
|
||||
case SI_Random: {
|
||||
// $random <logical name> { <logical name> ... }
|
||||
FRandomSoundList random;
|
||||
|
|
|
@ -74,17 +74,6 @@
|
|||
#define S_PITCH_PERTURB 1
|
||||
#define S_STEREO_SWING 0.75
|
||||
|
||||
/* Sound curve parameters for Doom */
|
||||
|
||||
// Maximum sound distance
|
||||
const int S_CLIPPING_DIST = 1200;
|
||||
|
||||
// Sounds closer than this to the listener are maxed out.
|
||||
// Originally: 200.
|
||||
const int S_CLOSE_DIST = 160;
|
||||
|
||||
const float S_ATTENUATOR = S_CLIPPING_DIST - S_CLOSE_DIST;
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
struct MusPlayingInfo
|
||||
|
@ -112,12 +101,10 @@ static void CalcPosVel (fixed_t *pt, AActor *mover, int constz, float pos[3],
|
|||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
int MAX_SND_DIST;
|
||||
static bool SoundPaused; // whether sound effects are paused
|
||||
static bool MusicPaused; // whether music is paused
|
||||
static MusPlayingInfo mus_playing; // music currently being played
|
||||
static FString LastSong; // last music that was played
|
||||
static float *SoundCurve;
|
||||
static FPlayList *PlayList;
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
@ -127,6 +114,12 @@ int sfx_empty;
|
|||
FSoundChan *Channels;
|
||||
FSoundChan *FreeChannels;
|
||||
|
||||
int S_RolloffType;
|
||||
float S_MinDistance;
|
||||
float S_MaxDistanceOrRolloffFactor;
|
||||
BYTE *S_SoundCurve;
|
||||
int S_SoundCurveSize;
|
||||
|
||||
CVAR (Bool, snd_surround, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // [RH] Use surround sounds?
|
||||
FBoolCVar noisedebug ("noise", false, 0); // [RH] Print sound debugging info?
|
||||
CVAR (Int, snd_channels, 32, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // number of channels available
|
||||
|
@ -251,43 +244,23 @@ void S_AddLocalSndInfo(int lump);
|
|||
|
||||
void S_Init ()
|
||||
{
|
||||
int i;
|
||||
int curvelump;
|
||||
|
||||
atterm (S_Shutdown);
|
||||
|
||||
// remove old data (S_Init can be called multiple times!)
|
||||
if (SoundCurve)
|
||||
if (S_SoundCurve != NULL)
|
||||
{
|
||||
delete[] SoundCurve;
|
||||
delete[] S_SoundCurve;
|
||||
}
|
||||
|
||||
// Heretic and Hexen have sound curve lookup tables. Doom does not.
|
||||
curvelump = Wads.CheckNumForName ("SNDCURVE");
|
||||
if (curvelump >= 0)
|
||||
{
|
||||
MAX_SND_DIST = Wads.LumpLength (curvelump);
|
||||
SoundCurve = new float[MAX_SND_DIST];
|
||||
FMemLump lump = Wads.ReadLump(curvelump);
|
||||
BYTE *lumpmem = (BYTE *)lump.GetMem();
|
||||
|
||||
// The maximum value in a SNDCURVE lump is 127, so scale it to
|
||||
// fit our sound system's volume levels. Also, FMOD's volumes
|
||||
// are linear, whereas we want the "dumb" logarithmic volumes
|
||||
// for our "2D" sounds.
|
||||
for (i = 0; i < S_CLIPPING_DIST; ++i)
|
||||
{
|
||||
SoundCurve[i] = (powf(10.f, (lumpmem[i] / 127.f)) - 1.f) / 9.f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MAX_SND_DIST = S_CLIPPING_DIST;
|
||||
SoundCurve = new float[S_CLIPPING_DIST];
|
||||
for (i = 0; i < S_CLIPPING_DIST; ++i)
|
||||
{
|
||||
SoundCurve[i] = (powf(10.f, MIN(1.f, (S_CLIPPING_DIST - i) / S_ATTENUATOR)) - 1.f) / 9.f;
|
||||
}
|
||||
S_SoundCurveSize = Wads.LumpLength (curvelump);
|
||||
S_SoundCurve = new BYTE[S_SoundCurveSize];
|
||||
Wads.ReadLump(curvelump, S_SoundCurve);
|
||||
}
|
||||
|
||||
// Free all channels for use.
|
||||
|
@ -348,10 +321,10 @@ void S_Shutdown ()
|
|||
}
|
||||
FreeChannels = NULL;
|
||||
|
||||
if (SoundCurve != NULL)
|
||||
if (S_SoundCurve != NULL)
|
||||
{
|
||||
delete[] SoundCurve;
|
||||
SoundCurve = NULL;
|
||||
delete[] S_SoundCurve;
|
||||
S_SoundCurve = NULL;
|
||||
}
|
||||
if (PlayList != NULL)
|
||||
{
|
||||
|
@ -734,36 +707,34 @@ static void S_StartSound (fixed_t *pt, AActor *mover, int channel,
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Select priority.
|
||||
if (attenuation <= 0)
|
||||
if (attenuation <= 0 || mover == players[consoleplayer].camera)
|
||||
{
|
||||
basepriority = 200;
|
||||
basepriority = 40;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case CHAN_WEAPON:
|
||||
basepriority = 100;
|
||||
basepriority = 20;
|
||||
break;
|
||||
case CHAN_VOICE:
|
||||
basepriority = 75;
|
||||
basepriority = 10;
|
||||
break;
|
||||
default:
|
||||
case CHAN_BODY:
|
||||
basepriority = 50;
|
||||
basepriority = 0;
|
||||
break;
|
||||
case CHAN_ITEM:
|
||||
basepriority = 25;
|
||||
basepriority = -10;
|
||||
break;
|
||||
}
|
||||
if (attenuation == 1)
|
||||
basepriority += 50;
|
||||
basepriority = int(basepriority * attenuation);
|
||||
}
|
||||
|
||||
if (mover != NULL)
|
||||
{
|
||||
if (channel == CHAN_AUTO)
|
||||
if (mover != NULL && channel == CHAN_AUTO)
|
||||
{ // Select a channel that isn't already playing something.
|
||||
BYTE mask = mover->SoundChans;
|
||||
|
||||
|
@ -788,9 +759,8 @@ static void S_StartSound (fixed_t *pt, AActor *mover, int channel,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// If this actor is already playing something on the selected channel, stop it.
|
||||
if (mover->SoundChans & (1 << channel))
|
||||
if ((mover == NULL && channel != CHAN_AUTO) || (mover != NULL && mover->SoundChans & (1 << channel)))
|
||||
{
|
||||
for (chan = Channels; chan != NULL; chan = chan->NextChan)
|
||||
{
|
||||
|
@ -801,7 +771,6 @@ static void S_StartSound (fixed_t *pt, AActor *mover, int channel,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Vary the sfx pitches.
|
||||
if (sfx->PitchMask != 0)
|
||||
|
@ -830,7 +799,7 @@ static void S_StartSound (fixed_t *pt, AActor *mover, int channel,
|
|||
pt2[2] = z;
|
||||
CalcPosVel (pt2, mover, chanflags & CHAN_LISTENERZ, pos, vel);
|
||||
}
|
||||
chan = GSnd->StartSound3D (sfx, volume, pitch, looping, pos, vel, !(chanflags & CHAN_NOPAUSE));
|
||||
chan = GSnd->StartSound3D (sfx, volume, attenuation, pitch, basepriority, looping, pos, vel, !(chanflags & CHAN_NOPAUSE));
|
||||
if (chan != NULL)
|
||||
{
|
||||
chan->ConstZ = !!(chanflags & CHAN_LISTENERZ);
|
||||
|
@ -1047,6 +1016,7 @@ void S_StopAllChannels ()
|
|||
{
|
||||
GSnd->StopSound(Channels);
|
||||
}
|
||||
GSnd->UpdateSounds();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -54,14 +54,34 @@ struct sfxinfo_t
|
|||
WORD bUsed:1;
|
||||
WORD bSingular:1;
|
||||
WORD bTentative:1;
|
||||
WORD RolloffType:2;
|
||||
|
||||
WORD link;
|
||||
enum { NO_LINK = 0xffff };
|
||||
|
||||
float MinDistance;
|
||||
union { float MaxDistance, RolloffFactor; };
|
||||
};
|
||||
|
||||
// Rolloff types
|
||||
enum
|
||||
{
|
||||
ROLLOFF_Doom, // Linear rolloff with a logarithmic volume scale
|
||||
ROLLOFF_Linear, // Linear rolloff with a linear volume scale
|
||||
ROLLOFF_Log, // Logarithmic rolloff (standard hardware type)
|
||||
ROLLOFF_Custom // Lookup volume from SNDCURVE
|
||||
};
|
||||
|
||||
// the complete set of sound effects
|
||||
extern TArray<sfxinfo_t> S_sfx;
|
||||
|
||||
// Default rolloff information.
|
||||
extern int S_RolloffType;
|
||||
extern float S_MinDistance;
|
||||
extern float S_MaxDistanceOrRolloffFactor;
|
||||
extern BYTE *S_SoundCurve;
|
||||
extern int S_SoundCurveSize;
|
||||
|
||||
// Information about one playing sound.
|
||||
struct FSoundChan
|
||||
{
|
||||
|
@ -75,6 +95,7 @@ struct FSoundChan
|
|||
int SoundID; // Sound ID of playing sound
|
||||
int OrgID; // Sound ID of sound used to start this channel
|
||||
float Volume;
|
||||
float DistanceScale;
|
||||
BYTE EntChannel; // Actor's sound channel.
|
||||
bool Loop;
|
||||
bool Is3D;
|
||||
|
|
|
@ -94,8 +94,6 @@ static const char *Enum_NameForNum(const FEnumList *list, int num);
|
|||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
extern int MAX_SND_DIST;
|
||||
|
||||
EXTERN_CVAR (String, snd_output)
|
||||
EXTERN_CVAR (Float, snd_musicvolume)
|
||||
EXTERN_CVAR (Int, snd_buffersize)
|
||||
|
@ -116,10 +114,14 @@ CVAR (Bool, snd_dspnet, false, 0)
|
|||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
static const int S_CLIPPING_DIST = 1200;
|
||||
static const int S_CLOSE_DIST = 160;
|
||||
static const ReverbContainer *PrevEnvironment;
|
||||
|
||||
// The rolloff callback is called during FMOD::Sound::play, so we need this
|
||||
// global variable to contain the sound info during that time for the
|
||||
// callback.
|
||||
static sfxinfo_t *GSfxInfo;
|
||||
static float GDistScale;
|
||||
|
||||
// In the below lists, duplicate entries are for user selection. When
|
||||
// queried, only the first one for the particular value is shown.
|
||||
static const FEnumList OutputNames[] =
|
||||
|
@ -551,13 +553,13 @@ bool FMODSoundRenderer::Init()
|
|||
{
|
||||
initflags |= FMOD_INIT_ENABLE_DSPNET;
|
||||
}
|
||||
result = Sys->init(MAX_CHANNELS, initflags, 0);
|
||||
result = Sys->init(snd_channels + NUM_EXTRA_SOFTWARE_CHANNELS, initflags, 0);
|
||||
if (result == FMOD_ERR_OUTPUT_CREATEBUFFER)
|
||||
{ // The speaker mode selected isn't supported by this soundcard. Switch it back to stereo.
|
||||
result = Sys->setSpeakerMode(FMOD_SPEAKERMODE_STEREO);
|
||||
ERRCHECK(result);
|
||||
|
||||
result = Sys->init(MAX_CHANNELS, initflags, 0);
|
||||
result = Sys->init(snd_channels + NUM_EXTRA_SOFTWARE_CHANNELS, initflags, 0);
|
||||
ERRCHECK(result);
|
||||
}
|
||||
if (result != FMOD_OK)
|
||||
|
@ -580,21 +582,8 @@ bool FMODSoundRenderer::Init()
|
|||
|
||||
result = SPC_CreateCodec(Sys);
|
||||
|
||||
float rolloff_factor;
|
||||
|
||||
if (gameinfo.gametype == GAME_Doom || gameinfo.gametype == GAME_Strife)
|
||||
{
|
||||
rolloff_factor = 1.7f;
|
||||
}
|
||||
else if (gameinfo.gametype == GAME_Heretic)
|
||||
{
|
||||
rolloff_factor = 1.24f;
|
||||
}
|
||||
else
|
||||
{
|
||||
rolloff_factor = 0.96f;
|
||||
}
|
||||
Sys->set3DSettings(1.f, 100.f, rolloff_factor);
|
||||
Sys->set3DSettings(0.5f, 96.f, 1.f);
|
||||
Sys->set3DRolloffCallback(RolloffCallback);
|
||||
snd_sfxvolume.Callback ();
|
||||
return true;
|
||||
}
|
||||
|
@ -933,6 +922,7 @@ FSoundChan *FMODSoundRenderer::StartSound(sfxinfo_t *sfx, float vol, int pitch,
|
|||
|
||||
freq = PITCH(sfx->frequency, pitch);
|
||||
|
||||
GSfxInfo = sfx;
|
||||
result = Sys->playSound(FMOD_CHANNEL_FREE, (FMOD::Sound *)sfx->data, true, &chan);
|
||||
if (FMOD_OK == result)
|
||||
{
|
||||
|
@ -967,18 +957,40 @@ FSoundChan *FMODSoundRenderer::StartSound(sfxinfo_t *sfx, float vol, int pitch,
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FSoundChan *FMODSoundRenderer::StartSound3D(sfxinfo_t *sfx, float vol, int pitch,
|
||||
bool looping, float pos[3], float vel[3], bool pausable)
|
||||
FSoundChan *FMODSoundRenderer::StartSound3D(sfxinfo_t *sfx, float vol, float distscale,
|
||||
int pitch, int priority, bool looping, float pos[3], float vel[3], bool pausable)
|
||||
{
|
||||
int id = int(sfx - &S_sfx[0]);
|
||||
FMOD_RESULT result;
|
||||
FMOD_MODE mode;
|
||||
FMOD::Channel *chan;
|
||||
float freq;
|
||||
float def_freq, def_vol, def_pan;
|
||||
int def_priority;
|
||||
|
||||
freq = PITCH(sfx->frequency, pitch);
|
||||
|
||||
// Change the sound's default priority before playing it.
|
||||
if (FMOD_OK == ((FMOD::Sound *)sfx->data)->getDefaults(&def_freq, &def_vol, &def_pan, &def_priority))
|
||||
{
|
||||
((FMOD::Sound *)sfx->data)->setDefaults(def_freq, def_vol, def_pan, clamp(def_priority - priority, 1, 256));
|
||||
}
|
||||
else
|
||||
{
|
||||
def_priority = -1;
|
||||
}
|
||||
|
||||
// Play it.
|
||||
GSfxInfo = sfx;
|
||||
GDistScale = distscale;
|
||||
result = Sys->playSound(FMOD_CHANNEL_FREE, (FMOD::Sound *)sfx->data, true, &chan);
|
||||
|
||||
// Then set the priority back.
|
||||
if (def_priority >= 0)
|
||||
{
|
||||
((FMOD::Sound *)sfx->data)->setDefaults(def_freq, def_vol, def_pan, def_priority);
|
||||
}
|
||||
|
||||
if (FMOD_OK == result)
|
||||
{
|
||||
result = chan->getMode(&mode);
|
||||
|
@ -1013,7 +1025,9 @@ FSoundChan *FMODSoundRenderer::StartSound3D(sfxinfo_t *sfx, float vol, int pitch
|
|||
chan->setVolume(vol);
|
||||
chan->set3DAttributes((FMOD_VECTOR *)pos, (FMOD_VECTOR *)vel);
|
||||
chan->setPaused(false);
|
||||
return CommonChannelSetup(chan, true);
|
||||
FSoundChan *schan = CommonChannelSetup(chan, true);
|
||||
schan->DistanceScale = distscale;
|
||||
return schan;
|
||||
}
|
||||
|
||||
DPrintf ("Sound %s failed to play: %d\n", sfx->name.GetChars(), result);
|
||||
|
@ -1035,6 +1049,7 @@ FSoundChan *FMODSoundRenderer::CommonChannelSetup(FMOD::Channel *chan, bool is3d
|
|||
chan->setUserData(schan);
|
||||
chan->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, ChannelEndCallback, 0);
|
||||
schan->Is3D = is3d;
|
||||
GSfxInfo = NULL;
|
||||
return schan;
|
||||
}
|
||||
|
||||
|
@ -1051,33 +1066,8 @@ void FMODSoundRenderer::StopSound(FSoundChan *chan)
|
|||
|
||||
if (chan->SysChannel != NULL)
|
||||
{
|
||||
((FMOD::Channel *)chan->SysChannel)->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, 0, 0);
|
||||
((FMOD::Channel *)chan->SysChannel)->stop();
|
||||
}
|
||||
S_ReturnChannel(chan);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMODSoundRenderer :: ChannelEndCallback static
|
||||
//
|
||||
// Called when the channel finishes playing.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FMOD_RESULT F_CALLBACK FMODSoundRenderer::ChannelEndCallback
|
||||
(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type,
|
||||
int cmd, unsigned int data1, unsigned int data2)
|
||||
{
|
||||
assert(type == FMOD_CHANNEL_CALLBACKTYPE_END);
|
||||
FMOD::Channel *chan = (FMOD::Channel *)channel;
|
||||
FSoundChan *schan;
|
||||
|
||||
if (chan->getUserData((void **)&schan) == FMOD_OK && schan != NULL)
|
||||
{
|
||||
S_ReturnChannel(schan);
|
||||
}
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1305,8 +1295,24 @@ void FMODSoundRenderer::DoLoad(void **slot, sfxinfo_t *sfx)
|
|||
FMOD_MODE samplemode;
|
||||
FMOD_CREATESOUNDEXINFO exinfo = { sizeof(exinfo), };
|
||||
FMOD::Sound *sample;
|
||||
int rolloff;
|
||||
float mindist, maxdist;
|
||||
|
||||
samplemode = FMOD_3D | FMOD_OPENMEMORY | FMOD_SOFTWARE;
|
||||
|
||||
if (sfx->MaxDistance == 0)
|
||||
{
|
||||
mindist = S_MinDistance;
|
||||
maxdist = S_MaxDistanceOrRolloffFactor;
|
||||
rolloff = S_RolloffType;
|
||||
}
|
||||
else
|
||||
{
|
||||
mindist = sfx->MinDistance;
|
||||
maxdist = sfx->MaxDistance;
|
||||
rolloff = sfx->RolloffType;
|
||||
}
|
||||
|
||||
sfxdata = NULL;
|
||||
|
||||
errcount = 0;
|
||||
|
@ -1401,11 +1407,14 @@ void FMODSoundRenderer::DoLoad(void **slot, sfxinfo_t *sfx)
|
|||
break;
|
||||
}
|
||||
|
||||
if (sfx->data)
|
||||
if (sample != NULL)
|
||||
{
|
||||
// Match s_sound.cpp min distance.
|
||||
// Max distance is irrelevant.
|
||||
sample->set3DMinMaxDistance(float(S_CLOSE_DIST), 10000.f);
|
||||
if (rolloff == ROLLOFF_Log)
|
||||
{
|
||||
maxdist = 10000.f;
|
||||
}
|
||||
sample->set3DMinMaxDistance(mindist, maxdist);
|
||||
sample->setUserData(sfx);
|
||||
}
|
||||
|
||||
if (sfxdata != NULL)
|
||||
|
@ -1445,3 +1454,105 @@ void FMODSoundRenderer::getsfx(sfxinfo_t *sfx)
|
|||
}
|
||||
DoLoad(&sfx->data, sfx);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMODSoundRenderer :: ChannelEndCallback static
|
||||
//
|
||||
// Called when the channel finishes playing.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FMOD_RESULT F_CALLBACK FMODSoundRenderer::ChannelEndCallback
|
||||
(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type,
|
||||
int cmd, unsigned int data1, unsigned int data2)
|
||||
{
|
||||
assert(type == FMOD_CHANNEL_CALLBACKTYPE_END);
|
||||
FMOD::Channel *chan = (FMOD::Channel *)channel;
|
||||
FSoundChan *schan;
|
||||
|
||||
if (chan->getUserData((void **)&schan) == FMOD_OK && schan != NULL)
|
||||
{
|
||||
S_ReturnChannel(schan);
|
||||
}
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FMODSoundRenderer :: RolloffCallback static
|
||||
//
|
||||
// Calculates a volume for the sound based on distance.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
float F_CALLBACK FMODSoundRenderer::RolloffCallback(FMOD_CHANNEL *channel, float distance)
|
||||
{
|
||||
FMOD::Channel *chan = (FMOD::Channel *)channel;
|
||||
FSoundChan *schan;
|
||||
// Defaults for Doom.
|
||||
int type = ROLLOFF_Doom;
|
||||
sfxinfo_t *sfx;
|
||||
float min;
|
||||
float max;
|
||||
float factor;
|
||||
float volume;
|
||||
|
||||
type = S_RolloffType;
|
||||
factor = S_MaxDistanceOrRolloffFactor;
|
||||
min = S_MinDistance;
|
||||
max = S_MaxDistanceOrRolloffFactor;
|
||||
|
||||
if (GSfxInfo != NULL)
|
||||
{
|
||||
sfx = GSfxInfo;
|
||||
distance *= GDistScale;
|
||||
}
|
||||
else if (chan->getUserData((void **)&schan) == FMOD_OK && schan != NULL)
|
||||
{
|
||||
sfx = schan->SfxInfo;
|
||||
distance *= schan->DistanceScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (sfx == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sfx->MaxDistance == 0)
|
||||
{
|
||||
type = sfx->RolloffType;
|
||||
factor = sfx->RolloffFactor;
|
||||
}
|
||||
chan->get3DMinMaxDistance(&min, &max);
|
||||
|
||||
if (distance <= min)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (type == ROLLOFF_Log)
|
||||
{ // Logarithmic rolloff has no max distance where it goes silent.
|
||||
return min / (min + factor * (distance - min));
|
||||
}
|
||||
if (distance >= max)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
volume = (max - distance) / (max - min);
|
||||
if (type == ROLLOFF_Custom && S_SoundCurve != NULL)
|
||||
{
|
||||
volume = S_SoundCurve[int(S_SoundCurveSize * (1 - volume))] / 127.f;
|
||||
}
|
||||
if (type == ROLLOFF_Linear)
|
||||
{
|
||||
return volume;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (powf(10.f, volume) - 1.f) / 9.f;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
|
||||
// Starts a sound.
|
||||
FSoundChan *StartSound (sfxinfo_t *sfx, float vol, int pitch, bool looping, bool pauseable);
|
||||
FSoundChan *StartSound3D (sfxinfo_t *sfx, float vol, int pitch, bool looping, float pos[3], float vel[3], bool pauseable);
|
||||
FSoundChan *StartSound3D (sfxinfo_t *sfx, float vol, float distscale, int pitch, int priority, bool looping, float pos[3], float vel[3], bool pauseable);
|
||||
|
||||
// Stops a sound channel.
|
||||
void StopSound (FSoundChan *chan);
|
||||
|
@ -56,6 +56,7 @@ private:
|
|||
|
||||
static FMOD_RESULT F_CALLBACK ChannelEndCallback
|
||||
(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type, int cmd, unsigned int data1, unsigned int data2);
|
||||
static float F_CALLBACK RolloffCallback(FMOD_CHANNEL *channel, float distance);
|
||||
|
||||
FSoundChan *CommonChannelSetup(FMOD::Channel *chan, bool is3d);
|
||||
void DoLoad (void **slot, sfxinfo_t *sfx);
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
|
||||
// Starts a sound.
|
||||
virtual FSoundChan *StartSound (sfxinfo_t *sfx, float vol, int pitch, bool looping, bool pauseable) = 0;
|
||||
virtual FSoundChan *StartSound3D (sfxinfo_t *sfx, float vol, int pitch, bool looping, float pos[3], float vel[3], bool pauseable) = 0;
|
||||
virtual FSoundChan *StartSound3D (sfxinfo_t *sfx, float vol, float distscale, int pitch, int priority, bool looping, float pos[3], float vel[3], bool pauseable) = 0;
|
||||
|
||||
// Stops a sound channel.
|
||||
virtual void StopSound (FSoundChan *chan) = 0;
|
||||
|
|
|
@ -46,6 +46,9 @@ world/quake dsquake
|
|||
misc/freeze icedth1
|
||||
misc/icebreak icebrk1a
|
||||
|
||||
// The released source code used a min distance of 160. Why?
|
||||
// Retail Doom and Strife use 200.
|
||||
$rolloff * 200 1200
|
||||
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
|
@ -55,6 +58,7 @@ misc/icebreak icebrk1a
|
|||
|
||||
$ifdoom
|
||||
|
||||
|
||||
// BOOM has pitch shifting equivalent to a range of 4. I never got to hear
|
||||
// Doom when it used pitch shifting, so I don't know if this is correct or not.
|
||||
$pitchshiftrange 4
|
||||
|
@ -483,6 +487,8 @@ $endif // ifdoom
|
|||
|
||||
$ifheretic
|
||||
|
||||
$rolloff * custom 0 1600
|
||||
|
||||
$pitchshiftrange 2
|
||||
|
||||
$playersound player male *wimpydeath plrwdth
|
||||
|
@ -731,6 +737,8 @@ $endif // ifheretic
|
|||
|
||||
$ifhexen
|
||||
|
||||
$rolloff * custom 0 2025
|
||||
|
||||
$pitchshiftrange 3
|
||||
|
||||
$random PlayerFighterExtremeDeathPicker { PlayerFighterExtreme1Death
|
||||
|
|
Loading…
Reference in a new issue