mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-18 23:52:02 +00:00
- Revised underwater effect now uses a lowpass filter in combination with an
optional freeverb unit. - Removed ResetEnvironment hack, since with software reverb, losing the existing reverb when focus is lost isn't a problem. - Commented out the TiMidity FIXME messages. SVN r973 (trunk)
This commit is contained in:
parent
ff4446a3a0
commit
5a066788b5
8 changed files with 139 additions and 31 deletions
|
@ -1,4 +1,9 @@
|
||||||
May 14, 2008
|
May 14, 2008
|
||||||
|
- Revised underwater effect now uses a lowpass filter in combination with an
|
||||||
|
optional freeverb unit.
|
||||||
|
- Removed ResetEnvironment hack, since with software reverb, losing the
|
||||||
|
existing reverb when focus is lost isn't a problem.
|
||||||
|
- Commented out the TiMidity FIXME messages.
|
||||||
- Fixed: FBarShader::GetColumn() passed incorrect information to the software
|
- Fixed: FBarShader::GetColumn() passed incorrect information to the software
|
||||||
renderer for horizontal bars.
|
renderer for horizontal bars.
|
||||||
|
|
||||||
|
|
|
@ -1142,6 +1142,7 @@ EXTERN_CVAR (Int, snd_buffercount)
|
||||||
EXTERN_CVAR (Int, snd_samplerate)
|
EXTERN_CVAR (Int, snd_samplerate)
|
||||||
EXTERN_CVAR (Bool, snd_hrtf)
|
EXTERN_CVAR (Bool, snd_hrtf)
|
||||||
EXTERN_CVAR (Bool, snd_waterreverb)
|
EXTERN_CVAR (Bool, snd_waterreverb)
|
||||||
|
EXTERN_CVAR (Float, snd_waterlp)
|
||||||
EXTERN_CVAR (Int, snd_mididevice)
|
EXTERN_CVAR (Int, snd_mididevice)
|
||||||
|
|
||||||
static void MakeSoundChanges ();
|
static void MakeSoundChanges ();
|
||||||
|
@ -1243,6 +1244,7 @@ static menuitem_t SoundItems[] =
|
||||||
{ discrete, "MIDI device", {&snd_mididevice}, {0.0}, {0.0}, {0.0}, {NULL} },
|
{ discrete, "MIDI device", {&snd_mididevice}, {0.0}, {0.0}, {0.0}, {NULL} },
|
||||||
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
|
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
|
||||||
{ discrete, "Underwater reverb", {&snd_waterreverb}, {2.0}, {0.0}, {0.0}, {OnOff} },
|
{ discrete, "Underwater reverb", {&snd_waterreverb}, {2.0}, {0.0}, {0.0}, {OnOff} },
|
||||||
|
{ slider, "Underwater cutoff", {&snd_waterlp}, {0.0}, {2000.0},{50.0}, {NULL} },
|
||||||
{ discrete, "Randomize pitches", {&snd_pitched}, {2.0}, {0.0}, {0.0}, {OnOff} },
|
{ discrete, "Randomize pitches", {&snd_pitched}, {2.0}, {0.0}, {0.0}, {OnOff} },
|
||||||
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
|
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
|
||||||
{ more, "Restart sound", {NULL}, {0.0}, {0.0}, {0.0}, {(value_t *)MakeSoundChanges} },
|
{ more, "Restart sound", {NULL}, {0.0}, {0.0}, {0.0}, {(value_t *)MakeSoundChanges} },
|
||||||
|
|
|
@ -119,6 +119,20 @@ CVAR (String, snd_output_format, "PCM-16", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
CVAR (String, snd_midipatchset, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR (String, snd_midipatchset, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
CVAR (Bool, snd_profile, false, 0)
|
CVAR (Bool, snd_profile, false, 0)
|
||||||
|
|
||||||
|
// Underwater low-pass filter cutoff frequency. Set to 0 to disable the filter.
|
||||||
|
CUSTOM_CVAR (Float, snd_waterlp, 250, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
|
{
|
||||||
|
// Clamp to the DSP unit's limits.
|
||||||
|
if (*self < 10 && *self != 0)
|
||||||
|
{
|
||||||
|
self = 10;
|
||||||
|
}
|
||||||
|
else if (*self > 22000)
|
||||||
|
{
|
||||||
|
self = 22000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
static const ReverbContainer *PrevEnvironment;
|
static const ReverbContainer *PrevEnvironment;
|
||||||
|
@ -569,6 +583,9 @@ bool FMODSoundRenderer::Init()
|
||||||
MusicGroup = NULL;
|
MusicGroup = NULL;
|
||||||
SfxGroup = NULL;
|
SfxGroup = NULL;
|
||||||
PausableSfx = NULL;
|
PausableSfx = NULL;
|
||||||
|
SfxConnection = NULL;
|
||||||
|
WaterLP = NULL;
|
||||||
|
WaterReverb = NULL;
|
||||||
PrevEnvironment = DefaultEnvironments[0];
|
PrevEnvironment = DefaultEnvironments[0];
|
||||||
DSPClockLo = 0;
|
DSPClockLo = 0;
|
||||||
DSPClockHi = 0;
|
DSPClockHi = 0;
|
||||||
|
@ -830,9 +847,55 @@ bool FMODSoundRenderer::Init()
|
||||||
result = SfxGroup->addGroup(PausableSfx);
|
result = SfxGroup->addGroup(PausableSfx);
|
||||||
if (result != FMOD_OK)
|
if (result != FMOD_OK)
|
||||||
{
|
{
|
||||||
Printf(TEXTCOLOR_BLUE" Could not create attach pausable sfx to sfx channel group. (Error %d)\n", result);
|
Printf(TEXTCOLOR_BLUE" Could not attach pausable sfx to sfx channel group. (Error %d)\n", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create DSP units for underwater effect
|
||||||
|
result = Sys->createDSPByType(FMOD_DSP_TYPE_LOWPASS, &WaterLP);
|
||||||
|
if (result != FMOD_OK)
|
||||||
|
{
|
||||||
|
Printf(TEXTCOLOR_BLUE" Could not create underwater lowpass unit. (Error %d)\n", result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = Sys->createDSPByType(FMOD_DSP_TYPE_REVERB, &WaterReverb);
|
||||||
|
if (result != FMOD_OK)
|
||||||
|
{
|
||||||
|
Printf(TEXTCOLOR_BLUE" Could not create underwater reverb unit. (Error %d)\n", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect underwater DSP unit between PausableSFX and SFX groups, while
|
||||||
|
// retaining the connection established by SfxGroup->addGroup().
|
||||||
|
if (WaterLP != NULL)
|
||||||
|
{
|
||||||
|
FMOD::DSP *sfx_head, *pausable_head;
|
||||||
|
|
||||||
|
result = SfxGroup->getDSPHead(&sfx_head);
|
||||||
|
result = sfx_head->getInput(0, &pausable_head, &SfxConnection);
|
||||||
|
|
||||||
|
result = WaterLP->addInput(pausable_head, NULL);
|
||||||
|
WaterLP->setActive(false);
|
||||||
|
WaterLP->setParameter(FMOD_DSP_LOWPASS_CUTOFF, snd_waterlp);
|
||||||
|
WaterLP->setParameter(FMOD_DSP_LOWPASS_RESONANCE, 2);
|
||||||
|
if (WaterReverb != NULL)
|
||||||
|
{
|
||||||
|
FMOD::DSPConnection *dry;
|
||||||
|
result = WaterReverb->addInput(pausable_head, &dry);
|
||||||
|
result = dry->setMix(0.1f);
|
||||||
|
result = WaterReverb->addInput(WaterLP, NULL);
|
||||||
|
result = sfx_head->addInput(WaterReverb, NULL);
|
||||||
|
WaterReverb->setParameter(FMOD_DSP_REVERB_ROOMSIZE, 0.001f);
|
||||||
|
WaterReverb->setParameter(FMOD_DSP_REVERB_DAMP, 0.2f);
|
||||||
|
WaterReverb->setActive(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = sfx_head->addInput(WaterLP, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LastWaterLP = snd_waterlp;
|
||||||
|
|
||||||
result = SPC_CreateCodec(Sys);
|
result = SPC_CreateCodec(Sys);
|
||||||
if (result != FMOD_OK)
|
if (result != FMOD_OK)
|
||||||
{
|
{
|
||||||
|
@ -878,6 +941,16 @@ void FMODSoundRenderer::Shutdown()
|
||||||
SfxGroup->release();
|
SfxGroup->release();
|
||||||
SfxGroup = NULL;
|
SfxGroup = NULL;
|
||||||
}
|
}
|
||||||
|
if (WaterLP != NULL)
|
||||||
|
{
|
||||||
|
WaterLP->release();
|
||||||
|
WaterLP = NULL;
|
||||||
|
}
|
||||||
|
if (WaterReverb != NULL)
|
||||||
|
{
|
||||||
|
WaterReverb->release();
|
||||||
|
WaterReverb = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Free all loaded samples
|
// Free all loaded samples
|
||||||
for (i = 0; i < S_sfx.Size(); i++)
|
for (i = 0; i < S_sfx.Size(); i++)
|
||||||
|
@ -1490,17 +1563,6 @@ void FMODSoundRenderer::UpdateSoundParams3D(FSoundChan *chan, float pos[3], floa
|
||||||
fchan->set3DAttributes((FMOD_VECTOR *)pos, (FMOD_VECTOR *)vel);
|
fchan->set3DAttributes((FMOD_VECTOR *)pos, (FMOD_VECTOR *)vel);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// FMODSoundRenderer :: ResetEnvironment
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void FMODSoundRenderer::ResetEnvironment()
|
|
||||||
{
|
|
||||||
PrevEnvironment = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FMODSoundRenderer :: UpdateListener
|
// FMODSoundRenderer :: UpdateListener
|
||||||
|
@ -1549,26 +1611,72 @@ void FMODSoundRenderer::UpdateListener()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
underwater = (listener->waterlevel == 3 && snd_waterreverb);
|
underwater = (listener->waterlevel == 3 && snd_waterlp);
|
||||||
assert (zones != NULL);
|
assert (zones != NULL);
|
||||||
env = zones[listener->Sector->ZoneNumber].Environment;
|
env = zones[listener->Sector->ZoneNumber].Environment;
|
||||||
if (env == NULL)
|
if (env == NULL)
|
||||||
{
|
{
|
||||||
env = DefaultEnvironments[0];
|
env = DefaultEnvironments[0];
|
||||||
}
|
}
|
||||||
if (env == DefaultEnvironments[0] && underwater)
|
/* if (env == DefaultEnvironments[0] && underwater)
|
||||||
{
|
{
|
||||||
env = DefaultEnvironments[22];
|
env = DefaultEnvironments[22];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
if (env != PrevEnvironment || env->Modified)
|
if (env != PrevEnvironment || env->Modified)
|
||||||
{
|
{
|
||||||
DPrintf ("Reverb Environment %s\n", env->Name);
|
DPrintf ("Reverb Environment %s\n", env->Name);
|
||||||
const_cast<ReverbContainer*>(env)->Modified = false;
|
const_cast<ReverbContainer*>(env)->Modified = false;
|
||||||
Sys->setReverbProperties((FMOD_REVERB_PROPERTIES *)(&env->Properties));
|
Sys->setReverbProperties((FMOD_REVERB_PROPERTIES *)(&env->Properties));
|
||||||
PausableSfx->setPitch(underwater ? 0.64171f : 1);
|
|
||||||
PrevEnvironment = env;
|
PrevEnvironment = env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (underwater)
|
||||||
|
{
|
||||||
|
//PausableSfx->setPitch(0.64171f); // This appears to be what Duke 3D uses
|
||||||
|
PausableSfx->setPitch(0.7937005f); // Approx. 4 semitones lower; what Nash suggesetd
|
||||||
|
if (WaterLP != NULL)
|
||||||
|
{
|
||||||
|
if (LastWaterLP != snd_waterlp)
|
||||||
|
{
|
||||||
|
LastWaterLP = snd_waterlp;
|
||||||
|
WaterLP->setParameter(FMOD_DSP_LOWPASS_CUTOFF, snd_waterlp);
|
||||||
|
}
|
||||||
|
WaterLP->setActive(true);
|
||||||
|
if (WaterReverb != NULL && snd_waterreverb)
|
||||||
|
{
|
||||||
|
WaterReverb->setActive(true);
|
||||||
|
WaterReverb->setBypass(false);
|
||||||
|
SfxConnection->setMix(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Let some of the original mix through so that high frequencies are
|
||||||
|
// not completely lost. The reverb unit has its own connection and
|
||||||
|
// preserves dry sounds itself if used.
|
||||||
|
SfxConnection->setMix(0.1f);
|
||||||
|
if (WaterReverb != NULL)
|
||||||
|
{
|
||||||
|
WaterReverb->setActive(true);
|
||||||
|
WaterReverb->setBypass(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PausableSfx->setPitch(1);
|
||||||
|
if (WaterLP != NULL)
|
||||||
|
{
|
||||||
|
SfxConnection->setMix(1);
|
||||||
|
WaterLP->setActive(false);
|
||||||
|
if (WaterReverb != NULL)
|
||||||
|
{
|
||||||
|
WaterReverb->setActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -47,7 +47,6 @@ public:
|
||||||
void PrintStatus ();
|
void PrintStatus ();
|
||||||
void PrintDriversList ();
|
void PrintDriversList ();
|
||||||
FString GatherStats ();
|
FString GatherStats ();
|
||||||
void ResetEnvironment ();
|
|
||||||
|
|
||||||
void DrawWaveDebug(int mode);
|
void DrawWaveDebug(int mode);
|
||||||
|
|
||||||
|
@ -85,6 +84,9 @@ private:
|
||||||
FMOD::System *Sys;
|
FMOD::System *Sys;
|
||||||
FMOD::ChannelGroup *SfxGroup, *PausableSfx;
|
FMOD::ChannelGroup *SfxGroup, *PausableSfx;
|
||||||
FMOD::ChannelGroup *MusicGroup;
|
FMOD::ChannelGroup *MusicGroup;
|
||||||
|
FMOD::DSP *WaterLP, *WaterReverb;
|
||||||
|
FMOD::DSPConnection *SfxConnection;
|
||||||
|
float LastWaterLP;
|
||||||
|
|
||||||
// Just for snd_status display
|
// Just for snd_status display
|
||||||
int Driver_MinFrequency;
|
int Driver_MinFrequency;
|
||||||
|
|
|
@ -208,10 +208,6 @@ void SoundRenderer::DrawWaveDebug(int mode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundRenderer::ResetEnvironment ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SoundStream::~SoundStream ()
|
SoundStream::~SoundStream ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,6 @@ public:
|
||||||
virtual void PrintStatus () = 0;
|
virtual void PrintStatus () = 0;
|
||||||
virtual void PrintDriversList () = 0;
|
virtual void PrintDriversList () = 0;
|
||||||
virtual FString GatherStats ();
|
virtual FString GatherStats ();
|
||||||
virtual void ResetEnvironment ();
|
|
||||||
|
|
||||||
virtual void DrawWaveDebug(int mode);
|
virtual void DrawWaveDebug(int mode);
|
||||||
};
|
};
|
||||||
|
|
|
@ -138,7 +138,7 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
* before TiMidity kills the note. This may be useful to implement
|
* before TiMidity kills the note. This may be useful to implement
|
||||||
* later, but I don't see any urgent need for it.
|
* later, but I don't see any urgent need for it.
|
||||||
*/
|
*/
|
||||||
Printf("FIXME: Implement \"timeout\" in TiMidity config.\n");
|
//Printf("FIXME: Implement \"timeout\" in TiMidity config.\n");
|
||||||
}
|
}
|
||||||
else if (!strcmp(w[0], "copydrumset") /* "copydrumset" drumset */
|
else if (!strcmp(w[0], "copydrumset") /* "copydrumset" drumset */
|
||||||
|| !strcmp(w[0], "copybank")) /* "copybank" bank */
|
|| !strcmp(w[0], "copybank")) /* "copybank" bank */
|
||||||
|
@ -148,7 +148,7 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
* the current drumset or bank. May be useful later, but not a
|
* the current drumset or bank. May be useful later, but not a
|
||||||
* high priority.
|
* high priority.
|
||||||
*/
|
*/
|
||||||
Printf("FIXME: Implement \"%s\" in TiMidity config.\n", w[0]);
|
//Printf("FIXME: Implement \"%s\" in TiMidity config.\n", w[0]);
|
||||||
}
|
}
|
||||||
else if (!strcmp(w[0], "undef")) /* "undef" progno */
|
else if (!strcmp(w[0], "undef")) /* "undef" progno */
|
||||||
{
|
{
|
||||||
|
@ -156,7 +156,7 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
* Undefines the tone "progno" of the current tone bank (or
|
* Undefines the tone "progno" of the current tone bank (or
|
||||||
* drum set?). Not a high priority.
|
* drum set?). Not a high priority.
|
||||||
*/
|
*/
|
||||||
Printf("FIXME: Implement \"undef\" in TiMidity config.\n");
|
//Printf("FIXME: Implement \"undef\" in TiMidity config.\n");
|
||||||
}
|
}
|
||||||
else if (!strcmp(w[0], "altassign")) /* "altassign" prog1 prog2 ... */
|
else if (!strcmp(w[0], "altassign")) /* "altassign" prog1 prog2 ... */
|
||||||
{
|
{
|
||||||
|
@ -164,7 +164,7 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
* Sets the alternate assign for drum set. Whatever that's
|
* Sets the alternate assign for drum set. Whatever that's
|
||||||
* supposed to mean.
|
* supposed to mean.
|
||||||
*/
|
*/
|
||||||
Printf("FIXME: Implement \"altassign\" in TiMidity config.\n");
|
//Printf("FIXME: Implement \"altassign\" in TiMidity config.\n");
|
||||||
}
|
}
|
||||||
else if (!strcmp(w[0], "soundfont"))
|
else if (!strcmp(w[0], "soundfont"))
|
||||||
{
|
{
|
||||||
|
@ -261,7 +261,7 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
* apparently it sets some sort of base offset for tone numbers.
|
* apparently it sets some sort of base offset for tone numbers.
|
||||||
* Why anyone would want to do this is beyond me.
|
* Why anyone would want to do this is beyond me.
|
||||||
*/
|
*/
|
||||||
Printf("FIXME: Implement \"progbase\" in TiMidity config.\n");
|
//Printf("FIXME: Implement \"progbase\" in TiMidity config.\n");
|
||||||
}
|
}
|
||||||
else if (!strcmp(w[0], "map")) /* "map" name set1 elem1 set2 elem2 */
|
else if (!strcmp(w[0], "map")) /* "map" name set1 elem1 set2 elem2 */
|
||||||
{
|
{
|
||||||
|
@ -271,7 +271,7 @@ static int read_config_file(const char *name, bool ismain)
|
||||||
* documentation whatsoever for it, but it looks like it's used
|
* documentation whatsoever for it, but it looks like it's used
|
||||||
* for remapping one instrument to another somehow.
|
* for remapping one instrument to another somehow.
|
||||||
*/
|
*/
|
||||||
Printf("FIXME: Implement \"map\" in TiMidity config.\n");
|
//Printf("FIXME: Implement \"map\" in TiMidity config.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Standard TiMidity config */
|
/* Standard TiMidity config */
|
||||||
|
|
|
@ -737,10 +737,6 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
if (wParam)
|
if (wParam)
|
||||||
{
|
{
|
||||||
SetPriorityClass (GetCurrentProcess (), INGAME_PRIORITY_CLASS);
|
SetPriorityClass (GetCurrentProcess (), INGAME_PRIORITY_CLASS);
|
||||||
if (GSnd != NULL)
|
|
||||||
{
|
|
||||||
GSnd->ResetEnvironment();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (!noidle && !netgame)
|
else if (!noidle && !netgame)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue