- 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:
Randy Heit 2008-05-15 04:51:57 +00:00
parent ff4446a3a0
commit 5a066788b5
8 changed files with 139 additions and 31 deletions

View file

@ -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.

View file

@ -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} },

View file

@ -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);
}
}
}
} }
//========================================================================== //==========================================================================

View file

@ -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;

View file

@ -208,10 +208,6 @@ void SoundRenderer::DrawWaveDebug(int mode)
{ {
} }
void SoundRenderer::ResetEnvironment ()
{
}
SoundStream::~SoundStream () SoundStream::~SoundStream ()
{ {
} }

View file

@ -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);
}; };

View file

@ -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 */

View file

@ -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)
{ {